mirror of https://github.com/docker/cli.git
vendor: moby/term 73f35e472e8f0a3f91347164138ce6bd73b756a9
full diff: 063f2cd0b4...73f35e472e
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
d10e2b9a6d
commit
f6541cfd80
|
@ -47,7 +47,7 @@ github.com/miekg/pkcs11 210dc1e16747c5ba98a03bcbcf72
|
||||||
github.com/mitchellh/mapstructure f15292f7a699fcc1a38a80977f80a046874ba8ac
|
github.com/mitchellh/mapstructure f15292f7a699fcc1a38a80977f80a046874ba8ac
|
||||||
github.com/moby/buildkit ae7ff7174f73bcb4df89b97e1623b3fb0bfb0a0c
|
github.com/moby/buildkit ae7ff7174f73bcb4df89b97e1623b3fb0bfb0a0c
|
||||||
github.com/moby/sys 6154f11e6840c0d6b0dbb23f4125a6134b3013c9 # mountinfo/v0.1.3
|
github.com/moby/sys 6154f11e6840c0d6b0dbb23f4125a6134b3013c9 # mountinfo/v0.1.3
|
||||||
github.com/moby/term 063f2cd0b49dbb0752774d1cb649998d91424fea
|
github.com/moby/term 73f35e472e8f0a3f91347164138ce6bd73b756a9
|
||||||
github.com/modern-go/concurrent bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94 # 1.0.3
|
github.com/modern-go/concurrent bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94 # 1.0.3
|
||||||
github.com/modern-go/reflect2 4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd # 1.0.1
|
github.com/modern-go/reflect2 4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd # 1.0.1
|
||||||
github.com/morikuni/aec 39771216ff4c63d11f5e604076f9c45e8be1067b # v1.0.0
|
github.com/morikuni/aec 39771216ff4c63d11f5e604076f9c45e8be1067b # v1.0.0
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# term - utilities for dealing with terminals
|
# term - utilities for dealing with terminals
|
||||||
|
|
||||||
![](https://github.com/moby/term/workflows/.github/workflows/test.yml/badge.svg) [![GoDoc](https://godoc.org/github.com/moby/term?status.svg)](https://godoc.org/github.com/moby/term) [![Go Report Card](https://goreportcard.com/badge/github.com/moby/term)](https://goreportcard.com/report/github.com/moby/term)
|
![Test](https://github.com/moby/term/workflows/Test/badge.svg) [![GoDoc](https://godoc.org/github.com/moby/term?status.svg)](https://godoc.org/github.com/moby/term) [![Go Report Card](https://goreportcard.com/badge/github.com/moby/term)](https://goreportcard.com/report/github.com/moby/term)
|
||||||
|
|
||||||
term provides structures and helper functions to work with terminal (state, sizes).
|
term provides structures and helper functions to work with terminal (state, sizes).
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,9 @@ go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78
|
||||||
github.com/google/go-cmp v0.3.1
|
github.com/creack/pty v1.1.9
|
||||||
|
github.com/google/go-cmp v0.4.0
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.4.2
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd
|
||||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527
|
|
||||||
gotest.tools v2.2.0+incompatible
|
gotest.tools v2.2.0+incompatible
|
||||||
gotest.tools/v3 v3.0.2 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build !windows
|
// +build !windows,!illumos,!solaris
|
||||||
|
|
||||||
package term
|
package term
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build !windows
|
// +build !windows,!illumos,!solaris
|
||||||
|
|
||||||
// Package term provides structures and helper functions to work with
|
// Package term provides structures and helper functions to work with
|
||||||
// terminal (state, sizes).
|
// terminal (state, sizes).
|
||||||
|
|
|
@ -4,10 +4,9 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall" // used for STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE
|
|
||||||
|
|
||||||
"github.com/Azure/go-ansiterm/winterm"
|
|
||||||
windowsconsole "github.com/moby/term/windows"
|
windowsconsole "github.com/moby/term/windows"
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
// State holds the console mode for the terminal.
|
// State holds the console mode for the terminal.
|
||||||
|
@ -28,37 +27,42 @@ var vtInputSupported bool
|
||||||
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
|
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
|
||||||
// Turn on VT handling on all std handles, if possible. This might
|
// Turn on VT handling on all std handles, if possible. This might
|
||||||
// fail, in which case we will fall back to terminal emulation.
|
// fail, in which case we will fall back to terminal emulation.
|
||||||
var emulateStdin, emulateStdout, emulateStderr bool
|
var (
|
||||||
fd := os.Stdin.Fd()
|
emulateStdin, emulateStdout, emulateStderr bool
|
||||||
if mode, err := winterm.GetConsoleMode(fd); err == nil {
|
|
||||||
|
mode uint32
|
||||||
|
)
|
||||||
|
|
||||||
|
fd := windows.Handle(os.Stdin.Fd())
|
||||||
|
if err := windows.GetConsoleMode(fd, &mode); err == nil {
|
||||||
// Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
|
// Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
|
||||||
if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
|
if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
|
||||||
emulateStdin = true
|
emulateStdin = true
|
||||||
} else {
|
} else {
|
||||||
vtInputSupported = true
|
vtInputSupported = true
|
||||||
}
|
}
|
||||||
// Unconditionally set the console mode back even on failure because SetConsoleMode
|
// Unconditionally set the console mode back even on failure because SetConsoleMode
|
||||||
// remembers invalid bits on input handles.
|
// remembers invalid bits on input handles.
|
||||||
winterm.SetConsoleMode(fd, mode)
|
_ = windows.SetConsoleMode(fd, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = os.Stdout.Fd()
|
fd = windows.Handle(os.Stdout.Fd())
|
||||||
if mode, err := winterm.GetConsoleMode(fd); err == nil {
|
if err := windows.GetConsoleMode(fd, &mode); err == nil {
|
||||||
// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
|
// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
|
||||||
if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
|
if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
|
||||||
emulateStdout = true
|
emulateStdout = true
|
||||||
} else {
|
} else {
|
||||||
winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
_ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = os.Stderr.Fd()
|
fd = windows.Handle(os.Stderr.Fd())
|
||||||
if mode, err := winterm.GetConsoleMode(fd); err == nil {
|
if err := windows.GetConsoleMode(fd, &mode); err == nil {
|
||||||
// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
|
// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
|
||||||
if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
|
if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
|
||||||
emulateStderr = true
|
emulateStderr = true
|
||||||
} else {
|
} else {
|
||||||
winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
_ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,19 +71,19 @@ func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
|
||||||
// go-ansiterm hasn't switch to x/sys/windows.
|
// go-ansiterm hasn't switch to x/sys/windows.
|
||||||
// TODO: switch back to x/sys/windows once go-ansiterm has switched
|
// TODO: switch back to x/sys/windows once go-ansiterm has switched
|
||||||
if emulateStdin {
|
if emulateStdin {
|
||||||
stdIn = windowsconsole.NewAnsiReader(syscall.STD_INPUT_HANDLE)
|
stdIn = windowsconsole.NewAnsiReader(windows.STD_INPUT_HANDLE)
|
||||||
} else {
|
} else {
|
||||||
stdIn = os.Stdin
|
stdIn = os.Stdin
|
||||||
}
|
}
|
||||||
|
|
||||||
if emulateStdout {
|
if emulateStdout {
|
||||||
stdOut = windowsconsole.NewAnsiWriter(syscall.STD_OUTPUT_HANDLE)
|
stdOut = windowsconsole.NewAnsiWriter(windows.STD_OUTPUT_HANDLE)
|
||||||
} else {
|
} else {
|
||||||
stdOut = os.Stdout
|
stdOut = os.Stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
if emulateStderr {
|
if emulateStderr {
|
||||||
stdErr = windowsconsole.NewAnsiWriter(syscall.STD_ERROR_HANDLE)
|
stdErr = windowsconsole.NewAnsiWriter(windows.STD_ERROR_HANDLE)
|
||||||
} else {
|
} else {
|
||||||
stdErr = os.Stderr
|
stdErr = os.Stderr
|
||||||
}
|
}
|
||||||
|
@ -94,8 +98,8 @@ func GetFdInfo(in interface{}) (uintptr, bool) {
|
||||||
|
|
||||||
// GetWinsize returns the window size based on the specified file descriptor.
|
// GetWinsize returns the window size based on the specified file descriptor.
|
||||||
func GetWinsize(fd uintptr) (*Winsize, error) {
|
func GetWinsize(fd uintptr) (*Winsize, error) {
|
||||||
info, err := winterm.GetConsoleScreenBufferInfo(fd)
|
var info windows.ConsoleScreenBufferInfo
|
||||||
if err != nil {
|
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,20 +113,23 @@ func GetWinsize(fd uintptr) (*Winsize, error) {
|
||||||
|
|
||||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||||
func IsTerminal(fd uintptr) bool {
|
func IsTerminal(fd uintptr) bool {
|
||||||
return windowsconsole.IsConsole(fd)
|
var mode uint32
|
||||||
|
err := windows.GetConsoleMode(windows.Handle(fd), &mode)
|
||||||
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestoreTerminal restores the terminal connected to the given file descriptor
|
// RestoreTerminal restores the terminal connected to the given file descriptor
|
||||||
// to a previous state.
|
// to a previous state.
|
||||||
func RestoreTerminal(fd uintptr, state *State) error {
|
func RestoreTerminal(fd uintptr, state *State) error {
|
||||||
return winterm.SetConsoleMode(fd, state.mode)
|
return windows.SetConsoleMode(windows.Handle(fd), state.mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveState saves the state of the terminal connected to the given file descriptor.
|
// SaveState saves the state of the terminal connected to the given file descriptor.
|
||||||
func SaveState(fd uintptr) (*State, error) {
|
func SaveState(fd uintptr) (*State, error) {
|
||||||
mode, e := winterm.GetConsoleMode(fd)
|
var mode uint32
|
||||||
if e != nil {
|
|
||||||
return nil, e
|
if err := windows.GetConsoleMode(windows.Handle(fd), &mode); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &State{mode: mode}, nil
|
return &State{mode: mode}, nil
|
||||||
|
@ -132,9 +139,9 @@ func SaveState(fd uintptr) (*State, error) {
|
||||||
// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
||||||
func DisableEcho(fd uintptr, state *State) error {
|
func DisableEcho(fd uintptr, state *State) error {
|
||||||
mode := state.mode
|
mode := state.mode
|
||||||
mode &^= winterm.ENABLE_ECHO_INPUT
|
mode &^= windows.ENABLE_ECHO_INPUT
|
||||||
mode |= winterm.ENABLE_PROCESSED_INPUT | winterm.ENABLE_LINE_INPUT
|
mode |= windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT
|
||||||
err := winterm.SetConsoleMode(fd, mode)
|
err := windows.SetConsoleMode(windows.Handle(fd), mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -169,7 +176,7 @@ func SetRawTerminalOutput(fd uintptr) (*State, error) {
|
||||||
|
|
||||||
// Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this
|
// Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this
|
||||||
// version of Windows.
|
// version of Windows.
|
||||||
winterm.SetConsoleMode(fd, state.mode|winterm.DISABLE_NEWLINE_AUTO_RETURN)
|
_ = windows.SetConsoleMode(windows.Handle(fd), state.mode|windows.DISABLE_NEWLINE_AUTO_RETURN)
|
||||||
return state, err
|
return state, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,21 +195,21 @@ func MakeRaw(fd uintptr) (*State, error) {
|
||||||
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
||||||
|
|
||||||
// Disable these modes
|
// Disable these modes
|
||||||
mode &^= winterm.ENABLE_ECHO_INPUT
|
mode &^= windows.ENABLE_ECHO_INPUT
|
||||||
mode &^= winterm.ENABLE_LINE_INPUT
|
mode &^= windows.ENABLE_LINE_INPUT
|
||||||
mode &^= winterm.ENABLE_MOUSE_INPUT
|
mode &^= windows.ENABLE_MOUSE_INPUT
|
||||||
mode &^= winterm.ENABLE_WINDOW_INPUT
|
mode &^= windows.ENABLE_WINDOW_INPUT
|
||||||
mode &^= winterm.ENABLE_PROCESSED_INPUT
|
mode &^= windows.ENABLE_PROCESSED_INPUT
|
||||||
|
|
||||||
// Enable these modes
|
// Enable these modes
|
||||||
mode |= winterm.ENABLE_EXTENDED_FLAGS
|
mode |= windows.ENABLE_EXTENDED_FLAGS
|
||||||
mode |= winterm.ENABLE_INSERT_MODE
|
mode |= windows.ENABLE_INSERT_MODE
|
||||||
mode |= winterm.ENABLE_QUICK_EDIT_MODE
|
mode |= windows.ENABLE_QUICK_EDIT_MODE
|
||||||
if vtInputSupported {
|
if vtInputSupported {
|
||||||
mode |= winterm.ENABLE_VIRTUAL_TERMINAL_INPUT
|
mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
|
||||||
}
|
}
|
||||||
|
|
||||||
err = winterm.SetConsoleMode(fd, mode)
|
err = windows.SetConsoleMode(windows.Handle(fd), mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -215,7 +222,7 @@ func restoreAtInterrupt(fd uintptr, state *State) {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
_ = <-sigchan
|
_ = <-sigchan
|
||||||
RestoreTerminal(fd, state)
|
_ = RestoreTerminal(fd, state)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package windowsconsole // import "github.com/moby/term/windows"
|
package windowsconsole
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -31,7 +31,6 @@ type ansiReader struct {
|
||||||
// NewAnsiReader returns an io.ReadCloser that provides VT100 terminal emulation on top of a
|
// NewAnsiReader returns an io.ReadCloser that provides VT100 terminal emulation on top of a
|
||||||
// Windows console input handle.
|
// Windows console input handle.
|
||||||
func NewAnsiReader(nFile int) io.ReadCloser {
|
func NewAnsiReader(nFile int) io.ReadCloser {
|
||||||
initLogger()
|
|
||||||
file, fd := winterm.GetStdFile(nFile)
|
file, fd := winterm.GetStdFile(nFile)
|
||||||
return &ansiReader{
|
return &ansiReader{
|
||||||
file: file,
|
file: file,
|
||||||
|
@ -59,8 +58,6 @@ func (ar *ansiReader) Read(p []byte) (int, error) {
|
||||||
|
|
||||||
// Previously read bytes exist, read as much as we can and return
|
// Previously read bytes exist, read as much as we can and return
|
||||||
if len(ar.buffer) > 0 {
|
if len(ar.buffer) > 0 {
|
||||||
logger.Debugf("Reading previously cached bytes")
|
|
||||||
|
|
||||||
originalLength := len(ar.buffer)
|
originalLength := len(ar.buffer)
|
||||||
copiedLength := copy(p, ar.buffer)
|
copiedLength := copy(p, ar.buffer)
|
||||||
|
|
||||||
|
@ -70,16 +67,14 @@ func (ar *ansiReader) Read(p []byte) (int, error) {
|
||||||
ar.buffer = ar.buffer[copiedLength:]
|
ar.buffer = ar.buffer[copiedLength:]
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debugf("Read from cache p[%d]: % x", copiedLength, p)
|
|
||||||
return copiedLength, nil
|
return copiedLength, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and translate key events
|
// Read and translate key events
|
||||||
events, err := readInputEvents(ar.fd, len(p))
|
events, err := readInputEvents(ar, len(p))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
} else if len(events) == 0 {
|
} else if len(events) == 0 {
|
||||||
logger.Debug("No input events detected")
|
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,11 +82,9 @@ func (ar *ansiReader) Read(p []byte) (int, error) {
|
||||||
|
|
||||||
// Save excess bytes and right-size keyBytes
|
// Save excess bytes and right-size keyBytes
|
||||||
if len(keyBytes) > len(p) {
|
if len(keyBytes) > len(p) {
|
||||||
logger.Debugf("Received %d keyBytes, only room for %d bytes", len(keyBytes), len(p))
|
|
||||||
ar.buffer = keyBytes[len(p):]
|
ar.buffer = keyBytes[len(p):]
|
||||||
keyBytes = keyBytes[:len(p)]
|
keyBytes = keyBytes[:len(p)]
|
||||||
} else if len(keyBytes) == 0 {
|
} else if len(keyBytes) == 0 {
|
||||||
logger.Debug("No key bytes returned from the translator")
|
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,13 +93,11 @@ func (ar *ansiReader) Read(p []byte) (int, error) {
|
||||||
return 0, errors.New("unexpected copy length encountered")
|
return 0, errors.New("unexpected copy length encountered")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debugf("Read p[%d]: % x", copiedLength, p)
|
|
||||||
logger.Debugf("Read keyBytes[%d]: % x", copiedLength, keyBytes)
|
|
||||||
return copiedLength, nil
|
return copiedLength, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// readInputEvents polls until at least one event is available.
|
// readInputEvents polls until at least one event is available.
|
||||||
func readInputEvents(fd uintptr, maxBytes int) ([]winterm.INPUT_RECORD, error) {
|
func readInputEvents(ar *ansiReader, maxBytes int) ([]winterm.INPUT_RECORD, error) {
|
||||||
// Determine the maximum number of records to retrieve
|
// Determine the maximum number of records to retrieve
|
||||||
// -- Cast around the type system to obtain the size of a single INPUT_RECORD.
|
// -- Cast around the type system to obtain the size of a single INPUT_RECORD.
|
||||||
// unsafe.Sizeof requires an expression vs. a type-reference; the casting
|
// unsafe.Sizeof requires an expression vs. a type-reference; the casting
|
||||||
|
@ -118,25 +109,23 @@ func readInputEvents(fd uintptr, maxBytes int) ([]winterm.INPUT_RECORD, error) {
|
||||||
} else if countRecords == 0 {
|
} else if countRecords == 0 {
|
||||||
countRecords = 1
|
countRecords = 1
|
||||||
}
|
}
|
||||||
logger.Debugf("[windows] readInputEvents: Reading %v records (buffer size %v, record size %v)", countRecords, maxBytes, recordSize)
|
|
||||||
|
|
||||||
// Wait for and read input events
|
// Wait for and read input events
|
||||||
events := make([]winterm.INPUT_RECORD, countRecords)
|
events := make([]winterm.INPUT_RECORD, countRecords)
|
||||||
nEvents := uint32(0)
|
nEvents := uint32(0)
|
||||||
eventsExist, err := winterm.WaitForSingleObject(fd, winterm.WAIT_INFINITE)
|
eventsExist, err := winterm.WaitForSingleObject(ar.fd, winterm.WAIT_INFINITE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if eventsExist {
|
if eventsExist {
|
||||||
err = winterm.ReadConsoleInput(fd, events, &nEvents)
|
err = winterm.ReadConsoleInput(ar.fd, events, &nEvents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a slice restricted to the number of returned records
|
// Return a slice restricted to the number of returned records
|
||||||
logger.Debugf("[windows] readInputEvents: Read %v events", nEvents)
|
|
||||||
return events[:nEvents], nil
|
return events[:nEvents], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package windowsconsole // import "github.com/moby/term/windows"
|
package windowsconsole
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
@ -24,7 +24,6 @@ type ansiWriter struct {
|
||||||
// NewAnsiWriter returns an io.Writer that provides VT100 terminal emulation on top of a
|
// NewAnsiWriter returns an io.Writer that provides VT100 terminal emulation on top of a
|
||||||
// Windows console output handle.
|
// Windows console output handle.
|
||||||
func NewAnsiWriter(nFile int) io.Writer {
|
func NewAnsiWriter(nFile int) io.Writer {
|
||||||
initLogger()
|
|
||||||
file, fd := winterm.GetStdFile(nFile)
|
file, fd := winterm.GetStdFile(nFile)
|
||||||
info, err := winterm.GetConsoleScreenBufferInfo(fd)
|
info, err := winterm.GetConsoleScreenBufferInfo(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -32,9 +31,8 @@ func NewAnsiWriter(nFile int) io.Writer {
|
||||||
}
|
}
|
||||||
|
|
||||||
parser := ansiterm.CreateParser("Ground", winterm.CreateWinEventHandler(fd, file))
|
parser := ansiterm.CreateParser("Ground", winterm.CreateWinEventHandler(fd, file))
|
||||||
logger.Infof("newAnsiWriter: parser %p", parser)
|
|
||||||
|
|
||||||
aw := &ansiWriter{
|
return &ansiWriter{
|
||||||
file: file,
|
file: file,
|
||||||
fd: fd,
|
fd: fd,
|
||||||
infoReset: info,
|
infoReset: info,
|
||||||
|
@ -42,10 +40,6 @@ func NewAnsiWriter(nFile int) io.Writer {
|
||||||
escapeSequence: []byte(ansiterm.KEY_ESC_CSI),
|
escapeSequence: []byte(ansiterm.KEY_ESC_CSI),
|
||||||
parser: parser,
|
parser: parser,
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("newAnsiWriter: aw.parser %p", aw.parser)
|
|
||||||
logger.Infof("newAnsiWriter: %v", aw)
|
|
||||||
return aw
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aw *ansiWriter) Fd() uintptr {
|
func (aw *ansiWriter) Fd() uintptr {
|
||||||
|
@ -58,7 +52,5 @@ func (aw *ansiWriter) Write(p []byte) (total int, err error) {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("Write: % x", p)
|
|
||||||
logger.Infof("Write: %s", string(p))
|
|
||||||
return aw.parser.Parse(p)
|
return aw.parser.Parse(p)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package windowsconsole // import "github.com/moby/term/windows"
|
package windowsconsole
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/Azure/go-ansiterm/winterm"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetHandleInfo returns file descriptor and bool indicating whether the file is a console.
|
// GetHandleInfo returns file descriptor and bool indicating whether the file is a console.
|
||||||
|
@ -22,14 +22,18 @@ func GetHandleInfo(in interface{}) (uintptr, bool) {
|
||||||
|
|
||||||
if file, ok := in.(*os.File); ok {
|
if file, ok := in.(*os.File); ok {
|
||||||
inFd = file.Fd()
|
inFd = file.Fd()
|
||||||
isTerminal = IsConsole(inFd)
|
isTerminal = isConsole(inFd)
|
||||||
}
|
}
|
||||||
return inFd, isTerminal
|
return inFd, isTerminal
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsConsole returns true if the given file descriptor is a Windows Console.
|
// IsConsole returns true if the given file descriptor is a Windows Console.
|
||||||
// The code assumes that GetConsoleMode will return an error for file descriptors that are not a console.
|
// The code assumes that GetConsoleMode will return an error for file descriptors that are not a console.
|
||||||
func IsConsole(fd uintptr) bool {
|
// Deprecated: use golang.org/x/sys/windows.GetConsoleMode() or golang.org/x/crypto/ssh/terminal.IsTerminal()
|
||||||
_, e := winterm.GetConsoleMode(fd)
|
var IsConsole = isConsole
|
||||||
return e == nil
|
|
||||||
|
func isConsole(fd uintptr) bool {
|
||||||
|
var mode uint32
|
||||||
|
err := windows.GetConsoleMode(windows.Handle(fd), &mode)
|
||||||
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
// +build windows
|
|
||||||
// These files implement ANSI-aware input and output streams for use by the Docker Windows client.
|
|
||||||
// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create
|
|
||||||
// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls.
|
|
||||||
|
|
||||||
package windowsconsole // import "github.com/moby/term/windows"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
ansiterm "github.com/Azure/go-ansiterm"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
var logger *logrus.Logger
|
|
||||||
var initOnce sync.Once
|
|
||||||
|
|
||||||
func initLogger() {
|
|
||||||
initOnce.Do(func() {
|
|
||||||
logFile := ioutil.Discard
|
|
||||||
|
|
||||||
if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" {
|
|
||||||
logFile, _ = os.Create("ansiReaderWriter.log")
|
|
||||||
}
|
|
||||||
|
|
||||||
logger = &logrus.Logger{
|
|
||||||
Out: logFile,
|
|
||||||
Formatter: new(logrus.TextFormatter),
|
|
||||||
Level: logrus.DebugLevel,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
Reference in New Issue