Skip to main content

CommandRegistry

Struct CommandRegistry 

Source
pub struct CommandRegistry { /* private fields */ }
Expand description

The one registry of every command: motions, operators, text objects, ex-commands and actions, built-in and plugin alike (DESIGN.md §5.2.1).

Registration. Each kind has a register_<kind> method taking a canonical name, a doc string and a spec. It mints a fresh CommandId from a process-wide counter, records the caller’s file and line as provenance (#[track_caller]; callers cannot forge it), and returns a typed id (MotionId, OperatorId, …). Plugins go through register_plugin_<kind>, which stamps SourceLayer::Plugin instead, and are removed wholesale by Self::unregister_plugin.

Names. Names are namespaced by kind: motion:word-forward, operator:delete, text-object:inner-word, ex:write, action:…. Names are not checked for uniqueness: registering a name again mints a new id and repoints the name at it, while the old id stays dispatchable. Aliases (:w) are not registry entries; the : front-end maps them to canonical names.

Lookup and dispatch. Self::id_by_name and Self::lookup resolve names and ids to CommandSpec metadata; execute takes the registry and an invocation and routes by kind. At runtime the registry is shared as a CommandRegistryHandle: readers load a snapshot wait-free, writers clone, mutate and store it.

§Examples

use lattice_grammar::{CommandKind, CommandRegistry, builtins, ex_commands};

let mut registry = CommandRegistry::new();
assert!(registry.is_empty());
let b = builtins::populate(&mut registry);
ex_commands::populate(&mut registry);

let id = registry.id_by_name("operator:delete").unwrap();
assert_eq!(id, b.delete.0);
let spec = registry.lookup(id).unwrap();
assert_eq!(spec.kind, CommandKind::Operator);
assert_eq!(registry.lookup_by_name("ex:write").unwrap().kind, CommandKind::ExCommand);

// Aliases are the front-end's business, not the registry's.
assert!(registry.id_by_name("w").is_none());

Implementations§

Source§

impl CommandRegistry

Source

pub fn new() -> Self

An empty registry. Populate it with builtins::populate and ex_commands::populate, then the host’s and subsystems’ own registrations.

Source

pub fn tag_word_forward_motion(&mut self, id: MotionId)

Tag a motion as “word-forward class” (vim w / W) so the operator range resolver applies the word-motion line-stop special case to it. Called by builtins::populate right after the two word-forward motions are registered. Idempotent.

Source

pub fn is_word_forward_motion(&self, id: CommandId) -> bool

Whether id is a word-forward-class motion (see Self::tag_word_forward_motion).

Source

pub fn register_motion( &mut self, name: &str, doc: &str, spec: MotionSpec, ) -> MotionId

Register a motion. The caller’s source location is captured via #[track_caller] – the caller cannot supply or override it. Trusted subsystems (config loader, plugin host bridge, runtime dispatcher) reach the pub(crate) insert_motion companion directly with a layer-appropriate source.

Source

pub fn register_operator( &mut self, name: &str, doc: &str, spec: OperatorSpec, ) -> OperatorId

Register an operator; provenance and id minting as for Self::register_motion.

Source

pub fn register_text_object( &mut self, name: &str, doc: &str, spec: TextObjectSpec, ) -> TextObjectId

Register a text object; provenance and id minting as for Self::register_motion.

Source

pub fn register_ex_command( &mut self, name: &str, doc: &str, spec: ExCommandSpec, ) -> ExCommandId

Register an ex-command; provenance and id minting as for Self::register_motion. The command’s latency class comes from ExCommandSpec::latency_class (other kinds are always Reflex).

Source

pub fn register_action( &mut self, name: &str, doc: &str, spec: ActionSpec, ) -> CommandId

Register a free-form action (DESIGN.md §5.2.1; see docs/dev/notes/8i-approach.md). Used by chord bindings whose historical Action enum payload had no grammar concept attached. The spec’s apply returns an crate::effect::Effect – typically Effect::AppAction(AppEffect::...).

Source

pub fn register_plugin_motion( &mut self, plugin_id: u32, name: &str, doc: &str, spec: MotionSpec, ) -> MotionId

Register a plugin-contributed motion under SourceLayer::Plugin(plugin_id).

Source

pub fn register_plugin_operator( &mut self, plugin_id: u32, name: &str, doc: &str, spec: OperatorSpec, ) -> OperatorId

Register a plugin-contributed operator under SourceLayer::Plugin(plugin_id).

Source

pub fn register_plugin_text_object( &mut self, plugin_id: u32, name: &str, doc: &str, spec: TextObjectSpec, ) -> TextObjectId

Register a plugin-contributed text object under SourceLayer::Plugin(plugin_id).

Source

pub fn register_plugin_ex_command( &mut self, plugin_id: u32, name: &str, doc: &str, spec: ExCommandSpec, ) -> ExCommandId

Register a plugin-contributed ex-command under SourceLayer::Plugin(plugin_id).

Source

pub fn register_plugin_action( &mut self, plugin_id: u32, name: &str, doc: &str, spec: ActionSpec, ) -> CommandId

Register a plugin-contributed action under SourceLayer::Plugin(plugin_id).

Source

pub fn unregister_plugin(&mut self, plugin_id: u32) -> usize

Remove every command a plugin contributed, keyed by its host-issued plugin_id (the u32 inside SourceLayer::Plugin). The teardown seam for a plugin reload / unload (PH7.12b): the registry is otherwise append-only, so without this a reload would re-register on top of the old entries and the by_id/by_name maps would grow unbounded across reloads (audit F6). Provenance-driven — only Plugin(plugin_id) entries go; built-in / config / runtime commands are never touched, mirroring the forgery invariant (a caller supplies only a u32, never a SourceLayer). Returns the number of commands removed (0 if the plugin contributed none — an idempotent no-op on a second unload). Every index (by_id, by_name, the word-forward tag set) is kept consistent.

Source

pub fn lookup(&self, id: CommandId) -> Option<&CommandSpec>

Metadata for a registered id, or None if the id is unknown here (never registered, or removed by Self::unregister_plugin).

Source

pub fn lookup_by_name(&self, name: &str) -> Option<&CommandSpec>

Metadata by canonical name ("motion:word-forward"). Exact match; no alias or prefix resolution.

Source

pub fn id_by_name(&self, name: &str) -> Option<CommandId>

The id currently bound to a canonical name. How modes and the host find a command they did not register themselves (e.g. id_by_name("action:…") at mode activation).

Source

pub fn motion_is_jump(&self, id: CommandId) -> bool

Is id a motion that vim would call a jump?

MotionSpec::jump has been declared since the grammar’s first slice and, until VM.3a, read by nobody: the host decided what counted as a jump with a hardcoded goto_first_line || goto_last_line in run_document_invocation. So }, {, (, ), the sixteen tree-sitter structural motions and every plugin motion declared jump: true and silently got neither a position-history entry nor a fold-open at the destination — org’s headline motions say in their own source comment that a headline jump “is somewhere you want <C-o> to bring you back from”, and it was not.

false for a non-motion or an unregistered id, so a caller can ask about any CommandId without pre-checking the kind.

Source

pub fn motion_curswant(&self, id: CommandId) -> CurswantEffect

VM.3g-1: what this command does to the goal column. Anything that is NOT a motion — an operator, an action, an ex-command — answers SetFromTarget, which is what vim does after an edit, an Insert exit or a yank: the column it leaves the cursor on becomes the new goal.

Source

pub fn ex_command_spec(&self, id: CommandId) -> Option<&ExCommandSpec>

Borrow the ExCommandSpec body for an ex-command id. Returns None for ids that aren’t ex-commands or aren’t registered. Used by the :-line parser front-end so it can call the command’s parse_args callback before building the CommandInvocation.

Source

pub fn len(&self) -> usize

Number of registered commands.

Source

pub fn is_empty(&self) -> bool

Whether nothing is registered.

Source

pub fn names(&self) -> impl Iterator<Item = &str>

Every registered canonical name, in no particular order.

Source

pub fn generation(&self) -> u64

Monotonic mutation counter (see the generation field). Read by the completion layer’s command-name generator to key its cache: a change means the command set moved (a plugin loaded or unloaded), so the cached candidate list must be regenerated rather than served stale.

Trait Implementations§

Source§

impl Clone for CommandRegistry

Source§

fn clone(&self) -> CommandRegistry

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
Source§

impl Debug for CommandRegistry

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Default for CommandRegistry

Source§

fn default() -> CommandRegistry

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

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