Codebase list golang-github-moby-term / 374642f
term_windows: use golang.org/x/sys/windows The parts of github.com/Azure/go-ansiterm/winterm that were used is now provided by golang.org/x/sys/windows, so switch to that package, as it's more actively maintained. Signed-off-by: Sebastiaan van Stijn <github@gone.nl> Sebastiaan van Stijn 4 years ago
1 changed file(s) with 52 addition(s) and 45 deletion(s). Raw diff Collapse all Expand all
33 "io"
44 "os"
55 "os/signal"
6 "syscall" // used for STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE
7
8 "github.com/Azure/go-ansiterm/winterm"
6
97 windowsconsole "github.com/moby/term/windows"
8 "golang.org/x/sys/windows"
109 )
1110
1211 // State holds the console mode for the terminal.
2726 func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
2827 // Turn on VT handling on all std handles, if possible. This might
2928 // fail, in which case we will fall back to terminal emulation.
30 var emulateStdin, emulateStdout, emulateStderr bool
31 fd := os.Stdin.Fd()
32 if mode, err := winterm.GetConsoleMode(fd); err == nil {
29 var (
30 emulateStdin, emulateStdout, emulateStderr bool
31
32 mode uint32
33 )
34
35 fd := windows.Handle(os.Stdin.Fd())
36 if err := windows.GetConsoleMode(fd, &mode); err == nil {
3337 // Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
34 if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
38 if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
3539 emulateStdin = true
3640 } else {
3741 vtInputSupported = true
3842 }
3943 // Unconditionally set the console mode back even on failure because SetConsoleMode
4044 // remembers invalid bits on input handles.
41 winterm.SetConsoleMode(fd, mode)
42 }
43
44 fd = os.Stdout.Fd()
45 if mode, err := winterm.GetConsoleMode(fd); err == nil {
45 _ = windows.SetConsoleMode(fd, mode)
46 }
47
48 fd = windows.Handle(os.Stdout.Fd())
49 if err := windows.GetConsoleMode(fd, &mode); err == nil {
4650 // Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
47 if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
51 if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
4852 emulateStdout = true
4953 } else {
50 winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
54 _ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
5155 }
5256 }
5357
54 fd = os.Stderr.Fd()
55 if mode, err := winterm.GetConsoleMode(fd); err == nil {
58 fd = windows.Handle(os.Stderr.Fd())
59 if err := windows.GetConsoleMode(fd, &mode); err == nil {
5660 // Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
57 if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
61 if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
5862 emulateStderr = true
5963 } else {
60 winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
64 _ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
6165 }
6266 }
6367
6670 // go-ansiterm hasn't switch to x/sys/windows.
6771 // TODO: switch back to x/sys/windows once go-ansiterm has switched
6872 if emulateStdin {
69 stdIn = windowsconsole.NewAnsiReader(syscall.STD_INPUT_HANDLE)
73 stdIn = windowsconsole.NewAnsiReader(windows.STD_INPUT_HANDLE)
7074 } else {
7175 stdIn = os.Stdin
7276 }
7377
7478 if emulateStdout {
75 stdOut = windowsconsole.NewAnsiWriter(syscall.STD_OUTPUT_HANDLE)
79 stdOut = windowsconsole.NewAnsiWriter(windows.STD_OUTPUT_HANDLE)
7680 } else {
7781 stdOut = os.Stdout
7882 }
7983
8084 if emulateStderr {
81 stdErr = windowsconsole.NewAnsiWriter(syscall.STD_ERROR_HANDLE)
85 stdErr = windowsconsole.NewAnsiWriter(windows.STD_ERROR_HANDLE)
8286 } else {
8387 stdErr = os.Stderr
8488 }
9397
9498 // GetWinsize returns the window size based on the specified file descriptor.
9599 func GetWinsize(fd uintptr) (*Winsize, error) {
96 info, err := winterm.GetConsoleScreenBufferInfo(fd)
97 if err != nil {
100 var info windows.ConsoleScreenBufferInfo
101 if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
98102 return nil, err
99103 }
100104
108112
109113 // IsTerminal returns true if the given file descriptor is a terminal.
110114 func IsTerminal(fd uintptr) bool {
111 return windowsconsole.IsConsole(fd)
115 var mode uint32
116 err := windows.GetConsoleMode(windows.Handle(fd), &mode)
117 return err == nil
112118 }
113119
114120 // RestoreTerminal restores the terminal connected to the given file descriptor
115121 // to a previous state.
116122 func RestoreTerminal(fd uintptr, state *State) error {
117 return winterm.SetConsoleMode(fd, state.mode)
123 return windows.SetConsoleMode(windows.Handle(fd), state.mode)
118124 }
119125
120126 // SaveState saves the state of the terminal connected to the given file descriptor.
121127 func SaveState(fd uintptr) (*State, error) {
122 mode, e := winterm.GetConsoleMode(fd)
123 if e != nil {
124 return nil, e
128 var mode uint32
129
130 if err := windows.GetConsoleMode(windows.Handle(fd), &mode); err != nil {
131 return nil, err
125132 }
126133
127134 return &State{mode: mode}, nil
131138 // -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
132139 func DisableEcho(fd uintptr, state *State) error {
133140 mode := state.mode
134 mode &^= winterm.ENABLE_ECHO_INPUT
135 mode |= winterm.ENABLE_PROCESSED_INPUT | winterm.ENABLE_LINE_INPUT
136 err := winterm.SetConsoleMode(fd, mode)
141 mode &^= windows.ENABLE_ECHO_INPUT
142 mode |= windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT
143 err := windows.SetConsoleMode(windows.Handle(fd), mode)
137144 if err != nil {
138145 return err
139146 }
168175
169176 // Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this
170177 // version of Windows.
171 winterm.SetConsoleMode(fd, state.mode|winterm.DISABLE_NEWLINE_AUTO_RETURN)
178 _ = windows.SetConsoleMode(windows.Handle(fd), state.mode|windows.DISABLE_NEWLINE_AUTO_RETURN)
172179 return state, err
173180 }
174181
187194 // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
188195
189196 // Disable these modes
190 mode &^= winterm.ENABLE_ECHO_INPUT
191 mode &^= winterm.ENABLE_LINE_INPUT
192 mode &^= winterm.ENABLE_MOUSE_INPUT
193 mode &^= winterm.ENABLE_WINDOW_INPUT
194 mode &^= winterm.ENABLE_PROCESSED_INPUT
197 mode &^= windows.ENABLE_ECHO_INPUT
198 mode &^= windows.ENABLE_LINE_INPUT
199 mode &^= windows.ENABLE_MOUSE_INPUT
200 mode &^= windows.ENABLE_WINDOW_INPUT
201 mode &^= windows.ENABLE_PROCESSED_INPUT
195202
196203 // Enable these modes
197 mode |= winterm.ENABLE_EXTENDED_FLAGS
198 mode |= winterm.ENABLE_INSERT_MODE
199 mode |= winterm.ENABLE_QUICK_EDIT_MODE
204 mode |= windows.ENABLE_EXTENDED_FLAGS
205 mode |= windows.ENABLE_INSERT_MODE
206 mode |= windows.ENABLE_QUICK_EDIT_MODE
200207 if vtInputSupported {
201 mode |= winterm.ENABLE_VIRTUAL_TERMINAL_INPUT
202 }
203
204 err = winterm.SetConsoleMode(fd, mode)
208 mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
209 }
210
211 err = windows.SetConsoleMode(windows.Handle(fd), mode)
205212 if err != nil {
206213 return nil, err
207214 }
214221
215222 go func() {
216223 _ = <-sigchan
217 RestoreTerminal(fd, state)
224 _ = RestoreTerminal(fd, state)
218225 os.Exit(0)
219226 }()
220227 }