Files
clide/assets/keymaps/default.yaml
T
jpmschweitzerandClaude Opus 4.7 798ba524f1 keystroke mapper layer — intents, presets, when-clauses (T-117)
Build the upstream of every keyboard-driven feature: widgets bind
to typed Intents, the keymap resolves chord+context to an Intent,
and Flutter's Actions dispatches. The widget never touches a key.

Layers (low → high precedence):
  1. preset YAML in assets/keymaps/<preset>.yaml
  2. extension-registered command bindings (via
     KeymapService.registerCommandBinding from ExtensionManager)
  3. user file at <appDir>/keybindings.yaml
  4. settings JSON overlay at app.keymap.overrides

The when-clause grammar is a tiny recursive-descent parser over
boolean expressions on a named context bag — VS-Code style
`palette.open && !textInputFocused`. Producing services publish
scope flags via setScopeFlag.

Keys reference LogicalKeyboardKey.keyId (stable across keyboard
layouts), not the locale-aware keyLabel the consultant flagged.

Ships:
  - lib/kernel/src/keymap/{key_chord, when_clause, intents, keymap,
    keymap_service}.dart
  - assets/keymaps/default.yaml (the baseline preset)
  - 90+ unit tests covering parser precedence, layering precedence,
    scope evaluation, register/unregister, settings overlay,
    malformed-input tolerance
  - app.dart root handler routes through KeymapService → Actions
  - ExtensionManager mirrors every legacy defaultBinding into the
    keymap as a contribution layer

KeybindingResolver kept temporarily as a back-compat shim for
callers we haven't migrated yet; safe to delete once the last
caller goes through Actions.

Closes T-110 (consultant: scoped Shortcuts/Actions; off keyLabel).
Annotates T-23 with what's left for T-100. Unblocks T-64 / T-65 /
T-66 (preset data tickets).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 21:40:02 +02:00

57 lines
1.8 KiB
YAML

# clide default keymap.
#
# This is the baseline preset. Vim / VSCode / JetBrains presets are
# their own files (T-64/T-65/T-66) and replace bindings via the same
# YAML shape.
#
# Each binding:
# intent: <stable intent id> # see kernel/src/keymap/intents.dart
# keys: <chord> | [<chord>, ...] # `ctrl+shift+p`, `cmd+enter`, ...
# when: <when-clause> # optional; VS-Code-style boolean expr
#
# Identifiers in `when:` are scope flags published by producing
# services (e.g. `palette.open` when ClidePalette is mounted +
# visible). Missing flags evaluate to false.
name: default
bindings:
# -- Activation / focus -----------------------------------------------
- intent: activate
keys: [enter, space]
when: focused.tappable
- intent: dismiss
keys: escape
- intent: focus.next
keys: tab
when: '!textInputFocused'
- intent: focus.previous
keys: shift+tab
when: '!textInputFocused'
# -- Command palette --------------------------------------------------
- intent: palette.open
keys: [ctrl+shift+p, meta+shift+p]
- intent: palette.selectNext
keys: [down, ctrl+n]
when: palette.open
- intent: palette.selectPrevious
keys: [up, ctrl+p]
when: palette.open
- intent: palette.accept
keys: enter
when: palette.open
- intent: dismiss
keys: escape
when: palette.open
# -- Text scale -------------------------------------------------------
# On most layouts `+` is `shift+equal`; we bind both so users who
# think of it as Ctrl+Plus and users who hit Ctrl+= both work.
- intent: text.scaleIncrease
keys: [ctrl+equal, ctrl+shift+equal, meta+equal, meta+shift+equal]
- intent: text.scaleDecrease
keys: [ctrl+minus, meta+minus]
- intent: text.scaleReset
keys: [ctrl+0, meta+0]