-
-
Save sweetbbak/1ccf73db60f899510236f948ef29d0ad 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