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>
57 lines
1.8 KiB
YAML
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]
|