diff --git a/.jules/palette.md b/.jules/palette.md new file mode 100644 index 0000000..ada6f97 --- /dev/null +++ b/.jules/palette.md @@ -0,0 +1,3 @@ +## 2024-06-22 - TUI Keyboard Trap Fix +**Learning:** When building terminal UIs with explicit raw mode reading (like bypassing `rich` prompt and using `tty.setraw`), standard interrupt combinations like Ctrl-C (`\x03`) do not raise `KeyboardInterrupt` by default. This causes a severe keyboard trap that prevents users from cleanly escaping out of selection states. +**Action:** Always intercept `\x03` explicitly when parsing raw keystrokes in terminal interactions and manually raise `KeyboardInterrupt` to preserve accessible escape hatches. diff --git a/libs/terminal_ui.py b/libs/terminal_ui.py index 47b8b3b..ef2adb3 100644 --- a/libs/terminal_ui.py +++ b/libs/terminal_ui.py @@ -19,6 +19,8 @@ def _read_key(self): if os.name == 'nt': import msvcrt key = msvcrt.getwch() + if key == '\x03': + raise KeyboardInterrupt('Selection cancelled by user.') if key in ('\x00', '\xe0'): extended = msvcrt.getwch() mapping = {'H': 'up', 'P': 'down', 'K': 'left', 'M': 'right'} @@ -37,6 +39,8 @@ def _read_key(self): try: tty.setraw(fd) key = sys.stdin.read(1) + if key == '\x03': + raise KeyboardInterrupt('Selection cancelled by user.') if key == '\x1b': next_chars = sys.stdin.read(2) mapping = {'[A': 'up', '[B': 'down', '[D': 'left', '[C': 'right'}