Skip to main content

Keymap

Struct Keymap 

pub struct Keymap {
    pub bindings: Vec<KeymapBinding>,
    pub entries: Vec<&'static KeymapEntry>,
}
Expand description

A mode’s full keymap contribution.

Keymap::default() is the empty contribution – modes that don’t ship bindings rely on the lattice_mode::Mode::keymap trait default.

Two declaration paths share the same contribution shape:

  1. Chain form — Keymap::new().bind_chord(...) / .bind(...). Terse; ergonomic for 1-5 bindings; populates Keymap::bindings with fully-typed KeymapBindings. Source-location auto-captured via #[track_caller]. No docstring per binding (use .bind(KeymapBinding::new(...) .with_doc(...)) if needed).
  2. Table form — Keymap::from_entries(&MY_TABLE) / .extend_with_entries(&...). Static-catalog-style; ergonomic for 5-20+ bindings; references a &'static [KeymapEntry] built with the keymap_entry! macro. Each entry carries a docstring; the host translation pass (K.2.4.A.0.3) resolves the entry’s canonical command-name string against the CommandRegistry at registration time, building one KeymapBinding per resolvable entry. Mode authors declare entries in a static slice next to the impl; macro-captured file!() + line!() give per-row provenance.

The two paths compose:

use lattice_grammar::{CommandId, CommandInvocation};
use lattice_keymap::{BindingMode, Keymap, KeymapEntry, keymap_entry};
use std::sync::LazyLock;

// A static table (`KeymapEntry` embeds a `SourceLocation`, so the
// slice is built lazily rather than as a `const`).
static MY_KEYMAP: LazyLock<Vec<KeymapEntry>> = LazyLock::new(|| vec![
    keymap_entry! { mode: Normal, chord: "]e", doc: "Next excerpt", cmd: "my:excerpt-next" },
    keymap_entry! { mode: [Normal, Visual], chord: "q", doc: "Close", cmd: "my:close" },
]);

let refresh = CommandInvocation::of(CommandId::new(7));
let km = Keymap::from_entries(MY_KEYMAP.as_slice())
    .bind_chord(BindingMode::Normal, "<C-r>", refresh.clone());

assert_eq!(km.entries.len(), 2); // resolved against the CommandRegistry later
assert_eq!(km.bindings.len(), 1); // already typed
assert_eq!(km.bindings[0].command, refresh);
assert_eq!(km.bindings[0].doc, None); // the chain form carries no doc

Layer placement is implicit at translation time: every binding / entry contributed by Mode X lands at KeymapLayer::MinorMode(x.id()) per K.1.b convention. Per-binding layer is not exposed here – letting a mode inject into another layer would break the layer-priority contract (a “minor mode” silently shadowing a builtin would be invisible to :describe-key).

Fields§

§bindings: Vec<KeymapBinding>

Declarative list of bindings this mode contributes. Populated by the chain form (bind / bind_chord) and by the host translation pass when it resolves entries.

§entries: Vec<&'static KeymapEntry>

Static-catalog-style entries this mode contributes. Populated by Self::from_entries / Self::extend_with_entries. The host translation pass (K.2.4.A.0.3) walks both bindings and entries; entries get name→CommandId resolved via the CommandRegistry and the resulting KeymapBindings (carrying the entry’s doc) flow into the trie alongside the explicit bindings.

Implementations§

§

impl Keymap

pub fn new() -> Keymap

Empty keymap. Equivalent to Keymap::default(); kept for symmetry with builder-style construction.

pub fn from_entries(entries: &'static [KeymapEntry]) -> Keymap

Build a keymap from a static slice of keymap_entry!- constructed entries. The host translation pass resolves each entry’s canonical command-name string against the CommandRegistry at registration time; unresolvable names log a tracing::warn! and skip the binding (matches the existing catalog-drift convention).

Returns a keymap with Self::entries populated and Self::bindings empty. Compose with the chain form (.bind_chord(...)) to add typed bindings on top.

pub fn extend_with_entries(self, entries: &'static [KeymapEntry]) -> Keymap

Append a static slice of keymap_entry!-constructed entries to an existing keymap. Returns self so call sites can chain Keymap::new().bind_chord(...).extend_with_entries(&TBL) or Keymap::from_entries(&BASE).extend_with_entries(&MORE).

pub fn bind(self, binding: KeymapBinding) -> Keymap

Append one binding. Returns self so call sites can chain Keymap::new().bind(...).bind(...).

pub fn bind_chord( self, mode: BindingMode, chord: &str, command: CommandInvocation, ) -> Keymap

Append one binding parsed from a chord-sequence string.

The recommended idiom for mode-contributed keymaps:

use lattice_grammar::{CommandId, CommandInvocation};
use lattice_keymap::{BindingMode, ChordPattern, Keymap};
use lattice_protocol::KeyChord;

let next = CommandInvocation::of(CommandId::new(1));
let prev = CommandInvocation::of(CommandId::new(2));
let km = Keymap::new()
    .bind_chord(BindingMode::Normal, "]e", next)
    .bind_chord(BindingMode::Normal, "<C-w>j", prev);

assert_eq!(
    km.bindings[1].chords,
    vec![
        ChordPattern::Literal(KeyChord::ctrl('w')),
        ChordPattern::Literal(KeyChord::char('j')),
    ],
);
// Provenance is this call site, via `#[track_caller]`.
assert!(matches!(
    &km.bindings[0].source.kind,
    lattice_grammar::SourceKind::File { path, .. } if path == std::path::Path::new(file!()),
));

#[track_caller] propagates the binding row’s own file:line into the resulting [SourceLocation]; no SourceLocation::builtin_file(file!(), line!()) boilerplate per row. :describe-key shows the chord’s declaration site directly.

The chord string is parsed via [lattice_protocol::parse_chord_sequence] – accepts the same notation the host’s keymap_entry! macro catalog uses ("j", "gd", "]e", "<C-w>j", "<Esc>", "<C-S-x>", …). Wildcards ('a, "a, fX) are not expressible here; the rare mode that needs ChordPattern::CharLiteral calls Keymap::bind directly with an explicit chords vector.

§Panics

On a chord-string parse error. Mode bindings are declared at compile-time-static call sites with constant chord strings; a malformed string is a bug in the mode impl, not a runtime condition. The panic message names the chord string + the caller location so the fix is obvious. Same shape as host-side catalog drift: the editor refuses to boot rather than silently dropping the binding.

pub fn bind_chord_modes( self, modes: &[BindingMode], chord: &str, command: CommandInvocation, ) -> Keymap

Bind one chord across SEVERAL modes — the declarative multi-mode peer of Self::bind_chord. Pushes one KeymapBinding per mode (the registry trie is per-mode), so :describe-key sees the chord in each named mode. modes must be non-empty.

The imperative peer is [crate::KeymapHandle::bind_modes]; the keymap_entry! mode: [..] catalog form is the static-table peer. Same parse-or-panic discipline + caller-location capture as Self::bind_chord.

Trait Implementations§

§

impl Clone for Keymap

§

fn clone(&self) -> Keymap

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for Keymap

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Default for Keymap

§

fn default() -> Keymap

Returns the “default value” for a type. Read more
§

impl PartialEq for Keymap

§

fn eq(&self, other: &Keymap) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
§

impl StructuralPartialEq for Keymap

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more