pub struct ActionContext<'a> {
pub buffer_id: BufferId,
pub cursor: Position,
pub selection: Option<Range>,
pub services: &'a ServiceRegistry,
pub events: &'a EventBus,
pub prompt_value: Option<&'a str>,
pub args: Args,
pub buffer_locals: Option<&'a BufferLocals>,
}Expand description
Read-only context handed to a mode-contributed action handler closure. Carries the bare minimum the host can supply on every invocation: the active buffer + cursor and shared subsystem registries the handler may need.
Borrows from App-owned state for the duration of the action dispatch — handlers do NOT outlive their context.
Fields§
§buffer_id: BufferIdActive buffer at the moment the chord fired.
cursor: PositionActive document cursor at the moment the chord fired.
selection: Option<Range>The active region — the Visual/Select-mode selection
extent, normalised so start <= end. None in Normal mode and
on every non-chord firing path (prompt submit, transient item,
a Confirm yes-action) (MG.18e).
Design §5.2’s “Visual mode IS the active region” applied to mode
action handlers: a chord that fires with a selection up should
be able to act on it, the same way Range::Selection is the
default range argument for an ex-command. magit’s region staging
is the first consumer — select some lines inside a hunk, press
s, stage only those.
Carries no visual kind. A diff line is the unit of every consumer so far, and the row span is all they read; adding charwise/blockwise distinctions before something needs them would be inventing a contract nobody is holding.
services: &'a ServiceRegistryTyped service registry. Handlers look up subsystem
handles they need (MultibufferRegistryHandle,
ProjectSearchServiceHandle, etc.) via
ctx.services.get::<Foo>().
events: &'a EventBusTyped event bus. Handlers publish events that other
subsystems subscribe to (e.g.
ProjectSearchRefreshed).
prompt_value: Option<&'a str>Set only when this handler fires as the submit callback of an
Effect::OpenPrompt-opened prompt (Editor::do_prompt_line_submit)
— the prompt buffer’s typed content at the moment of submit.
None for every other firing path (chord dispatch, transient
item click, Effect::Confirm’s yes-action, …).
args: ArgsArguments the invocation carried (MG.17a).
Args::None for a bare chord press. A transient item’s flags
and arguments arrive here as Args::List, ordered by the
action’s args_schema — the same shape the : line produces
for an ex-command, so one handler body serves both front-ends
instead of each surface growing its own accessor. Read it with
Self::flag / Self::arg_str rather than matching the
list positionally.
buffer_locals: Option<&'a BufferLocals>The active buffer’s typed mode-owned locals, read-only, for
the duration of the dispatch. Some on the host chord-dispatch
path (where a mode handler may need to read its buffer’s state —
oil’s dir/snapshot, a file tree’s entries — to resolve the entry
under the cursor); None on the auxiliary firing paths (prompt
submit, transient item, a Confirm yes-action) and wherever a
caller builds a context without a buffer-locals store (LM.1).
Read it through Self::buffer_local rather than the field, so a
handler that runs with None degrades to “no such local” — the
same answer as an unseeded buffer — instead of a branch.
Keeping the state in buffer_locals (rather than a separate
service) is deliberate: it stays enumerable by :describe-buffer
via iter_descriptors, so a mode owning per-buffer state does not
trade introspection for handler-reachability.
Implementations§
Source§impl<'a> ActionContext<'a>
impl<'a> ActionContext<'a>
Sourcepub fn buffer_local<T: BufferLocal>(&self) -> Option<&T>
pub fn buffer_local<T: BufferLocal>(&self) -> Option<&T>
Read one of the active buffer’s mode-owned locals, if the context carries a buffer-locals store and the local is seeded (LM.1).
Total: None covers a context built without locals (an auxiliary
firing path) and a buffer that never seeded T, which a handler
treats the same way — there is nothing to act on.
Source§impl ActionContext<'_>
impl ActionContext<'_>
Sourcepub fn flag(&self, index: usize) -> bool
pub fn flag(&self, index: usize) -> bool
The boolean argument at index in the action’s args_schema.
false when the invocation carried no args (a bare chord), when
the index is past the end, or when that slot holds a non-bool —
a handler asking “was --force set?” wants false for all
three, not three different error paths.
Sourcepub fn project(&self) -> Project
pub fn project(&self) -> Project
The project this action is acting in (PR.2).
Design: docs/dev/architecture/project-resolution.md §5. This is
a method rather than a field so that “which project” is a
question every action handler can ask without the host having to
answer it on every dispatch — resolution is cached and most
handlers never ask.
Total, matching ProjectResolver::for_path: a handler that
cannot express “no project” cannot get it wrong. The degradations
are both real answers, not errors:
- a buffer with no path (scratch,
*messages*, a terminal) has no tree to walk, so the working directory stands in; - a partially-wired harness with no resolver registered falls back to the process working directory, which is what every consumer did before this existed.