From f1eb14662f186f7d4ac165848fb1527abc16e3c4 Mon Sep 17 00:00:00 2001 From: Manuel Goepfi Date: Wed, 29 Apr 2026 08:45:19 +0200 Subject: [PATCH] fix(tui): make Ctrl+L and Ctrl+N fire from chat input via priority bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screen-level `Binding(...)` declarations are consultative by default — focused widgets get first crack at every keypress and can swallow it. The chat input (a TextArea descendant) inherits readline-style bindings that consume Ctrl+L (clear-line) and Ctrl+N (next-line), so those keypresses never reach `action_toggle_ltm` / `action_new_chat`. The visible symptom was that pressing Ctrl+L appeared to do nothing until the user opened another modal (e.g. Ctrl+Shift+M model selection) which transferred focus off the input. After that modal closed, focus landed on the screen and Ctrl+L finally bubbled up to the binding. Adding `priority=True` to both bindings tells Textual to fire the screen action before the focused widget gets to consume the key, so the shortcut works regardless of where focus currently lives. Ctrl+Shift+M (change model), Ctrl+Shift+W (workstream), and Ctrl+C (stop streaming) keep their default priority: the first two are rare enough that no widget binds them; Ctrl+C in Textual is special-cased and elevating it could interfere with focus-aware copy/cancel flows. --- src/pieces/tui/views/copilot_view.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pieces/tui/views/copilot_view.py b/src/pieces/tui/views/copilot_view.py index 27a2ecc8..7c81a85a 100644 --- a/src/pieces/tui/views/copilot_view.py +++ b/src/pieces/tui/views/copilot_view.py @@ -24,9 +24,16 @@ class PiecesCopilot(BaseDualPaneView): """Copilot/chat interface with consistent dual-pane layout.""" BINDINGS = [ - Binding("ctrl+n", "new_chat", "New Chat"), + # priority=True so these screen-level shortcuts fire even when + # the chat input has focus. Without it, common readline/terminal + # bindings inside the input (notably Ctrl+L = clear-line and + # Ctrl+N = next-line) silently swallow the keypress before it + # reaches the screen's action handler — the symptom is the + # action only firing after the user opens another modal that + # transfers focus away from the input. + Binding("ctrl+n", "new_chat", "New Chat", priority=True), Binding("ctrl+shift+m", "change_model", "Change Model"), - Binding("ctrl+l", "toggle_ltm", "Toggle LTM"), + Binding("ctrl+l", "toggle_ltm", "Toggle LTM", priority=True), Binding("ctrl+shift+w", "switch_to_workstream", "Switch to Workstream"), Binding("ctrl+c", "stop_streaming", "Stop Streaming"), ]