aboutsummaryrefslogtreecommitdiff
path: root/internal/tui/keys.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-12 20:14:47 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-12 20:14:47 +0200
commit3f8679be9373ee7508d512dfdfc1dda0839c7f90 (patch)
treeec02eb075f6c4e90f21baa2fe674e86a2f7f6a62 /internal/tui/keys.go
parent24a84671ace373ae331fa83a1ff484990f4dff0e (diff)
downloadkrino-3f8679be9373ee7508d512dfdfc1dda0839c7f90.tar.gz
krino-3f8679be9373ee7508d512dfdfc1dda0839c7f90.zip
krino: acting — trash, journal, apply, lock, review, undo
Diffstat (limited to 'internal/tui/keys.go')
-rw-r--r--internal/tui/keys.go37
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
+}