-
-
Save kvaps/37de1fc4546d874a50dbf62dd9417046 to your computer and use it in GitHub Desktop.
syscall to set raw-mode-input terminal in Go (Posix/Windows)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// +build darwin linux | |
package main | |
import ( | |
"os" | |
"syscall" | |
"unsafe" | |
) | |
func getTermios(fd uintptr) *syscall.Termios { | |
var t syscall.Termios | |
_, _, err := syscall.Syscall6( | |
syscall.SYS_IOCTL, | |
os.Stdin.Fd(), | |
syscall.TCGETS, | |
uintptr(unsafe.Pointer(&t)), | |
0, 0, 0) | |
if err != 0 { | |
panic("err") | |
} | |
return &t | |
} | |
func setTermios(fd uintptr, term *syscall.Termios) { | |
_, _, err := syscall.Syscall6( | |
syscall.SYS_IOCTL, | |
os.Stdin.Fd(), | |
syscall.TCSETS, | |
uintptr(unsafe.Pointer(term)), | |
0,0,0) | |
if err != 0 { | |
panic("err") | |
} | |
} | |
func setRaw(term *syscall.Termios) { | |
// This attempts to replicate the behaviour documented for cfmakeraw in | |
// the termios(3) manpage. | |
term.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON | |
// newState.Oflag &^= syscall.OPOST | |
term.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN | |
term.Cflag &^= syscall.CSIZE | syscall.PARENB | |
term.Cflag |= syscall.CS8 | |
term.Cc[syscall.VMIN] = 1 | |
term.Cc[syscall.VTIME] = 0 | |
} | |
func main() { | |
t := getTermios(os.Stdin.Fd()) | |
origin := *t | |
defer func() { | |
setTermios(os.Stdin.Fd(), &origin) | |
}() | |
setRaw(t) | |
setTermios(os.Stdin.Fd(), t) | |
for i := 0; i < 3; i++{ | |
buf := make([]byte, 1) | |
syscall.Read(0, buf) | |
println(buf[0]) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"os" | |
"syscall" | |
"unsafe" | |
) | |
var kernel32 = syscall.NewLazyDLL("kernel32.dll") | |
var ( | |
procGetConsoleMode = kernel32.NewProc("GetConsoleMode") | |
procSetConsoleMode = kernel32.NewProc("SetConsoleMode") | |
) | |
const ( | |
enableLineInput = 2 | |
enableEchoInput = 4 | |
enableProcessedInput = 1 | |
enableWindowInput = 8 | |
enableMouseInput = 16 | |
enableInsertMode = 32 | |
enableQuickEditMode = 64 | |
enableExtendedFlags = 128 | |
enableAutoPosition = 256 | |
enableProcessedOutput = 1 | |
enableWrapAtEolOutput = 2 | |
) | |
func getTermMode(fd uintptr) uint32 { | |
var mode uint32 | |
_, _, err := syscall.Syscall( | |
procGetConsoleMode.Addr(), | |
2, | |
fd, | |
uintptr(unsafe.Pointer(&mode)), | |
0) | |
if err != 0 { | |
panic("err") | |
} | |
return mode | |
} | |
func setTermMode(fd uintptr, mode uint32) { | |
_, _, err := syscall.Syscall( | |
procSetConsoleMode.Addr(), | |
2, | |
fd, | |
uintptr(mode), | |
0) | |
if err != 0 { | |
panic("err") | |
} | |
} | |
func main() { | |
originMode := getTermMode(os.Stdin.Fd()) | |
defer func(m uint32) { | |
setTermMode(os.Stdin.Fd(), m) | |
}(originMode) | |
originMode &^= (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput) | |
setTermMode(os.Stdin.Fd(), originMode) | |
for i := 0; i < 3; i++{ | |
buf := make([]byte, 1) | |
syscall.Read(syscall.Handle(os.Stdin.Fd()), buf) | |
println(buf[0]) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment