Skip to main content

Crate lattice_grammar

Crate lattice_grammar 

Source
Expand description

Vim modal editing engine and the unified command/grammar dispatch.

Per DESIGN.md §5.2:

  • The vim grammar is the public command API.
  • There is one CommandRegistry and one execute(...) dispatcher.
  • Operators, motions, text objects, ex-commands, and plugin contributions are all peers of the dispatcher.
  • Built-in motions / operators / text objects live here in native Rust (off the WASM hot path).

§What this crate owns

§What it must not depend on

Only lattice-protocol and lattice-core from the workspace. No tree-sitter, no lattice-mode / lattice-runtime / host / UI crate, no plugin runtime. The grammar runs on every keystroke and is linked by all of those layers, so it must sit beneath them; anything it needs from above arrives as data or as a small trait the host implements (ScopeResolver, IndentResolver, FoldResolver, MarkResolver, ViewportResolver, DisplayResolver) bundled in a per-dispatch GrammarEnv. That boundary is why this is a crate: it is what keeps built-in and plugin commands, and every buffer kind, on one dispatch path without dragging the syntax stack or the host into it.

§Example

Register a motion, then dispatch 2 of it through the one dispatcher:

use std::sync::Arc;
use lattice_core::{BufferId, Document};
use lattice_grammar::registry::MotionResult;
use lattice_grammar::{
    CancellationToken, CommandInvocation, CommandRegistry, Count, CurswantEffect, Effect,
    MotionSpec, execute,
};
use lattice_protocol::position::Position;

let mut registry = CommandRegistry::new();
let down = registry.register_motion(
    "motion:my-line-down",
    "Move `count` lines down, to column 0.",
    MotionSpec {
        jump: false,
        exclusive: false,
        curswant: CurswantEffect::default(),
        args_schema: vec![],
        apply: Arc::new(|ctx| {
            let target = Position::new(ctx.from.line + ctx.count.get(), 0);
            Ok(MotionResult { target, ..Default::default() })
        }),
    },
);

let mut doc = Document::from_text("a\nb\nc\n");
let effect = execute(
    &registry,
    &mut doc,
    BufferId(0),
    Position::ZERO,
    CommandInvocation::of(down.0).with_count(Count(2)),
    &CancellationToken::never(),
)
.unwrap();
assert!(matches!(effect, Effect::CursorMove(p) if p == Position::new(2, 0)));

§Design documents

  • docs/dev/architecture/design.md §5.2 (modal engine; §5.2.1 unified dispatch, §5.2.5 latency classes), §5.11 (introspection)
  • docs/dev/architecture/typed-motion-dispatch.md
  • docs/dev/architecture/treesitter-motions.md
  • docs/dev/architecture/select-mode.md
  • docs/dev/architecture/text-reflow.md
  • docs/dev/architecture/auto-indent.md

Re-exports§

pub use crate::app_effect::AppEffect;
pub use crate::app_effect::ErrorTarget;
pub use crate::app_effect::HScroll;
pub use crate::app_effect::InsertLineEdit;
pub use crate::app_effect::ScrollPos;
pub use crate::app_effect::ViewportPos;
pub use crate::args::ArgDefault;
pub use crate::args::ArgKind;
pub use crate::args::ArgSpec;
pub use crate::args::ArgValue;
pub use crate::args::Args;
pub use crate::cancel::CheckCancelled;
pub use crate::command::CommandInvocation;
pub use crate::command::CommandKind;
pub use crate::command::CommandSpec;
pub use crate::command::Count;
pub use crate::command::LatencyClass;
pub use crate::command::kind_icon;
pub use crate::dispatcher::execute;
pub use crate::dispatcher::execute_motion_only;
pub use crate::dispatcher::execute_motion_only_reporting;
pub use crate::dispatcher::execute_with_env;
pub use crate::dispatcher::notice_text;
pub use crate::effect::EchoLevel;
pub use crate::effect::Effect;
pub use crate::effect::FileAnchor;
pub use crate::effect::LspRequest;
pub use crate::effect::QuitScope;
pub use crate::effect::SubstituteScope;
pub use crate::effect::Utf16Pos;
pub use crate::effect::YankKind;
pub use crate::error::CommandError;
pub use crate::error::GrammarResult;
pub use crate::introspect::HelpSection;
pub use crate::introspect::Introspectable;
pub use crate::introspect::RenderedAnchor;
pub use crate::introspect::RenderedIntrospection;
pub use crate::introspect::SourceEntry;
pub use crate::introspect::SourceLabel;
pub use crate::introspect::render_introspection;
pub use crate::introspect::render_introspection_lines;
pub use crate::introspect::render_introspection_with;
pub use crate::modal::ModalState;
pub use crate::modal::SearchDirection;
pub use crate::modal::VisualKind;
pub use crate::range::Range;
pub use crate::range::RangeBound;
pub use crate::register::Register;
pub use crate::registry::ActionContext;
pub use crate::registry::ActionSpec;
pub use crate::registry::CommandRegistration;
pub use crate::registry::CommandRegistry;
pub use crate::registry::CommentSyntax;
pub use crate::registry::Curswant;
pub use crate::registry::CurswantEffect;
pub use crate::registry::DisplayResolver;
pub use crate::registry::ExCommandContext;
pub use crate::registry::ExCommandSpec;
pub use crate::registry::FindKind;
pub use crate::registry::FoldResolver;
pub use crate::registry::GrammarEnv;
pub use crate::registry::IndentResolver;
pub use crate::registry::LastFind;
pub use crate::registry::LastSearch;
pub use crate::registry::MarkResolver;
pub use crate::registry::MotionNotice;
pub use crate::registry::MotionSpec;
pub use crate::registry::NavBoundary;
pub use crate::registry::NavDir;
pub use crate::registry::OperatorContext;
pub use crate::registry::OperatorSpec;
pub use crate::registry::ScopeResolver;
pub use crate::registry::ShownLines;
pub use crate::registry::SurfaceForm;
pub use crate::registry::TextObjectSpec;
pub use crate::registry::ViewportResolver;
pub use crate::registry::ExCommandId;
pub use crate::registry::MotionId;
pub use crate::registry::OperatorId;
pub use crate::registry::TextObjectId;
pub use crate::source::SourceKind;
pub use crate::source::SourceLayer;
pub use crate::source::SourceLocation;
pub use crate::target::Target;

Modules§

app_effect
AppEffect – the typed App-side effects produced by free-form CommandKind::Action registrations.
args
Per-command argument values.
builtins
Built-in motions, text objects, and operators that ship native (off the WASM boundary; per DESIGN.md §5.5.2 “built-ins stay native”).
cancel
Cancellation tokens for evaluator interruption (DESIGN.md §5.2.5).
command
CommandInvocation – the unified call type that flows through the dispatcher (DESIGN.md §5.2.1).
dispatcher
The unified dispatcher (DESIGN.md §5.2.1).
effect
What a CommandInvocation produced once executed.
error
CommandError: why a grammar invocation produced no effect.
ex_commands
Built-in ex-commands registered as peers of motions / operators / text objects in the unified CommandRegistry (DESIGN.md §5.2.1).
introspect
Generic introspection (DESIGN.md §5.11).
modal
Modal state – a buffer-level state machine in front of the buffer (DESIGN.md §5.2). Orthogonal to major / minor modes.
range
The vim grammar Range – the dispatcher’s range arg.
reflow
The text-reflow engine — re-break a range of lines to textwidth.
register
Vim registers (DESIGN.md §5.2.2).
registry
The CommandRegistry holds every registered operator, motion, text object, and ex-command. The dispatcher (super::dispatcher::execute) looks up commands here.
source
Provenance metadata (DESIGN.md §5.11).
target
Target: the value an operator operates on.

Structs§

CancellationToken
Re-export of the protocol-layer cancellation primitive. Grammar callers access it under this name; lower crates (search loops in lattice-core) use lattice_protocol::CancellationToken directly. The two are the same type. Cooperative cancellation handle. Cheap to clone (one Arc bump); safe to share across threads / tasks.
CommandId
Re-export the protocol’s CommandId so callers don’t need a second import. Identifies a registered command — the command of a lattice_grammar::CommandInvocation, and what a keymap binding resolves to. Minted at registration by lattice-grammar’s command registry from a process-wide counter starting at 1. (The completion registry keeps a separate counter of its own, so an id is only meaningful together with the registry that issued it.)

Enums§

PaneDirection
<C-w>h/j/k/l cardinal navigation. Geometry-aware: walks the tree to find the spatial neighbour of the active pane.

Type Aliases§

CommandRegistryHandle
The shared, hot-swappable command registry: the typed handle for ServiceRegistry registration + lookup (M.10.3, 2026-06-03). Mode crates pull it via ctx.service::<CommandRegistryHandle>() to look up CommandIds by action name (id_by_name("action:...")) at on_activate time. Same shape as lattice_mode::ActionHandlerRegistryHandle per feedback_servicesregistry_arc_typeid.