Skip to main content

ModeActivator

Trait ModeActivator 

Source
pub trait ModeActivator {
    // Required methods
    fn activate_major_for_kind(&mut self, buffer: BufferId, kind: BufferKind);
    fn activate_minor_by_id(&mut self, buffer: BufferId, mode: ModeId);
    fn ensure_named_document(
        &mut self,
        name: &str,
        major: ModeId,
        flags: BufferFlags,
    ) -> BufferId;
    fn services(&self) -> Arc<ServiceRegistry> ⓘ;

    // Provided methods
    fn deactivate_minor_by_id(&mut self, buffer: BufferId, mode: ModeId) { ... }
    fn active_buffer(&self) -> Option<BufferId> { ... }
    fn register_virtual_row_provider(
        &mut self,
        buffer: BufferId,
        provider: Arc<dyn VirtualRowProvider>,
    ) -> bool { ... }
    fn set_buffer_scope_dir(&mut self, buffer: BufferId, dir: PathBuf) { ... }
}
Expand description

Activation surface implemented by lattice-host::Editor and consumed by extension crates that need to drive activation without holding a typed &mut Editor.

All three methods run synchronously on the App thread (caller owns &mut Self). The implementor is responsible for routing the cascade’s renderer signals into its own pending-signals queue — extension crates never see RendererSignal, keeping host-layer types out of lattice-mode.

Failures (mode not registered, missing capability, conflict) are logged + swallowed by the impl (matching the existing Editor::activate_* helpers’ shape). Callers that need to observe activation outcome subscribe to crate::ModeEvent on the event bus.

Required Methods§

Source

fn activate_major_for_kind(&mut self, buffer: BufferId, kind: BufferKind)

Activate the major mode bound to kind on buffer. Uses the crate::ModeRegistry::find_major_for_kind lookup (populated by Mode::target_buffer_kind declarations) to resolve the mode id. No-ops if a major is already active on the buffer (idempotency / preserve-intent).

Source

fn activate_minor_by_id(&mut self, buffer: BufferId, mode: ModeId)

Activate a minor mode by id on buffer. The mode must be registered. Idempotent: re-activating an already-active minor is a no-op.

Source

fn ensure_named_document( &mut self, name: &str, major: ModeId, flags: BufferFlags, ) -> BufferId

Find-or-create a synthetic named Document buffer and activate major on it by id (no on-disk language detection), returning its [BufferId]. This is the reliable, &mut-backed creation seam a mode / provider uses to provision its own buffer — the creation of a mode-owned buffer is the mode’s responsibility, triggered through here.

Unlike crate::BufferStore (whose &self handle can only find an existing buffer — activating a mode mutates the mode registry / active-modes / options cache and needs &mut), this method actually creates: the host impl mints the BufferId, spawns an empty Document, registers it with flags, seeds mode-locals, and runs major’s on_activate — so any drain / subscription the mode establishes there is live by the time this returns. Idempotent: a second call with the same name returns the existing id without re-activating (the drain from the first activation stays put).

Source

fn services(&self) -> Arc<ServiceRegistry> ⓘ

Cheap-clone handle to the App’s ServiceRegistry. Used by extension-crate trigger functions that need to look up service handles (BufferStoreHandle, per-provider services, the per-extension-crate registries) without fighting the borrow checker against the &mut Self activator borrow.

Provided Methods§

Source

fn deactivate_minor_by_id(&mut self, buffer: BufferId, mode: ModeId)

Deactivate a minor mode by id on buffer. Idempotent: a mode that is not active is a no-op.

PD.4: the symmetric half of Self::activate_minor_by_id, and it exists because a re-triggered provider view reuses its buffer. A view that was read-only for one query and is editable for the next has to be able to say so — without this, “open the staged diff, then open the working-tree diff” would leave the second one unwritable, and the cause would be invisible because the buffer looks identical.

Default impl is a no-op so test activators that do not model mode state stay valid; the host impl forwards to Editor::deactivate_mode_by_id.

Source

fn active_buffer(&self) -> Option<BufferId>

The buffer that is active right now (MR.6).

A provider view is opened over something — the file you were reading, the magit buffer you pressed a chord in — and what it should show usually depends on which. ProviderViewOpener received the services and the trigger’s arguments but no way to name that buffer, so magit’s project diff had to fall back to the process’s working directory and showed the wrong repository’s changes for anyone with two checkouts open.

The peer of TransientContext::buffer and ExCommandContext::buffer_id, and generic for the same reason: “which buffer did this come from” is a question every context-varying surface asks, not a magit one.

Default None so test activators that model no pane tree stay valid; the host impl returns its active document buffer.

Source

fn register_virtual_row_provider( &mut self, buffer: BufferId, provider: Arc<dyn VirtualRowProvider>, ) -> bool

Register a virtual-row provider against buffer. Used by extension crates that contribute virtual rows for their own buffer kinds (multibuffer excerpt headers — MultibufferHeaderProvider; future fold-range providers, diff-hunk overlays, LSP code-lens, …). The host-side impl forwards to Editor::virtual_row_providers.register(buffer, provider); the worker picks the provider up on its next wake (K.4.6, 2026-06-02).

Returns true on registration, false if a provider with the same ProviderId was already registered in the same buffer scope (no replacement — caller unregisters first via the existing registry handle). The default impl returns false so test activators that don’t wire the virtual-row pipeline behave as no-ops; production impls (Editor) override.

Paramount-#2 anchor: every mode contributing to a buffer registers its own virtual rows via this seam, matching the mode-owns-its-surface principle (keymaps via register_<mode>_keymap, virtual rows via this method, future status-line items via similar). WIT plugin path inherits the trait surface.

Source

fn set_buffer_scope_dir(&mut self, buffer: BufferId, dir: PathBuf)

Record the directory buffer is about (BufferScopeDir).

A provider calls this from its trigger, where it has already resolved the directory — a magit repository’s workdir, an oil listing’s dir, a scan root. Project resolution (:files, :search) then answers for that buffer instead of falling through to the working directory.

Pass the directory, not a project root: the host resolves the project from it through the ordinary resolver, so a provider never has to learn what a project is and the two cannot be recorded inconsistently.

Default impl is a no-op so test activators stay valid; the host forwards to Editor::set_buffer_scope_dir.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§