Skip to main content

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}