Import upstream version 0.0~git20230502.9c3c875
Debian Janitor
11 months ago
3 | 3 | test: |
4 | 4 | strategy: |
5 | 5 | matrix: |
6 | go: ["1.18.x", "1.19.x"] | |
7 | platform: [ubuntu-latest] | |
6 | go: ["1.18.x", "1.19.x", "1.20.x"] | |
7 | platform: [ubuntu-latest, windows-latest, macos-latest] | |
8 | 8 | runs-on: ${{ matrix.platform }} |
9 | 9 | steps: |
10 | 10 | - name: Install Go ${{ matrix.go }} |
11 | uses: actions/setup-go@v3 | |
11 | uses: actions/setup-go@v4 | |
12 | 12 | with: |
13 | 13 | go-version: ${{ matrix.go }} |
14 | 14 | - name: Checkout code |
20 | 20 | steps: |
21 | 21 | - name: Checkout code |
22 | 22 | uses: actions/checkout@v3 |
23 | - name: go mod tidy | |
24 | run: | | |
25 | go mod tidy | |
26 | git diff --exit-code | |
23 | 27 | - name: Lint |
24 | 28 | run: | |
25 | 29 | docker run --rm -v `pwd`:/go/src/github.com/moby/term -w /go/src/github.com/moby/term \ |
0 | // Package term provides structures and helper functions to work with | |
1 | // terminal (state, sizes). | |
2 | package term |
3 | 3 | |
4 | 4 | require ( |
5 | 5 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 |
6 | github.com/creack/pty v1.1.11 | |
7 | golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 | |
6 | github.com/creack/pty v1.1.18 | |
7 | golang.org/x/sys v0.1.0 | |
8 | 8 | ) |
0 | 0 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= |
1 | 1 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= |
2 | github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= | |
3 | github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= | |
4 | golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= | |
2 | github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= | |
3 | github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= | |
5 | 4 | golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
5 | golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= | |
6 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
0 | //go:build !windows | |
1 | // +build !windows | |
2 | ||
3 | package term | |
4 | ||
5 | import ( | |
6 | "golang.org/x/sys/unix" | |
7 | ) | |
8 | ||
9 | func tcget(fd uintptr) (*Termios, error) { | |
10 | p, err := unix.IoctlGetTermios(int(fd), getTermios) | |
11 | if err != nil { | |
12 | return nil, err | |
13 | } | |
14 | return p, nil | |
15 | } | |
16 | ||
17 | func tcset(fd uintptr, p *Termios) error { | |
18 | return unix.IoctlSetTermios(int(fd), setTermios, p) | |
19 | } |
0 | //go:build !windows | |
1 | // +build !windows | |
2 | ||
3 | // Package term provides structures and helper functions to work with | |
4 | // terminal (state, sizes). | |
5 | 0 | package term |
6 | 1 | |
7 | import ( | |
8 | "errors" | |
9 | "fmt" | |
10 | "io" | |
11 | "os" | |
12 | "os/signal" | |
2 | import "io" | |
13 | 3 | |
14 | "golang.org/x/sys/unix" | |
15 | ) | |
16 | ||
17 | // ErrInvalidState is returned if the state of the terminal is invalid. | |
18 | var ErrInvalidState = errors.New("Invalid terminal state") | |
19 | ||
20 | // State represents the state of the terminal. | |
21 | type State struct { | |
22 | termios Termios | |
23 | } | |
4 | // State holds the platform-specific state / console mode for the terminal. | |
5 | type State terminalState | |
24 | 6 | |
25 | 7 | // Winsize represents the size of the terminal window. |
26 | 8 | type Winsize struct { |
27 | 9 | Height uint16 |
28 | 10 | Width uint16 |
29 | x uint16 | |
30 | y uint16 | |
11 | ||
12 | // Only used on Unix | |
13 | x uint16 | |
14 | y uint16 | |
31 | 15 | } |
32 | 16 | |
33 | 17 | // StdStreams returns the standard streams (stdin, stdout, stderr). |
18 | // | |
19 | // On Windows, it attempts to turn on VT handling on all std handles if | |
20 | // supported, or falls back to terminal emulation. On Unix, this returns | |
21 | // the standard [os.Stdin], [os.Stdout] and [os.Stderr]. | |
34 | 22 | func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { |
35 | return os.Stdin, os.Stdout, os.Stderr | |
23 | return stdStreams() | |
36 | 24 | } |
37 | 25 | |
38 | 26 | // GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. |
39 | func GetFdInfo(in interface{}) (uintptr, bool) { | |
40 | var inFd uintptr | |
41 | var isTerminalIn bool | |
42 | if file, ok := in.(*os.File); ok { | |
43 | inFd = file.Fd() | |
44 | isTerminalIn = IsTerminal(inFd) | |
45 | } | |
46 | return inFd, isTerminalIn | |
27 | func GetFdInfo(in interface{}) (fd uintptr, isTerminal bool) { | |
28 | return getFdInfo(in) | |
29 | } | |
30 | ||
31 | // GetWinsize returns the window size based on the specified file descriptor. | |
32 | func GetWinsize(fd uintptr) (*Winsize, error) { | |
33 | return getWinsize(fd) | |
34 | } | |
35 | ||
36 | // SetWinsize tries to set the specified window size for the specified file | |
37 | // descriptor. It is only implemented on Unix, and returns an error on Windows. | |
38 | func SetWinsize(fd uintptr, ws *Winsize) error { | |
39 | return setWinsize(fd, ws) | |
47 | 40 | } |
48 | 41 | |
49 | 42 | // IsTerminal returns true if the given file descriptor is a terminal. |
50 | 43 | func IsTerminal(fd uintptr) bool { |
51 | _, err := tcget(fd) | |
52 | return err == nil | |
44 | return isTerminal(fd) | |
53 | 45 | } |
54 | 46 | |
55 | 47 | // RestoreTerminal restores the terminal connected to the given file descriptor |
56 | 48 | // to a previous state. |
57 | 49 | func RestoreTerminal(fd uintptr, state *State) error { |
58 | if state == nil { | |
59 | return ErrInvalidState | |
60 | } | |
61 | return tcset(fd, &state.termios) | |
50 | return restoreTerminal(fd, state) | |
62 | 51 | } |
63 | 52 | |
64 | 53 | // SaveState saves the state of the terminal connected to the given file descriptor. |
65 | 54 | func SaveState(fd uintptr) (*State, error) { |
66 | termios, err := tcget(fd) | |
67 | if err != nil { | |
68 | return nil, err | |
69 | } | |
70 | return &State{termios: *termios}, nil | |
55 | return saveState(fd) | |
71 | 56 | } |
72 | 57 | |
73 | 58 | // DisableEcho applies the specified state to the terminal connected to the file |
74 | 59 | // descriptor, with echo disabled. |
75 | 60 | func DisableEcho(fd uintptr, state *State) error { |
76 | newState := state.termios | |
77 | newState.Lflag &^= unix.ECHO | |
78 | ||
79 | if err := tcset(fd, &newState); err != nil { | |
80 | return err | |
81 | } | |
82 | handleInterrupt(fd, state) | |
83 | return nil | |
61 | return disableEcho(fd, state) | |
84 | 62 | } |
85 | 63 | |
86 | 64 | // SetRawTerminal puts the terminal connected to the given file descriptor into |
87 | // raw mode and returns the previous state. On UNIX, this puts both the input | |
88 | // and output into raw mode. On Windows, it only puts the input into raw mode. | |
89 | func SetRawTerminal(fd uintptr) (*State, error) { | |
90 | oldState, err := MakeRaw(fd) | |
91 | if err != nil { | |
92 | return nil, err | |
93 | } | |
94 | handleInterrupt(fd, oldState) | |
95 | return oldState, err | |
65 | // raw mode and returns the previous state. On UNIX, this is the equivalent of | |
66 | // [MakeRaw], and puts both the input and output into raw mode. On Windows, it | |
67 | // only puts the input into raw mode. | |
68 | func SetRawTerminal(fd uintptr) (previousState *State, err error) { | |
69 | return setRawTerminal(fd) | |
96 | 70 | } |
97 | 71 | |
98 | 72 | // SetRawTerminalOutput puts the output of terminal connected to the given file |
99 | 73 | // descriptor into raw mode. On UNIX, this does nothing and returns nil for the |
100 | 74 | // state. On Windows, it disables LF -> CRLF translation. |
101 | func SetRawTerminalOutput(fd uintptr) (*State, error) { | |
102 | return nil, nil | |
75 | func SetRawTerminalOutput(fd uintptr) (previousState *State, err error) { | |
76 | return setRawTerminalOutput(fd) | |
103 | 77 | } |
104 | 78 | |
105 | func handleInterrupt(fd uintptr, state *State) { | |
106 | sigchan := make(chan os.Signal, 1) | |
107 | signal.Notify(sigchan, os.Interrupt) | |
108 | go func() { | |
109 | for range sigchan { | |
110 | // quit cleanly and the new terminal item is on a new line | |
111 | fmt.Println() | |
112 | signal.Stop(sigchan) | |
113 | close(sigchan) | |
114 | RestoreTerminal(fd, state) | |
115 | os.Exit(1) | |
116 | } | |
117 | }() | |
79 | // MakeRaw puts the terminal (Windows Console) connected to the | |
80 | // given file descriptor into raw mode and returns the previous state of | |
81 | // the terminal so that it can be restored. | |
82 | func MakeRaw(fd uintptr) (previousState *State, err error) { | |
83 | return makeRaw(fd) | |
118 | 84 | } |
0 | //go:build !windows | |
1 | // +build !windows | |
2 | ||
3 | package term | |
4 | ||
5 | import ( | |
6 | "errors" | |
7 | "io" | |
8 | "os" | |
9 | ||
10 | "golang.org/x/sys/unix" | |
11 | ) | |
12 | ||
13 | // ErrInvalidState is returned if the state of the terminal is invalid. | |
14 | // | |
15 | // Deprecated: ErrInvalidState is no longer used. | |
16 | var ErrInvalidState = errors.New("Invalid terminal state") | |
17 | ||
18 | // terminalState holds the platform-specific state / console mode for the terminal. | |
19 | type terminalState struct { | |
20 | termios unix.Termios | |
21 | } | |
22 | ||
23 | func stdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { | |
24 | return os.Stdin, os.Stdout, os.Stderr | |
25 | } | |
26 | ||
27 | func getFdInfo(in interface{}) (uintptr, bool) { | |
28 | var inFd uintptr | |
29 | var isTerminalIn bool | |
30 | if file, ok := in.(*os.File); ok { | |
31 | inFd = file.Fd() | |
32 | isTerminalIn = isTerminal(inFd) | |
33 | } | |
34 | return inFd, isTerminalIn | |
35 | } | |
36 | ||
37 | func getWinsize(fd uintptr) (*Winsize, error) { | |
38 | uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) | |
39 | ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel} | |
40 | return ws, err | |
41 | } | |
42 | ||
43 | func setWinsize(fd uintptr, ws *Winsize) error { | |
44 | return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, &unix.Winsize{ | |
45 | Row: ws.Height, | |
46 | Col: ws.Width, | |
47 | Xpixel: ws.x, | |
48 | Ypixel: ws.y, | |
49 | }) | |
50 | } | |
51 | ||
52 | func isTerminal(fd uintptr) bool { | |
53 | _, err := tcget(fd) | |
54 | return err == nil | |
55 | } | |
56 | ||
57 | func restoreTerminal(fd uintptr, state *State) error { | |
58 | if state == nil { | |
59 | return errors.New("invalid terminal state") | |
60 | } | |
61 | return tcset(fd, &state.termios) | |
62 | } | |
63 | ||
64 | func saveState(fd uintptr) (*State, error) { | |
65 | termios, err := tcget(fd) | |
66 | if err != nil { | |
67 | return nil, err | |
68 | } | |
69 | return &State{termios: *termios}, nil | |
70 | } | |
71 | ||
72 | func disableEcho(fd uintptr, state *State) error { | |
73 | newState := state.termios | |
74 | newState.Lflag &^= unix.ECHO | |
75 | ||
76 | return tcset(fd, &newState) | |
77 | } | |
78 | ||
79 | func setRawTerminal(fd uintptr) (*State, error) { | |
80 | return makeRaw(fd) | |
81 | } | |
82 | ||
83 | func setRawTerminalOutput(fd uintptr) (*State, error) { | |
84 | return nil, nil | |
85 | } | |
86 | ||
87 | func tcget(fd uintptr) (*unix.Termios, error) { | |
88 | p, err := unix.IoctlGetTermios(int(fd), getTermios) | |
89 | if err != nil { | |
90 | return nil, err | |
91 | } | |
92 | return p, nil | |
93 | } | |
94 | ||
95 | func tcset(fd uintptr, p *unix.Termios) error { | |
96 | return unix.IoctlSetTermios(int(fd), setTermios, p) | |
97 | } |
0 | 0 | package term |
1 | 1 | |
2 | 2 | import ( |
3 | "fmt" | |
3 | 4 | "io" |
4 | 5 | "os" |
5 | 6 | "os/signal" |
8 | 9 | "golang.org/x/sys/windows" |
9 | 10 | ) |
10 | 11 | |
11 | // State holds the console mode for the terminal. | |
12 | type State struct { | |
12 | // terminalState holds the platform-specific state / console mode for the terminal. | |
13 | type terminalState struct { | |
13 | 14 | mode uint32 |
14 | } | |
15 | ||
16 | // Winsize is used for window size. | |
17 | type Winsize struct { | |
18 | Height uint16 | |
19 | Width uint16 | |
20 | 15 | } |
21 | 16 | |
22 | 17 | // vtInputSupported is true if winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported by the console |
23 | 18 | var vtInputSupported bool |
24 | 19 | |
25 | // StdStreams returns the standard streams (stdin, stdout, stderr). | |
26 | func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { | |
20 | func stdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { | |
27 | 21 | // Turn on VT handling on all std handles, if possible. This might |
28 | 22 | // fail, in which case we will fall back to terminal emulation. |
29 | 23 | var ( |
86 | 80 | stdErr = os.Stderr |
87 | 81 | } |
88 | 82 | |
89 | return | |
83 | return stdIn, stdOut, stdErr | |
90 | 84 | } |
91 | 85 | |
92 | // GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. | |
93 | func GetFdInfo(in interface{}) (uintptr, bool) { | |
86 | func getFdInfo(in interface{}) (uintptr, bool) { | |
94 | 87 | return windowsconsole.GetHandleInfo(in) |
95 | 88 | } |
96 | 89 | |
97 | // GetWinsize returns the window size based on the specified file descriptor. | |
98 | func GetWinsize(fd uintptr) (*Winsize, error) { | |
90 | func getWinsize(fd uintptr) (*Winsize, error) { | |
99 | 91 | var info windows.ConsoleScreenBufferInfo |
100 | 92 | if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { |
101 | 93 | return nil, err |
109 | 101 | return winsize, nil |
110 | 102 | } |
111 | 103 | |
112 | // IsTerminal returns true if the given file descriptor is a terminal. | |
113 | func IsTerminal(fd uintptr) bool { | |
104 | func setWinsize(fd uintptr, ws *Winsize) error { | |
105 | return fmt.Errorf("not implemented on Windows") | |
106 | } | |
107 | ||
108 | func isTerminal(fd uintptr) bool { | |
114 | 109 | var mode uint32 |
115 | 110 | err := windows.GetConsoleMode(windows.Handle(fd), &mode) |
116 | 111 | return err == nil |
117 | 112 | } |
118 | 113 | |
119 | // RestoreTerminal restores the terminal connected to the given file descriptor | |
120 | // to a previous state. | |
121 | func RestoreTerminal(fd uintptr, state *State) error { | |
114 | func restoreTerminal(fd uintptr, state *State) error { | |
122 | 115 | return windows.SetConsoleMode(windows.Handle(fd), state.mode) |
123 | 116 | } |
124 | 117 | |
125 | // SaveState saves the state of the terminal connected to the given file descriptor. | |
126 | func SaveState(fd uintptr) (*State, error) { | |
118 | func saveState(fd uintptr) (*State, error) { | |
127 | 119 | var mode uint32 |
128 | 120 | |
129 | 121 | if err := windows.GetConsoleMode(windows.Handle(fd), &mode); err != nil { |
133 | 125 | return &State{mode: mode}, nil |
134 | 126 | } |
135 | 127 | |
136 | // DisableEcho disables echo for the terminal connected to the given file descriptor. | |
137 | // -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx | |
138 | func DisableEcho(fd uintptr, state *State) error { | |
128 | func disableEcho(fd uintptr, state *State) error { | |
129 | // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx | |
139 | 130 | mode := state.mode |
140 | 131 | mode &^= windows.ENABLE_ECHO_INPUT |
141 | 132 | mode |= windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT |
149 | 140 | return nil |
150 | 141 | } |
151 | 142 | |
152 | // SetRawTerminal puts the terminal connected to the given file descriptor into | |
153 | // raw mode and returns the previous state. On UNIX, this puts both the input | |
154 | // and output into raw mode. On Windows, it only puts the input into raw mode. | |
155 | func SetRawTerminal(fd uintptr) (*State, error) { | |
156 | state, err := MakeRaw(fd) | |
143 | func setRawTerminal(fd uintptr) (*State, error) { | |
144 | oldState, err := MakeRaw(fd) | |
157 | 145 | if err != nil { |
158 | 146 | return nil, err |
159 | 147 | } |
160 | 148 | |
161 | 149 | // Register an interrupt handler to catch and restore prior state |
162 | restoreAtInterrupt(fd, state) | |
163 | return state, err | |
150 | restoreAtInterrupt(fd, oldState) | |
151 | return oldState, err | |
164 | 152 | } |
165 | 153 | |
166 | // SetRawTerminalOutput puts the output of terminal connected to the given file | |
167 | // descriptor into raw mode. On UNIX, this does nothing and returns nil for the | |
168 | // state. On Windows, it disables LF -> CRLF translation. | |
169 | func SetRawTerminalOutput(fd uintptr) (*State, error) { | |
170 | state, err := SaveState(fd) | |
154 | func setRawTerminalOutput(fd uintptr) (*State, error) { | |
155 | oldState, err := saveState(fd) | |
171 | 156 | if err != nil { |
172 | 157 | return nil, err |
173 | 158 | } |
174 | 159 | |
175 | 160 | // Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this |
176 | 161 | // version of Windows. |
177 | _ = windows.SetConsoleMode(windows.Handle(fd), state.mode|windows.DISABLE_NEWLINE_AUTO_RETURN) | |
178 | return state, err | |
179 | } | |
180 | ||
181 | // MakeRaw puts the terminal (Windows Console) connected to the given file descriptor into raw | |
182 | // mode and returns the previous state of the terminal so that it can be restored. | |
183 | func MakeRaw(fd uintptr) (*State, error) { | |
184 | state, err := SaveState(fd) | |
185 | if err != nil { | |
186 | return nil, err | |
187 | } | |
188 | ||
189 | mode := state.mode | |
190 | ||
191 | // See | |
192 | // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx | |
193 | // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx | |
194 | ||
195 | // Disable these modes | |
196 | mode &^= windows.ENABLE_ECHO_INPUT | |
197 | mode &^= windows.ENABLE_LINE_INPUT | |
198 | mode &^= windows.ENABLE_MOUSE_INPUT | |
199 | mode &^= windows.ENABLE_WINDOW_INPUT | |
200 | mode &^= windows.ENABLE_PROCESSED_INPUT | |
201 | ||
202 | // Enable these modes | |
203 | mode |= windows.ENABLE_EXTENDED_FLAGS | |
204 | mode |= windows.ENABLE_INSERT_MODE | |
205 | mode |= windows.ENABLE_QUICK_EDIT_MODE | |
206 | if vtInputSupported { | |
207 | mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT | |
208 | } | |
209 | ||
210 | err = windows.SetConsoleMode(windows.Handle(fd), mode) | |
211 | if err != nil { | |
212 | return nil, err | |
213 | } | |
214 | return state, nil | |
162 | _ = windows.SetConsoleMode(windows.Handle(fd), oldState.mode|windows.DISABLE_NEWLINE_AUTO_RETURN) | |
163 | return oldState, err | |
215 | 164 | } |
216 | 165 | |
217 | 166 | func restoreAtInterrupt(fd uintptr, state *State) { |
0 | //go:build !windows | |
1 | // +build !windows | |
2 | ||
3 | package term | |
4 | ||
5 | import ( | |
6 | "golang.org/x/sys/unix" | |
7 | ) | |
8 | ||
9 | // Termios is the Unix API for terminal I/O. | |
10 | type Termios = unix.Termios | |
11 | ||
12 | // MakeRaw puts the terminal connected to the given file descriptor into raw | |
13 | // mode and returns the previous state of the terminal so that it can be | |
14 | // restored. | |
15 | func MakeRaw(fd uintptr) (*State, error) { | |
16 | termios, err := tcget(fd) | |
17 | if err != nil { | |
18 | return nil, err | |
19 | } | |
20 | ||
21 | oldState := State{termios: *termios} | |
22 | ||
23 | termios.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON) | |
24 | termios.Oflag &^= unix.OPOST | |
25 | termios.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN) | |
26 | termios.Cflag &^= (unix.CSIZE | unix.PARENB) | |
27 | termios.Cflag |= unix.CS8 | |
28 | termios.Cc[unix.VMIN] = 1 | |
29 | termios.Cc[unix.VTIME] = 0 | |
30 | ||
31 | if err := tcset(fd, termios); err != nil { | |
32 | return nil, err | |
33 | } | |
34 | return &oldState, nil | |
35 | } |
0 | //go:build !windows | |
1 | // +build !windows | |
2 | ||
3 | package term | |
4 | ||
5 | import ( | |
6 | "golang.org/x/sys/unix" | |
7 | ) | |
8 | ||
9 | // Termios is the Unix API for terminal I/O. | |
10 | // | |
11 | // Deprecated: use [unix.Termios]. | |
12 | type Termios = unix.Termios | |
13 | ||
14 | func makeRaw(fd uintptr) (*State, error) { | |
15 | termios, err := tcget(fd) | |
16 | if err != nil { | |
17 | return nil, err | |
18 | } | |
19 | ||
20 | oldState := State{termios: *termios} | |
21 | ||
22 | termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON | |
23 | termios.Oflag &^= unix.OPOST | |
24 | termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN | |
25 | termios.Cflag &^= unix.CSIZE | unix.PARENB | |
26 | termios.Cflag |= unix.CS8 | |
27 | termios.Cc[unix.VMIN] = 1 | |
28 | termios.Cc[unix.VTIME] = 0 | |
29 | ||
30 | if err := tcset(fd, termios); err != nil { | |
31 | return nil, err | |
32 | } | |
33 | return &oldState, nil | |
34 | } |
0 | package term | |
1 | ||
2 | import "golang.org/x/sys/windows" | |
3 | ||
4 | func makeRaw(fd uintptr) (*State, error) { | |
5 | state, err := SaveState(fd) | |
6 | if err != nil { | |
7 | return nil, err | |
8 | } | |
9 | ||
10 | mode := state.mode | |
11 | ||
12 | // See | |
13 | // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx | |
14 | // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx | |
15 | ||
16 | // Disable these modes | |
17 | mode &^= windows.ENABLE_ECHO_INPUT | |
18 | mode &^= windows.ENABLE_LINE_INPUT | |
19 | mode &^= windows.ENABLE_MOUSE_INPUT | |
20 | mode &^= windows.ENABLE_WINDOW_INPUT | |
21 | mode &^= windows.ENABLE_PROCESSED_INPUT | |
22 | ||
23 | // Enable these modes | |
24 | mode |= windows.ENABLE_EXTENDED_FLAGS | |
25 | mode |= windows.ENABLE_INSERT_MODE | |
26 | mode |= windows.ENABLE_QUICK_EDIT_MODE | |
27 | if vtInputSupported { | |
28 | mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT | |
29 | } | |
30 | ||
31 | err = windows.SetConsoleMode(windows.Handle(fd), mode) | |
32 | if err != nil { | |
33 | return nil, err | |
34 | } | |
35 | return state, nil | |
36 | } |
194 | 194 | |
195 | 195 | // <Alt>+Key generates ESC N Key |
196 | 196 | if !control && alt { |
197 | return ansiterm.KEY_ESC_N + strings.ToLower(string(keyEvent.UnicodeChar)) | |
198 | } | |
199 | ||
200 | return string(keyEvent.UnicodeChar) | |
197 | return ansiterm.KEY_ESC_N + strings.ToLower(string(rune(keyEvent.UnicodeChar))) | |
198 | } | |
199 | ||
200 | return string(rune(keyEvent.UnicodeChar)) | |
201 | 201 | } |
202 | 202 | |
203 | 203 | // formatVirtualKey converts a virtual key (e.g., up arrow) into the appropriate ANSI string. |
0 | //go:build windows | |
1 | // +build windows | |
2 | ||
3 | package windowsconsole | |
4 | ||
5 | import ( | |
6 | "testing" | |
7 | ||
8 | "github.com/Azure/go-ansiterm" | |
9 | "github.com/Azure/go-ansiterm/winterm" | |
10 | ) | |
11 | ||
12 | func TestKeyToString(t *testing.T) { | |
13 | ke := &winterm.KEY_EVENT_RECORD{ | |
14 | ControlKeyState: winterm.LEFT_ALT_PRESSED, | |
15 | UnicodeChar: 65, // capital A | |
16 | } | |
17 | ||
18 | const expected = ansiterm.KEY_ESC_N + "a" | |
19 | out := keyToString(ke, nil) | |
20 | if out != expected { | |
21 | t.Errorf("expected %s, got %s", expected, out) | |
22 | } | |
23 | } |
29 | 29 | |
30 | 30 | // IsConsole returns true if the given file descriptor is a Windows Console. |
31 | 31 | // The code assumes that GetConsoleMode will return an error for file descriptors that are not a console. |
32 | // Deprecated: use golang.org/x/sys/windows.GetConsoleMode() or golang.org/x/term.IsTerminal() | |
33 | var IsConsole = isConsole | |
32 | // | |
33 | // Deprecated: use [windows.GetConsoleMode] or [golang.org/x/term.IsTerminal]. | |
34 | func IsConsole(fd uintptr) bool { | |
35 | return isConsole(fd) | |
36 | } | |
34 | 37 | |
35 | 38 | func isConsole(fd uintptr) bool { |
36 | 39 | var mode uint32 |
0 | //go:build !windows | |
1 | // +build !windows | |
2 | ||
3 | package term | |
4 | ||
5 | import ( | |
6 | "golang.org/x/sys/unix" | |
7 | ) | |
8 | ||
9 | // GetWinsize returns the window size based on the specified file descriptor. | |
10 | func GetWinsize(fd uintptr) (*Winsize, error) { | |
11 | uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) | |
12 | ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel} | |
13 | return ws, err | |
14 | } | |
15 | ||
16 | // SetWinsize tries to set the specified window size for the specified file descriptor. | |
17 | func SetWinsize(fd uintptr, ws *Winsize) error { | |
18 | uws := &unix.Winsize{Row: ws.Height, Col: ws.Width, Xpixel: ws.x, Ypixel: ws.y} | |
19 | return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, uws) | |
20 | } |