0818b5e318
- update the readline package to have basic support on windows, this is not full feature parity with the unix cli yet
62 lines
1.8 KiB
Go
62 lines
1.8 KiB
Go
package readline
|
|
|
|
import (
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
const (
|
|
enableLineInput = 2
|
|
enableWindowInput = 8
|
|
enableMouseInput = 16
|
|
enableInsertMode = 32
|
|
enableQuickEditMode = 64
|
|
enableExtendedFlags = 128
|
|
enableProcessedOutput = 1
|
|
enableWrapAtEolOutput = 2
|
|
enableAutoPosition = 256 // Cursor position is not affected by writing data to the console.
|
|
enableEchoInput = 4 // Characters are written to the console as they're read.
|
|
enableProcessedInput = 1 // Enables input processing (like recognizing Ctrl+C).
|
|
)
|
|
|
|
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
|
|
var (
|
|
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
|
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
|
|
)
|
|
|
|
type State struct {
|
|
mode uint32
|
|
}
|
|
|
|
// IsTerminal checks if the given file descriptor is associated with a terminal
|
|
func IsTerminal(fd int) bool {
|
|
var st uint32
|
|
r, _, e := syscall.SyscallN(procGetConsoleMode.Addr(), uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
|
|
// if the call succeeds and doesn't produce an error, it's a terminal
|
|
return r != 0 && e == 0
|
|
}
|
|
|
|
func SetRawMode(fd int) (*State, error) {
|
|
var st uint32
|
|
// retrieve the current mode of the terminal
|
|
_, _, e := syscall.SyscallN(procGetConsoleMode.Addr(), uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
|
|
if e != 0 {
|
|
return nil, error(e)
|
|
}
|
|
// modify the mode to set it to raw
|
|
raw := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput)
|
|
// apply the new mode to the terminal
|
|
_, _, e = syscall.SyscallN(procSetConsoleMode.Addr(), uintptr(fd), uintptr(raw), 0)
|
|
if e != 0 {
|
|
return nil, error(e)
|
|
}
|
|
// return the original state so that it can be restored later
|
|
return &State{st}, nil
|
|
}
|
|
|
|
func UnsetRawMode(fd int, state *State) error {
|
|
_, _, err := syscall.SyscallN(procSetConsoleMode.Addr(), uintptr(fd), uintptr(state.mode), 0)
|
|
return err
|
|
}
|