vim normal-mode navigation in non-editor panes (T-406)
The structural T-403 child: make vim normal mode mean navigation in panes that were mouse-only. The passive global key path can't run multi-chord sequences (D-82), so each pane hosts its own SequenceMatcher — factored into a reusable PaneKeyNav that resolves the live keymap and dispatches nav.* intents while a pane holds focus under the vim preset. - nav.* intents (down/up/pageDown/pageUp/top/bottom/expandOrRight/ collapseOrLeft/activate) — preset-neutral; vim.yaml binds j/k/ctrl+d/ctrl+u/ gg/G/l/h/[o,enter] under `vim.normal && !editor.focused`. - The editor publishes an `editor.focused` scope flag from its focus node, so the same keys stay buffer motions while the editor is focused and become nav when a pane is — resolved by file order + the guard (no change to the editor motion bindings). - File tree: a flattened visible-index selection cursor in FileTreeController (j/k move, h collapse-or-out, l expand-or-into, o/enter open), with a focus ring + scroll-into-view. - Conversation: j/k line-scroll, ctrl+d/u half-page, gg top, G bottom — G re-arms follow-tail. Foundation for T-404/T-405/T-407, which build on the per-pane matcher and the editor.focused guard. Git panel + ticket board list nav deferred to a follow-up (the ticket says lists can trail). Tests: keymap resolution under both scopes, PaneKeyNav dispatch, the controller selection model, and end-to-end key-driven nav in both panes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -63,6 +63,43 @@ bindings:
|
||||
- intent: text.scaleReset
|
||||
keys: [ctrl+0, meta+0]
|
||||
|
||||
# ---- Pane navigation (non-editor panes) ------------------------------
|
||||
# When a non-editor pane holds focus (file tree, conversation, lists), the
|
||||
# same motion keys mean NAVIGATION, not buffer edits (T-406). The
|
||||
# `!editor.focused` guard keeps these out of the editor's way; the editor
|
||||
# publishes `editor.focused` while it has focus. These MUST precede the
|
||||
# editor motions below — the resolver takes the first matching binding in
|
||||
# file order, so with a pane focused (editor.focused false) nav wins, and
|
||||
# with the editor focused the `!editor.focused` clause fails and the buffer
|
||||
# motion below wins. Each pane runs its own SequenceMatcher (PaneKeyNav).
|
||||
- intent: nav.down
|
||||
keys: j
|
||||
when: "vim.normal && !editor.focused"
|
||||
- intent: nav.up
|
||||
keys: k
|
||||
when: "vim.normal && !editor.focused"
|
||||
- intent: nav.pageDown
|
||||
keys: ctrl+d
|
||||
when: "vim.normal && !editor.focused"
|
||||
- intent: nav.pageUp
|
||||
keys: ctrl+u
|
||||
when: "vim.normal && !editor.focused"
|
||||
- intent: nav.top
|
||||
keys: "g g" # gg
|
||||
when: "vim.normal && !editor.focused"
|
||||
- intent: nav.bottom
|
||||
keys: shift+g # G
|
||||
when: "vim.normal && !editor.focused"
|
||||
- intent: nav.expandOrRight
|
||||
keys: l
|
||||
when: "vim.normal && !editor.focused"
|
||||
- intent: nav.collapseOrLeft
|
||||
keys: h
|
||||
when: "vim.normal && !editor.focused"
|
||||
- intent: nav.activate
|
||||
keys: [o, enter]
|
||||
when: "vim.normal && !editor.focused"
|
||||
|
||||
# ---- Mode transitions ------------------------------------------------
|
||||
- intent: command:vim.mode.visual
|
||||
keys: v
|
||||
|
||||
Reference in New Issue
Block a user