Expand description
The editor’s keymap engine: the chord trie, the layered runtime
registry every keystroke resolves against, the built-in vim keymap
catalog, and the introspection models (:describe-key, which-key)
derived from them.
§What it owns
- Matching —
KeymapTrie: one layer’s bindings,O(prefix)lookup toLookupResult::Bound/Partial/Unbound, with a{char}wildcard (ChordPattern::CharLiteral) for marks, registers and find-char. - Layering —
KeymapRegistrybehindKeymapHandle: fiveKeymapLayers (Builtin < MajorMode < MinorMode < User < Buffer), one trie perBindingModeper layer, wait-free reads and capability-gated writes (KeymapCapability). Mode layers are gated by the active buffer’sModeIds (KeymapHandle::lookup_with_context). - Declaration —
Keymap/KeymapBinding, a mode’s declarative contribution, and thekeymap_entry!static-table form (KeymapEntry) with the built-in catalog indefault_keymap. - Introspection —
KeymapResolution/Continuationfor:describe-key;which_key’sWhichKeyModeland layout; thePartialChordPendingevent which-key subscribes to.
§What it must not depend on
Dependency position in the workspace: lattice-protocol → lattice-grammar → lattice-keymap → lattice-mode → lattice-host
Nothing in this crate may import from lattice-mode or lattice-host.
It is its own crate so the trie, the layer enum and the binding types
can be named by lattice-mode (whose Mode::keymap returns a
Keymap) without a cycle, and so the keystroke-path matcher carries
no editor state, renderer or I/O — everything here is testable with a
hand-built trie and no host.
§Examples
Bind a builtin chord and a mode override, then resolve a keystroke the way the dispatcher does:
use lattice_grammar::{CommandId, CommandInvocation, SourceLocation};
use lattice_keymap::{
BindingMode, KeymapCapability, KeymapHandle, KeymapLayer, LookupResult, ModeId,
};
use lattice_protocol::parse_chord_sequence;
let keymap = KeymapHandle::new();
let bind = |layer, chord, id| {
keymap.try_bind_chord_string(KeymapCapability::Full, layer, BindingMode::Normal, chord,
CommandInvocation::of(CommandId::new(id)), SourceLocation::synthetic("doc")).unwrap()
};
bind(KeymapLayer::Builtin, "<C-w>v", 1);
bind(KeymapLayer::MinorMode(ModeId::new("magit-mode")), "<C-w>v", 2);
let keys = parse_chord_sequence("<C-w>v").unwrap();
let resolve = |active: &[ModeId]| match keymap.lookup_with_context(BindingMode::Normal, &keys, active) {
LookupResult::Bound { command, .. } => command.command.command,
other => panic!("{other:?}"),
};
assert_eq!(resolve(&[]), CommandId::new(1));
assert_eq!(resolve(&[ModeId::new("magit-mode")]), CommandId::new(2));
// `:describe-key` sees both layers, and which one fires here.
let trace = keymap.resolve_trace(BindingMode::Normal, &keys, &[]);
assert_eq!(trace.hits.len(), 2);
assert_eq!(trace.winner().unwrap().layer, KeymapLayer::Builtin);§Design
docs/dev/architecture/keymap-architecture.md— layers, merge on write, capabilities, the motion mirror.docs/dev/architecture/which-key.md— thewhich_keymodel.docs/dev/architecture/design.md§5.2.3 — the five-layer model.
Re-exports§
pub use binding_mode::BindingMode;pub use contribution::Keymap;pub use contribution::KeymapBinding;pub use keymap_entry::KeymapEntry;pub use keymap_entry::default_keymap;pub use keymap_entry::entries;pub use keymap_entry::lookup;pub use mode_id::ModeId;pub use trie::BoundCommand;pub use trie::KeymapLayer;pub use trie::KeymapTrie;pub use trie::LookupResult;pub use registry::DEFAULT_LEADER;pub use registry::KeymapCapability;pub use registry::KeymapError;pub use registry::KeymapHandle;pub use registry::KeymapRegistry;pub use registry::LayerId;pub use registry::PushLayerKind;pub use registry::expand_leader;pub use registry::overtypes_in_select;pub use resolution::Continuation;pub use resolution::KeymapResolution;pub use resolution::LayerHit;pub use resolution::parse_describe_key_arg;pub use events::PartialChordPending;pub use trie::ChildView;pub use trie::NodeView;pub use which_key::Entry;pub use which_key::EntryKind;pub use which_key::Sort;pub use which_key::WhichKeyModel;pub use which_key::build_model;
Modules§
- binding_
mode BindingMode— the vim-modal state a chord resolves in.- contribution
KeymapandKeymapBinding— a mode’s declarative keymap contribution.- events
- WK.4: typed events about chords.
- keymap_
entry - Static keymap catalog +
keymap_entry!macro (DESIGN.md §5.2.3). - mode_id
ModeId— canonical interned-string identity for a mode.- registry
KeymapRegistry– the public, layered keymap engine the input dispatcher consults. Audit slice 8.c of the M3 refactor; seedocs/dev/architecture/keymap-architecture.mdfor the design.- resolution
KeymapResolution— trace result forresolve_traceandresolve_trace_all_modes.- trie
KeymapTrie– the lookup data structure the keymap registry consults on the keystroke path. Audit slice 8.b of the M3 refactor; seedocs/dev/architecture/keymap-architecture.mdfor the design.- which_
key - Which-key’s resolver — prefix → continuation model.
Macros§
- keymap_
entry - Construct a
KeymapEntrywith the row’s source location captured at the macro invocation site. Forms:
Enums§
- Chord
Pattern - One element of a keymap registration path.