lattice_host/keymap_registry.rs
1//! Re-export shim ā `KeymapCapability`, `KeymapError`,
2//! `KeymapHandle`, `KeymapRegistry`, `LayerId`, and
3//! `PushLayerKind` moved to `lattice-keymap` in K.3
4//! (2026-06-07). `KeymapReverseLookupHandle` stays here
5//! because it implements `lattice_completion::KeymapReverseLookup`
6//! ā `lattice-keymap` cannot depend on `lattice-completion`.
7pub use lattice_keymap::{
8 KeymapCapability, KeymapError, KeymapHandle, KeymapRegistry, LayerId, PushLayerKind,
9};
10
11use std::sync::Arc;
12
13use lattice_completion::{KeybindingSource, KeymapReverseLookup};
14use lattice_keymap::KeymapLayer;
15use lattice_protocol::KeyChord;
16
17/// MARG.2 (2026-06-03): adapter that implements
18/// [`lattice_completion::KeymapReverseLookup`] over a
19/// [`KeymapRegistry`]'s reverse cache + a [`CommandRegistry`]
20/// for the canonical-name ā [`CommandId`] resolution. Editor
21/// boot constructs one and passes it to
22/// [`lattice_completion::KeybindingAnnotator::new`].
23///
24/// The adapter holds Arc clones of both registries; cache
25/// loads are wait-free via `ArcSwap::load`.
26///
27/// MARG.3 (2026-07-15): the reverse cache now carries
28/// [`KeymapLayer`] provenance alongside each chord, and
29/// [`chords_with_source`](KeymapReverseLookup::chords_with_source)
30/// converts layers to [`KeybindingSource`] for the picker's
31/// mode-aware filtering + provenance column.
32pub struct KeymapReverseLookupHandle {
33 // MARG.3: the reverse cache carries `KeymapLayer` provenance per chord.
34 /// (Cā²) The handle, not a raw `ArcSwap` clone: reads must go
35 /// through `reverse_entries`, which freshens the lazily-rebuilt
36 /// derived state first. Holding the `ArcSwap` directly would read
37 /// a cache a pending `bind` has already invalidated.
38 keymap: KeymapHandle,
39 // B3b: the `ArcSwap` handle so a plugin command's keybinding annotation
40 // resolves against runtime registrations too; `.load()` per lookup.
41 command_registry: lattice_grammar::CommandRegistryHandle,
42}
43
44impl KeymapReverseLookupHandle {
45 /// Construct from a `KeymapHandle`'s reverse cache and a
46 /// command registry. Editor boot calls this once after the
47 /// builtin catalog is registered.
48 pub fn new(
49 handle: &KeymapHandle,
50 command_registry: lattice_grammar::CommandRegistryHandle,
51 ) -> Arc<Self> {
52 Arc::new(Self {
53 keymap: handle.clone(),
54 command_registry,
55 })
56 }
57}
58
59impl KeymapReverseLookup for KeymapReverseLookupHandle {
60 fn chords_for(&self, command_name: &str) -> Vec<KeyChord> {
61 let Some(id) = self.command_registry.load().id_by_name(command_name) else {
62 return Vec::new();
63 };
64 self.keymap
65 .reverse_entries(id)
66 .into_iter()
67 .map(|(c, _)| c)
68 .collect()
69 }
70
71 fn chords_with_source(&self, command_name: &str) -> Vec<(KeyChord, KeybindingSource)> {
72 let Some(id) = self.command_registry.load().id_by_name(command_name) else {
73 return Vec::new();
74 };
75 let entries = self.keymap.reverse_entries(id);
76 Some(&entries)
77 .map(|entries| {
78 entries
79 .iter()
80 .map(|(chord, layer)| (*chord, layer_to_source(*layer)))
81 .collect()
82 })
83 .unwrap_or_default()
84 }
85}
86
87fn layer_to_source(layer: KeymapLayer) -> KeybindingSource {
88 match layer {
89 KeymapLayer::Builtin | KeymapLayer::User | KeymapLayer::Buffer => {
90 KeybindingSource::AlwaysOn
91 }
92 KeymapLayer::MajorMode(mode_id) | KeymapLayer::MinorMode(mode_id) => {
93 KeybindingSource::Mode(Arc::from(mode_id.as_str()))
94 }
95 }
96}