Add Ctrl+C quit handling to REPL

- Add _quit_requested flag to TerminalDisplay
- Add request_quit() method to TerminalDisplay
- Handle 'ctrl_c' key in REPL input loops in both pipeline_runner.py and main.py
- When Ctrl+C is pressed, request_quit() is called which sets the flag
- The main loop checks is_quit_requested() and raises KeyboardInterrupt
This commit is contained in:
2026-03-22 16:48:05 -07:00
parent d5406a6b11
commit a050e26c03
3 changed files with 21 additions and 4 deletions

View File

@@ -550,7 +550,13 @@ def run_pipeline_mode_direct():
keys = display.get_input_keys(timeout=0.0) keys = display.get_input_keys(timeout=0.0)
for key in keys: for key in keys:
if key == "return": if key == "ctrl_c":
# Request quit when Ctrl+C is pressed
if hasattr(display, "request_quit"):
display.request_quit()
else:
raise KeyboardInterrupt()
elif key == "return":
# Get command string before processing # Get command string before processing
cmd_str = repl_effect.state.current_command cmd_str = repl_effect.state.current_command
if cmd_str: if cmd_str:

View File

@@ -986,7 +986,13 @@ def run_pipeline_mode(preset_name: str = "demo", graph_config: str | None = None
keys = display.get_input_keys(timeout=0.0) keys = display.get_input_keys(timeout=0.0)
for key in keys: for key in keys:
if key == "return": if key == "ctrl_c":
# Request quit when Ctrl+C is pressed
if hasattr(display, "request_quit"):
display.request_quit()
else:
raise KeyboardInterrupt()
elif key == "return":
# Get command string before processing # Get command string before processing
cmd_str = repl_effect.state.current_command cmd_str = repl_effect.state.current_command
if cmd_str: if cmd_str:

View File

@@ -28,6 +28,7 @@ class TerminalDisplay:
self._cached_dimensions: tuple[int, int] | None = None self._cached_dimensions: tuple[int, int] | None = None
self._raw_mode_enabled: bool = False self._raw_mode_enabled: bool = False
self._original_termios: list = [] self._original_termios: list = []
self._quit_requested: bool = False
def init(self, width: int, height: int, reuse: bool = False) -> None: def init(self, width: int, height: int, reuse: bool = False) -> None:
"""Initialize display with dimensions. """Initialize display with dimensions.
@@ -163,11 +164,15 @@ class TerminalDisplay:
def is_quit_requested(self) -> bool: def is_quit_requested(self) -> bool:
"""Check if quit was requested (optional protocol method).""" """Check if quit was requested (optional protocol method)."""
return False return self._quit_requested
def clear_quit_request(self) -> None: def clear_quit_request(self) -> None:
"""Clear quit request (optional protocol method).""" """Clear quit request (optional protocol method)."""
pass self._quit_requested = False
def request_quit(self) -> None:
"""Request quit (e.g., when Ctrl+C is pressed)."""
self._quit_requested = True
def set_raw_mode(self, enable: bool = True) -> None: def set_raw_mode(self, enable: bool = True) -> None:
"""Enable/disable raw terminal mode for input capture. """Enable/disable raw terminal mode for input capture.