fix(input): leave navigate mode on ctrl+[ - #2340
Conversation
📝 WalkthroughWalkthroughNavigate-mode cancellation now supports Ctrl+[ as a fallback after navigation bindings are checked. Escape and prefix keys retain immediate cancellation. Ctrl+Shift+[ remains non-canceling. Runtime and test handlers apply the same behavior. ChangesNavigation input handling
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Greptile SummaryThis PR makes Ctrl+[ cancel navigate mode when no configured navigate binding consumes it, while preserving Ctrl+Shift+[ and custom Ctrl+[ bindings.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| src/app/input/navigate.rs | Adds post-dispatch Ctrl+[ cancellation with regression coverage while preserving existing Escape behavior and configured binding precedence. |
Reviews (4): Last reviewed commit: "Merge branch 'master' into fix/1431-ctrl..." | Re-trigger Greptile
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/app/input/navigate.rs (1)
1312-1312: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover both navigation handlers.
The new tests call
App::handle_navigate_keyonly. Line 1312 changes the separatehandle_navigate_key(&mut AppState, KeyEvent)handler. Add equivalentCtrl+[andCtrl+Shift+[assertions through that handler so the two paths cannot diverge.Suggested additional coverage
+ #[test] + fn state_navigate_mode_cancel_keys_match_app_handler() { + let mut state = state_with_workspaces(&["one", "two"]); + state.mode = Mode::Navigate; + handle_navigate_key( + &mut state, + KeyEvent::new(KeyCode::Char('['), KeyModifiers::CONTROL), + ); + assert_eq!(state.mode, Mode::Terminal); + + state.mode = Mode::Navigate; + handle_navigate_key( + &mut state, + KeyEvent::new( + KeyCode::Char('['), + KeyModifiers::CONTROL | KeyModifiers::SHIFT, + ), + ); + assert_eq!(state.mode, Mode::Navigate); + }Also applies to: 2907-2932
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 6ac4deea-63fe-4cd6-bc83-4e32e490b329
📒 Files selected for processing (1)
src/app/input/navigate.rs
ogulcancelik
left a comment
There was a problem hiding this comment.
requesting changes because this currently overrides valid user configuration.
ctrl+[ is checked before navigate-mode keybinding dispatch, so any existing ctrl+[ binding is ignored while navigate mode is open. please treat it as a fallback cancel key only when no configured binding matched.
please cover both paths: unbound ctrl+[ cancels navigate mode, and a configured ctrl+[ binding still runs.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/app/input/navigate.rs (1)
1317-1337: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd tests for the state-only navigation handler.
handle_navigate_key(&mut AppState, KeyEvent)has a separate conversion and dispatch path. The new precedence test at Lines [2931-2943] covers onlyApp::handle_navigate_key(TerminalKey). Add equivalent tests through theKeyEvententry point for unboundCtrl+[, a configuredCtrl+[binding, andCtrl+Shift+[. This prevents the two handlers from diverging.As per coding guidelines, keep unit tests next to the Rust code in
#[cfg(test)] mod tests.Also applies to: 2931-2943
Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 75966db5-3886-40ce-8eb5-694f825749b0
📒 Files selected for processing (1)
src/app/input/navigate.rs
|
Good catch,
Both paths are covered:
The second test fails if the check is moved back above dispatch, so it pins the ordering rather than just passing. |
Ctrl+[ is the terminal-level equivalent of Esc, but navigate mode only checked
KeyCode::Esc, so the mode stayed open.On a legacy terminal Ctrl+[ sends 0x1b and already arrives as
KeyCode::Esc, which is why this works for some people. Under the kitty keyboard protocol, which Herdr negotiates, the modified key is reported on its own and reaches the handler asChar('[')with CONTROL, so the Esc check missed it. The report came from foot, which speaks that protocol.Adds
is_navigate_cancel_keyand uses it where navigate mode tested for Esc. Ctrl+Shift+[ keeps its own meaning because the match requires CONTROL alone.Prefix mode needs no matching change. It already falls through to
leave_command_modefor any unbound key, so Ctrl+[ cancels it today, and adding the same check there would shadow a custom Ctrl+[ binding under Prefix dispatch.No doc change looks needed: the keyboard docs do not currently mention Esc for navigate mode. Happy to add one if you want the alias documented.
Checks on 1.96.1:
cargo fmt --checkandcargo clippy --all-targets --locked -- -D warningsare clean.cargo nextest run --lockedis 3179/3181; the two failures,live_handoff::live_server_holds_one_pty_master_fd_per_paneandterminal::state::metadata::tests::metadata_clear_only_without_ttl_does_not_extend_old_ttl, fail the same way on unmodified master in my environment. I ran this in a Linux container because zig 0.15.2 cannot build the vendored libghostty-vt on macOS 26, sojust windows-lintis untested here; the change is not platform-gated.refs #1431