diff options
Diffstat (limited to 'internal/tui/keys.go')
| -rw-r--r-- | internal/tui/keys.go | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/internal/tui/keys.go b/internal/tui/keys.go new file mode 100644 index 0000000..e88a326 --- /dev/null +++ b/internal/tui/keys.go @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package tui + +import ( + "fmt" + "os" + + "golang.org/x/term" +) + +// ReadKey reads one keypress without Enter, restoring the terminal before +// it returns - on every path, including an error. It always reads a +// single byte; only a terminal is first put into raw mode, so a +// non-terminal (a pipe, in tests) needs no pty to exercise it. +func ReadKey(in *os.File) (rune, error) { + fd := int(in.Fd()) + if !isTerminal(fd) { + return readByte(in) + } + + state, err := term.MakeRaw(fd) + if err != nil { + return 0, fmt.Errorf("tui: %w", err) + } + defer term.Restore(fd, state) + + return readByte(in) +} + +func readByte(in *os.File) (rune, error) { + var b [1]byte + if _, err := in.Read(b[:]); err != nil { + return 0, err + } + return rune(b[0]), nil +} |
