17
17
package console
18
18
19
19
import (
20
- "fmt"
21
20
"os"
22
21
23
22
"github.com/pkg/errors"
@@ -29,90 +28,55 @@ var (
29
28
ErrNotImplemented = errors .New ("not implemented" )
30
29
)
31
30
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
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
50
44
} else {
51
- windows .SetConsoleMode (m .out , m .outMode )
45
+ windows .SetConsoleMode (m .h , m .mode )
52
46
}
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 )
66
47
}
67
48
}
68
49
69
50
type master struct {
70
- in windows.Handle
71
- inMode uint32
72
-
73
- out windows.Handle
74
- outMode uint32
75
-
76
- err windows.Handle
77
- errMode uint32
51
+ h windows.Handle
52
+ mode uint32
53
+ f * os.File
78
54
}
79
55
80
56
func (m * master ) SetRaw () error {
81
- if err := makeInputRaw (m .in , m .inMode ); err != nil {
82
- return err
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 )
83
66
}
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
-
93
67
return nil
94
68
}
95
69
96
70
func (m * master ) Reset () error {
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
- }
71
+ if err := windows .SetConsoleMode (m .h , m .mode ); err != nil {
72
+ return errors .Wrap (err , "unable to restore console mode" )
108
73
}
109
-
110
74
return nil
111
75
}
112
76
113
77
func (m * master ) Size () (WinSize , error ) {
114
78
var info windows.ConsoleScreenBufferInfo
115
- err := windows .GetConsoleScreenBufferInfo (m .out , & info )
79
+ err := windows .GetConsoleScreenBufferInfo (m .h , & info )
116
80
if err != nil {
117
81
return WinSize {}, errors .Wrap (err , "unable to get console info" )
118
82
}
@@ -134,11 +98,11 @@ func (m *master) ResizeFrom(c Console) error {
134
98
}
135
99
136
100
func (m * master ) DisableEcho () error {
137
- mode := m .inMode &^ windows .ENABLE_ECHO_INPUT
101
+ mode := m .mode &^ windows .ENABLE_ECHO_INPUT
138
102
mode |= windows .ENABLE_PROCESSED_INPUT
139
103
mode |= windows .ENABLE_LINE_INPUT
140
104
141
- if err := windows .SetConsoleMode (m .in , mode ); err != nil {
105
+ if err := windows .SetConsoleMode (m .h , mode ); err != nil {
142
106
return errors .Wrap (err , "unable to set console to disable echo" )
143
107
}
144
108
@@ -150,15 +114,15 @@ func (m *master) Close() error {
150
114
}
151
115
152
116
func (m * master ) Read (b []byte ) (int , error ) {
153
- panic ( "not implemented on windows" )
117
+ return m . f . Read ( b )
154
118
}
155
119
156
120
func (m * master ) Write (b []byte ) (int , error ) {
157
- panic ( "not implemented on windows" )
121
+ return m . f . Write ( b )
158
122
}
159
123
160
124
func (m * master ) Fd () uintptr {
161
- return uintptr (m .in )
125
+ return uintptr (m .h )
162
126
}
163
127
164
128
// on windows, console can only be made from os.Std{in,out,err}, hence there
@@ -210,7 +174,7 @@ func newMaster(f *os.File) (Console, error) {
210
174
if f != os .Stdin && f != os .Stdout && f != os .Stderr {
211
175
return nil , errors .New ("creating a console from a file is not supported on windows" )
212
176
}
213
- m := & master {}
214
- m .initStdios ()
177
+ m := & master {f : f }
178
+ m .init ()
215
179
return m , nil
216
180
}
0 commit comments