17
17
package console
18
18
19
19
import (
20
+ "fmt"
20
21
"os"
21
22
22
23
"github.com/pkg/errors"
@@ -28,55 +29,90 @@ var (
28
29
ErrNotImplemented = errors .New ("not implemented" )
29
30
)
30
31
31
- func (m * master ) init () {
32
- m .h = windows .Handle (m .f .Fd ())
33
- if err := windows .GetConsoleMode (m .h , & m .mode ); err == nil {
34
- if m .f == os .Stdin {
35
- // Validate that windows.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
36
- if err = windows .SetConsoleMode (m .h , m .mode | windows .ENABLE_VIRTUAL_TERMINAL_INPUT ); err == nil {
37
- vtInputSupported = true
38
- }
39
- // Unconditionally set the console mode back even on failure because SetConsoleMode
40
- // remembers invalid bits on input handles.
41
- windows .SetConsoleMode (m .h , m .mode )
42
- } else if err := windows .SetConsoleMode (m .h , m .mode | windows .ENABLE_VIRTUAL_TERMINAL_PROCESSING ); err == nil {
43
- m .mode |= windows .ENABLE_VIRTUAL_TERMINAL_PROCESSING
32
+ func (m * master ) initStdios () {
33
+ m .in = windows .Handle (os .Stdin .Fd ())
34
+ if err := windows .GetConsoleMode (m .in , & m .inMode ); err == nil {
35
+ // Validate that windows.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
36
+ if err = windows .SetConsoleMode (m .in , m .inMode | windows .ENABLE_VIRTUAL_TERMINAL_INPUT ); err == nil {
37
+ vtInputSupported = true
38
+ }
39
+ // Unconditionally set the console mode back even on failure because SetConsoleMode
40
+ // remembers invalid bits on input handles.
41
+ windows .SetConsoleMode (m .in , m .inMode )
42
+ } else {
43
+ fmt .Printf ("failed to get console mode for stdin: %v\n " , err )
44
+ }
45
+
46
+ m .out = windows .Handle (os .Stdout .Fd ())
47
+ if err := windows .GetConsoleMode (m .out , & m .outMode ); err == nil {
48
+ if err := windows .SetConsoleMode (m .out , m .outMode | windows .ENABLE_VIRTUAL_TERMINAL_PROCESSING ); err == nil {
49
+ m .outMode |= windows .ENABLE_VIRTUAL_TERMINAL_PROCESSING
44
50
} else {
45
- windows .SetConsoleMode (m .h , m .mode )
51
+ windows .SetConsoleMode (m .out , m .outMode )
46
52
}
53
+ } else {
54
+ fmt .Printf ("failed to get console mode for stdout: %v\n " , err )
55
+ }
56
+
57
+ m .err = windows .Handle (os .Stderr .Fd ())
58
+ if err := windows .GetConsoleMode (m .err , & m .errMode ); err == nil {
59
+ if err := windows .SetConsoleMode (m .err , m .errMode | windows .ENABLE_VIRTUAL_TERMINAL_PROCESSING ); err == nil {
60
+ m .errMode |= windows .ENABLE_VIRTUAL_TERMINAL_PROCESSING
61
+ } else {
62
+ windows .SetConsoleMode (m .err , m .errMode )
63
+ }
64
+ } else {
65
+ fmt .Printf ("failed to get console mode for stderr: %v\n " , err )
47
66
}
48
67
}
49
68
50
69
type master struct {
51
- h windows.Handle
52
- mode uint32
53
- f * os.File
70
+ in windows.Handle
71
+ inMode uint32
72
+
73
+ out windows.Handle
74
+ outMode uint32
75
+
76
+ err windows.Handle
77
+ errMode uint32
54
78
}
55
79
56
80
func (m * master ) SetRaw () error {
57
- if m .f == os .Stdin {
58
- if err := makeInputRaw (m .h , m .mode ); err != nil {
59
- return err
60
- }
61
- } else {
62
- // Set StdOut and StdErr to raw mode, we ignore failures since
63
- // windows.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this version of
64
- // Windows.
65
- windows .SetConsoleMode (m .h , m .mode | windows .DISABLE_NEWLINE_AUTO_RETURN )
81
+ if err := makeInputRaw (m .in , m .inMode ); err != nil {
82
+ return err
66
83
}
84
+
85
+ // Set StdOut and StdErr to raw mode, we ignore failures since
86
+ // windows.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this version of
87
+ // Windows.
88
+
89
+ windows .SetConsoleMode (m .out , m .outMode | windows .DISABLE_NEWLINE_AUTO_RETURN )
90
+
91
+ windows .SetConsoleMode (m .err , m .errMode | windows .DISABLE_NEWLINE_AUTO_RETURN )
92
+
67
93
return nil
68
94
}
69
95
70
96
func (m * master ) Reset () error {
71
- if err := windows .SetConsoleMode (m .h , m .mode ); err != nil {
72
- return errors .Wrap (err , "unable to restore console mode" )
97
+ for _ , s := range []struct {
98
+ fd windows.Handle
99
+ mode uint32
100
+ }{
101
+ {m .in , m .inMode },
102
+ {m .out , m .outMode },
103
+ {m .err , m .errMode },
104
+ } {
105
+ if err := windows .SetConsoleMode (s .fd , s .mode ); err != nil {
106
+ return errors .Wrap (err , "unable to restore console mode" )
107
+ }
73
108
}
109
+
74
110
return nil
75
111
}
76
112
77
113
func (m * master ) Size () (WinSize , error ) {
78
114
var info windows.ConsoleScreenBufferInfo
79
- err := windows .GetConsoleScreenBufferInfo (m .h , & info )
115
+ err := windows .GetConsoleScreenBufferInfo (m .out , & info )
80
116
if err != nil {
81
117
return WinSize {}, errors .Wrap (err , "unable to get console info" )
82
118
}
@@ -98,11 +134,11 @@ func (m *master) ResizeFrom(c Console) error {
98
134
}
99
135
100
136
func (m * master ) DisableEcho () error {
101
- mode := m .mode &^ windows .ENABLE_ECHO_INPUT
137
+ mode := m .inMode &^ windows .ENABLE_ECHO_INPUT
102
138
mode |= windows .ENABLE_PROCESSED_INPUT
103
139
mode |= windows .ENABLE_LINE_INPUT
104
140
105
- if err := windows .SetConsoleMode (m .h , mode ); err != nil {
141
+ if err := windows .SetConsoleMode (m .in , mode ); err != nil {
106
142
return errors .Wrap (err , "unable to set console to disable echo" )
107
143
}
108
144
@@ -114,15 +150,15 @@ func (m *master) Close() error {
114
150
}
115
151
116
152
func (m * master ) Read (b []byte ) (int , error ) {
117
- return m . f .Read (b )
153
+ return os . Stdin .Read (b )
118
154
}
119
155
120
156
func (m * master ) Write (b []byte ) (int , error ) {
121
- return m . f .Write (b )
157
+ return os . Stdout .Write (b )
122
158
}
123
159
124
160
func (m * master ) Fd () uintptr {
125
- return uintptr (m .h )
161
+ return uintptr (m .in )
126
162
}
127
163
128
164
// on windows, console can only be made from os.Std{in,out,err}, hence there
@@ -174,7 +210,7 @@ func newMaster(f *os.File) (Console, error) {
174
210
if f != os .Stdin && f != os .Stdout && f != os .Stderr {
175
211
return nil , errors .New ("creating a console from a file is not supported on windows" )
176
212
}
177
- m := & master {f : f }
178
- m .init ()
213
+ m := & master {}
214
+ m .initStdios ()
179
215
return m , nil
180
216
}
0 commit comments