pub struct OperatorContext<'a> {Show 14 fields
pub document: &'a mut Document,
pub buffer_id: BufferId,
pub range: Range,
pub origin: Position,
pub linewise: bool,
pub register: Register,
pub count: Count,
pub args: Args,
pub cancel: &'a CancellationToken,
pub indent: IndentUnit,
pub indent_resolver: Option<&'a dyn IndentResolver>,
pub textwidth: WrapWidth,
pub comment_syntax: Option<&'a CommentSyntax>,
pub native_format: NativeFormatIntents,
}Expand description
Context passed to an operator’s evaluator.
Fields§
§document: &'a mut DocumentThe document to edit. Native operators apply their edits here
directly (as one undo unit) and report them in the returned
Effect; plugin operators hold a read-only view and
return an ApplyEdit effect instead.
buffer_id: BufferIdCM.3: the buffer the operator is running over — the target a plugin
operator names in an apply-edit effect.
Absent until now, and the absence was an asymmetry rather than a
decision, exactly as MR.2 found for ExCommandContext::buffer_id:
ActionContext and MotionContext both carry it, a native
operator never needed it because it mutates document in place, and a
PLUGIN operator cannot — it holds a read-only handle and must ask the
host to apply. Without this field a plugin operator can read its range
and never change it, which makes the contribution pointless.
range: RangeThe span to operate on, already resolved from the target or range and
expanded to whole lines when Self::linewise.
origin: PositionVM.3m: the start of the operated text BEFORE linewise expansion —
min(cursor, motion target) for a motion, the object’s or selection’s
start otherwise, the cursor for a count / current-line / ex range.
vim leaves the cursor here after a yank, which is why the expanded
range can’t answer: yk keeps its column (k’s target has it) and
yy doesn’t move at all, though both expand to whole lines.
linewise: boolWhether the range was produced by a linewise source (vim’s
Range::CurrentLine / Range::Whole, or a linewise visual
selection). Yank uses this to tag the unnamed register so paste
can do the right thing.
register: RegisterThe register the operator reads or writes (unnamed when none typed).
count: CountThe count, 1 when none was typed. Usually already folded into the
span by target resolution (3dw), so most operators ignore it.
args: ArgsThe operator’s own arguments, e.g. the captured char for r{char} or
surround’s ys{motion}{char}.
cancel: &'a CancellationTokenCooperative cancellation handle (DESIGN.md §5.2.5). Operators
that scan large ranges (d_whole, gU over a big visual
block) should poll cancel.check()? between rows; on a
flipped token return crate::CommandError::Cancelled.
indent: IndentUnitIN.0: one level of indentation, resolved by the host. Only the
indent operators (> / <) read it.
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 leaves lines alone – the same graceful-degradation
contract every other env field carries.
textwidth: WrapWidthRF.2: the buffer’s textwidth, resolved by the host (including
any :setlocal). Read by the reflow operator (gq / gw).
Not an Option, for the same reason Self::indent is not:
there is always a defensible answer, and
WrapWidth::default() is the registered option default, so a
caller that never resolved config reflows like an unconfigured
buffer rather than not at all.
comment_syntax: Option<&'a CommentSyntax>RF.2: the buffer language’s line-comment leader, so reflow can
keep a comment block’s marker. None for prose languages and
for any language whose comment syntax is undeclared – reflow
then uses indentation alone, which is the right answer there.
native_format: NativeFormatIntentsRF.5b: for each intent, whether the buffer’s chain resolves to the native engine.
The host resolves the chain — it owns the LSP client and the
PATH probe — and hands down the one bit the operator needs:
“do it yourself, or hand me the range”. true (the default) is
the shipped configuration, so the common path never delegates.