fix: treat ctrl-c as curses cancel

This commit is contained in:
wanazhar 2026-05-03 06:22:47 +00:00 committed by Teknium
parent ccb5d87076
commit df88375f0d
2 changed files with 15 additions and 1 deletions

View file

@ -156,6 +156,8 @@ def curses_checklist(
flush_stdin() flush_stdin()
return result_holder[0] if result_holder[0] is not None else cancel_returns return result_holder[0] if result_holder[0] is not None else cancel_returns
except KeyboardInterrupt:
return cancel_returns
except Exception: except Exception:
return _numbered_fallback(title, items, selected, cancel_returns, status_fn) return _numbered_fallback(title, items, selected, cancel_returns, status_fn)
@ -278,6 +280,8 @@ def curses_radiolist(
flush_stdin() flush_stdin()
return result_holder[0] if result_holder[0] is not None else cancel_returns return result_holder[0] if result_holder[0] is not None else cancel_returns
except KeyboardInterrupt:
return cancel_returns
except Exception: except Exception:
return _radio_numbered_fallback(title, items, selected, cancel_returns) return _radio_numbered_fallback(title, items, selected, cancel_returns)
@ -401,6 +405,8 @@ def curses_single_select(
return None return None
return result_holder[0] return result_holder[0]
except KeyboardInterrupt:
return None
except Exception: except Exception:
all_items = list(items) + [cancel_label] all_items = list(items) + [cancel_label]
cancel_idx = len(items) cancel_idx = len(items)

View file

@ -508,7 +508,7 @@ class TestPromptPluginEnvVars:
class TestCursesRadiolist: class TestCursesRadiolist:
"""Test the curses_radiolist function (non-TTY fallback path).""" """Test the curses_radiolist function."""
def test_non_tty_returns_default(self): def test_non_tty_returns_default(self):
from hermes_cli.curses_ui import curses_radiolist from hermes_cli.curses_ui import curses_radiolist
@ -524,6 +524,14 @@ class TestCursesRadiolist:
result = curses_radiolist("Pick", ["x", "y"], selected=0, cancel_returns=1) result = curses_radiolist("Pick", ["x", "y"], selected=0, cancel_returns=1)
assert result == 1 assert result == 1
def test_keyboard_interrupt_returns_cancel_value(self):
from hermes_cli.curses_ui import curses_radiolist
with patch("sys.stdin") as mock_stdin, patch("curses.wrapper", side_effect=KeyboardInterrupt):
mock_stdin.isatty.return_value = True
result = curses_radiolist("Pick", ["x", "y"], selected=0, cancel_returns=-1)
assert result == -1
# ── Provider discovery helpers ─────────────────────────────────────────── # ── Provider discovery helpers ───────────────────────────────────────────