pub struct ExCommandSpec {
pub latency_class: LatencyClass,
pub accepts_bang: bool,
pub accepts_range: bool,
pub parse_args: Arc<dyn Fn(&str, bool) -> GrammarResult<Args> + Send + Sync>,
pub apply: Arc<dyn Fn(&ExCommandContext) -> GrammarResult<Effect> + Send + Sync>,
pub args_schema: Vec<ArgSpec>,
pub surface_form: SurfaceForm,
}Expand description
A registered ex-command: how the : line parses it and what it
returns.
Registered through CommandRegistry::register_ex_command (or
CommandRegistry::register_plugin_ex_command). The : front-end (in
lattice-host) resolves the typed word to a registry name, rejects a
! the spec does not accept, calls Self::parse_args on the rest of
the line, and dispatches the resulting invocation. apply receives an
ExCommandContext and returns an Effect — it never
performs I/O itself.
§Examples
use std::sync::Arc;
use lattice_core::{BufferId, Document};
use lattice_grammar::{
Args, CancellationToken, CommandInvocation, CommandRegistry, EchoLevel, Effect,
ExCommandSpec, LatencyClass, SurfaceForm, execute,
};
use lattice_protocol::position::Position;
let mut registry = CommandRegistry::new();
let id = registry.register_ex_command(
"ex:greet",
"Echo a greeting (`:greet [name]`).",
ExCommandSpec {
latency_class: LatencyClass::Reflex,
accepts_bang: false,
accepts_range: false,
parse_args: Arc::new(|rest, _bang| {
Ok(match rest.trim() {
"" => Args::None,
name => Args::String(name.to_string()),
})
}),
apply: Arc::new(|ctx| {
let who = match &ctx.args {
Args::String(s) => s.as_str(),
_ => "world",
};
Ok(Effect::Echo { level: EchoLevel::Info, text: format!("hello, {who}") })
}),
args_schema: vec![],
surface_form: SurfaceForm::Keyword,
},
);
let spec = registry.ex_command_spec(id.0).unwrap();
let args = (spec.parse_args)(" lattice", false).unwrap();
let mut doc = Document::from_text("");
let effect = execute(
®istry,
&mut doc,
BufferId(0),
Position::ZERO,
CommandInvocation::of(id.0).with_args(args),
&CancellationToken::never(),
)
.unwrap();
assert!(matches!(effect, Effect::Echo { text, .. } if text == "hello, lattice"));Fields§
§latency_class: LatencyClassLatency class declaration (DESIGN.md §5.2.5). Most ex-commands
stay crate::command::LatencyClass::Reflex (the default) –
they’re cheap state mutations. File I/O (:write, :edit)
and help-buffer builders (:describe-*, :apropos,
:keymap) declare crate::command::LatencyClass::Display
so future cancellation / deadline machinery treats them with
the right budget.
accepts_bang: boolWhether the parser should accept a trailing ! after the command
word. If false, :cmd! parses as an unknown command.
accepts_range: boolWhether the parser should accept an ex-style line range (1,5cmd,
'a,'bcmd, …). v1 only honours Whole and CurrentLine; this
flag is the migration knob for richer range parsing.
parse_args: Arc<dyn Fn(&str, bool) -> GrammarResult<Args> + Send + Sync>Parses everything after the command word (and !) into Args.
Receives the bang bit so ! can change the grammar.
apply: Arc<dyn Fn(&ExCommandContext) -> GrammarResult<Effect> + Send + Sync>The evaluator: packages the invocation into an Effect.
args_schema: Vec<ArgSpec>Per-positional-argument metadata (DESIGN.md §B.1). Drives palette
forms, missing-arg prompts, completion, validation, and
:describe-command output. Empty for commands taking no
structured args (:q, :noh).
surface_form: SurfaceFormUser-facing surface form. Drives whether completion / palette
list this command. Defaults to SurfaceForm::Keyword.
Trait Implementations§
Source§impl Clone for ExCommandSpec
impl Clone for ExCommandSpec
Source§fn clone(&self) -> ExCommandSpec
fn clone(&self) -> ExCommandSpec
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more