1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- 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
- }
|