Skip to main content

GrammarEnv

Struct GrammarEnv 

Source
pub struct GrammarEnv<'a> {
Show 18 fields pub scope_resolver: Option<&'a dyn ScopeResolver>, pub comment_syntax: Option<&'a CommentSyntax>, pub syntax: Option<&'a Arc<dyn Any + Send + Sync>>, pub indent: IndentUnit, pub indent_resolver: Option<&'a dyn IndentResolver>, pub textwidth: WrapWidth, pub native_format: NativeFormatIntents, pub selection: Option<Range>, pub last_find: Option<LastFind>, pub fold_resolver: Option<&'a dyn FoldResolver>, pub last_search: Option<&'a LastSearch>, pub marks: Option<&'a dyn MarkResolver>, pub viewport: Option<&'a dyn ViewportResolver>, pub nostartofline: bool, pub curswant: Option<Curswant>, pub display: Option<&'a dyn DisplayResolver>, pub curswant_out: Option<&'a Mutex<Option<Curswant>>>, pub scrolloff: u32,
}
Expand description

The per-dispatch environment: everything the host knows that a command’s apply may need but the grammar layer cannot derive for itself. Bundled into ONE value so the dispatch seam carries a single env rather than a widening parameter list (the long-term-fit choice over parallel params). Copy; default() is the no-input case, and commands that read nothing from the env (iw, ap, i{) are unaffected by what it carries.

It has widened twice, and the name followed on the second:

  • N.1.6 (2026-06-10) introduced it as a text-object-only env — the tree-sitter scope_resolver (af/ac, N.1.4) and the comment_syntax (aC/iC).
  • TS.1 added the tree-sitter syntax snapshot for actions (borrowed Arc<dyn Any> so execute_action can Arc::clone it into the owned ActionContext::syntax — a &dyn Any alone can’t recover the Arc), which already made TextObjectEnv a misnomer.
  • IN.0 renamed it to GrammarEnv on adding a field read by operators (> / <), which would have made the old name actively misleading rather than merely stale.

Fields§

§scope_resolver: Option<&'a dyn ScopeResolver>

Tree-sitter scope lookup for structural text objects and motions. None on buffers with no parse.

§comment_syntax: Option<&'a CommentSyntax>

The buffer language’s comment leader, for aC / iC and reflow. None when the language declares none.

§syntax: Option<&'a Arc<dyn Any + Send + Sync>>

TS.1: the per-dispatch tree-sitter snapshot, type-erased and borrowed so it stays Copy. execute_action clones it into ActionContext::syntax; motions / text-objects / operators ignore it (they read scope_resolver). None = no parse.

§indent: IndentUnit

IN.0: one level of indentation, resolved by the host from shiftwidth / expandtab / tabstop (including any :setlocal override). Read by the > / < operators.

Not an Option: there is always a defensible answer, and IndentUnit::default() is the registered option defaults, so a caller that never resolved config indents like an unconfigured buffer instead of like nothing. That keeps the ~40 test and plugin call sites that build a default() env working without each having to care about indentation.

§indent_resolver: Option<&'a dyn IndentResolver>

IN.7: per-line indent depth for the = operator, injected by the host. None (the default) means = has no structural source and reindents nothing – the same graceful-degradation contract every other env field carries.

§textwidth: WrapWidth

RF.2: the buffer’s textwidth, resolved by the host (including any :setlocal). Read by the reflow operator.

WrapWidth rather than a bare usize precisely so this struct can keep its DERIVED Default: a usize would default to 0, which is not a column anything wraps at, and all ~40 hand-built default() envs would silently get a reflow that does nothing.

§native_format: NativeFormatIntents

RF.5b: which intents this buffer handles natively. See NativeFormatIntents.

§selection: Option<Range>

OS.2: the active region — the Visual/Select selection extent, normalised so start <= end. None in Normal mode and on every non-chord firing path.

Injected by the host from the SAME resolver that fills lattice_mode::ActionContext::selection (MG.18e), rather than re-derived here from the document’s selections. That is deliberate: two answers to “what is the region” is precisely the drift OS.3 spent a fix round removing from Checkboxes, and a plugin action seeing a different region than a native mode handler reached the same way is the same bug wearing a boundary.

None (the default) means no region, so the ~40 call sites that build a default() env keep behaving exactly as they did.

§last_find: Option<LastFind>

VM.3c: the last f / F / t / T, so ; and , can be motions rather than host actions.

Carried here for the reason syntax and selection had to be: ; reaches the grammar through the ACTOR path on every real keystroke, so a field missing here is a field the motion never sees no matter how well the direct path is tested. None — the default, and the state before the user has pressed any f — makes ; a no-op, which is what vim does.

§fold_resolver: Option<&'a dyn FoldResolver>

VM.3i: the buffer’s fold edges, so zj / zk can be motions.

Carried here for the reason last_find is: zj reaches the grammar through the ACTOR path on every real keystroke, so a field missing here is one the motion never sees. None — no folds, or a caller with no fold table — leaves zj / zk where they are.

§last_search: Option<&'a LastSearch>

VM.3d-2: the last search, so n / N / * / # can be motions. Carried for the reason last_find is: they reach the grammar through the ACTOR path on every real keystroke. None makes n fail with E35, as vim does before any search.

§marks: Option<&'a dyn MarkResolver>

VM.3e: the mark table, so 'x / `x can be motions. Carried for the reason last_search is. None makes every mark unset (E20).

§viewport: Option<&'a dyn ViewportResolver>

VM.3f: the lines the window shows, so H / M / L can be motions. None — no window, or an invocation that isn’t one of them — makes them fail without moving.

§nostartofline: bool

VM.3f: !startofline. Named for the vim option that turns the rule OFF so that Default (false) is vim’s default.

§curswant: Option<Curswant>

VM.3g-1: the goal column j / k aim for. None — nothing has set one yet — means “use the cursor’s own column”, which is what the first j after any edit does in vim.

§display: Option<&'a dyn DisplayResolver>

VM.3g-2: display geometry for gj / gk / g0 / g$. None — no renderer has reported one — leaves them behaving as j / k / 0 / $, which is also what they do with wrap off.

§curswant_out: Option<&'a Mutex<Option<Curswant>>>

VM.3g-3: where a motion’s MotionResult::curswant override is reported back to the caller. None — the default — discards it, which is right for every caller that does not maintain a goal column.

The symmetric partner of Self::curswant above: that field carries the goal INTO the motion, this one carries the motion’s answer back out. It is a slot rather than a return value because a motion’s effect reaches the host as an Effect::CursorMove, a WIT type and the wrong place for per-dispatch host state — exclusive and notice are kept off that boundary for the same reason.

A shared slot rather than &mut so GrammarEnv stays Copy, which the tree-sitter snapshot field above already depends on; a Mutex rather than a Cell because the owning DispatchEnv crosses the Document trait into an async Pending<Effect> and must stay Send + Sync. The lock is uncontended — one motion writes it once per dispatch, on the same thread that reads it.

§scrolloff: u32

VM.3f: scrolloff, the margin H / L keep from the window’s edges. 0 — the default — leaves them on the first and last lines shown, which is vim with scrolloff=0.

Trait Implementations§

Source§

impl<'a> Clone for GrammarEnv<'a>

Source§

fn clone(&self) -> GrammarEnv<'a>

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<'a> Copy for GrammarEnv<'a>

Source§

impl<'a> Default for GrammarEnv<'a>

Source§

fn default() -> GrammarEnv<'a>

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

Auto Trait Implementations§

§

impl<'a> !RefUnwindSafe for GrammarEnv<'a>

§

impl<'a> !Send for GrammarEnv<'a>

§

impl<'a> !Sync for GrammarEnv<'a>

§

impl<'a> !UnwindSafe for GrammarEnv<'a>

§

impl<'a> Freeze for GrammarEnv<'a>

§

impl<'a> Unpin for GrammarEnv<'a>

§

impl<'a> UnsafeUnpin for GrammarEnv<'a>

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