Skip to main content

lattice_host/
activator.rs

1//! M.2.b.2 (2026-06-01): `impl ModeActivator for Editor`.
2//!
3//! Synchronous activation surface for extension crates
4//! (`lattice-multibuffer` today; future in-tree provider crates
5//! shipped within it). Thin wrappers over the existing fat helpers
6//! (`activate_major_for_buffer_kind`, `activate_mode_by_id`) —
7//! both already run the full cascade (major → default minor → auto
8//! minors → recompute options + completion → maybe-auto-LSP) and
9//! return a `Vec<RendererSignal>`.
10//!
11//! The trait surface returns `()`, keeping `RendererSignal` out of
12//! `lattice-mode`. Signals are enqueued into
13//! `Editor::pending_renderer_signals`; the App's dispatch loop
14//! drains via [`Editor::drain_pending_renderer_signals`] after the
15//! extension-crate call frame returns.
16//!
17//! See `docs/dev/architecture/multibuffer-views.md` §3.7.
18
19use std::sync::Arc;
20
21use lattice_core::{BufferFlags, BufferId, BufferKind};
22use lattice_mode::{ModeActivator, ModeId, ServiceRegistry};
23
24use crate::editor::Editor;
25
26impl ModeActivator for Editor {
27    /// MR.6: the buffer a provider view is being opened over.
28    ///
29    /// The active *document* buffer, which is what the trigger was
30    /// pressed in — the same id `transient_open_context` reports and the
31    /// same one the chord dispatcher hands an action handler.
32    fn active_buffer(&self) -> Option<BufferId> {
33        Some(self.document_buffer_id)
34    }
35
36    fn activate_major_for_kind(&mut self, buffer: BufferId, kind: BufferKind) {
37        let signals = self.activate_major_for_buffer_kind(buffer, kind);
38        self.enqueue_renderer_signals(signals);
39    }
40
41    fn activate_minor_by_id(&mut self, buffer: BufferId, mode: ModeId) {
42        let signals = self.activate_mode_by_id(buffer, mode);
43        self.enqueue_renderer_signals(signals);
44    }
45
46    fn deactivate_minor_by_id(&mut self, buffer: BufferId, mode: ModeId) {
47        let signals = self.deactivate_mode_by_id(buffer, mode);
48        self.enqueue_renderer_signals(signals);
49    }
50
51    /// The real create-and-activate seam (`ensure_named_synthetic_document`
52    /// inserts the buffer + runs the major's `on_activate` by id). This
53    /// is why buffer creation lives here on the `&mut`-backed
54    /// `ModeActivator` and not on the `&self` `BufferStore`.
55    fn ensure_named_document(&mut self, name: &str, major: ModeId, flags: BufferFlags) -> BufferId {
56        self.ensure_named_synthetic_document(name, major, flags)
57    }
58
59    fn services(&self) -> Arc<ServiceRegistry> {
60        Arc::clone(&self.services)
61    }
62
63    /// Forward to the host's single write chokepoint, so a provider crate
64    /// records what its buffer is about without depending on `lattice-host`.
65    fn set_buffer_scope_dir(&mut self, buffer: BufferId, dir: std::path::PathBuf) {
66        Editor::set_buffer_scope_dir(self, buffer, dir);
67    }
68
69    /// K.4.6 (2026-06-02): forward to the editor's
70    /// `VirtualRowProviderRegistry`. The virtual-rows worker
71    /// (`crate::virtual_rows_worker`) picks up new providers on
72    /// its next wake; the registry itself is already shared
73    /// (`Arc<VirtualRowProviderRegistry>`), so registration is
74    /// observable to the worker without further plumbing.
75    /// Returns `false` if a provider with the same `ProviderId`
76    /// already exists in `buffer`'s scope — matches the
77    /// underlying registry's no-replacement contract.
78    fn register_virtual_row_provider(
79        &mut self,
80        buffer: BufferId,
81        provider: Arc<dyn lattice_cells::VirtualRowProvider>,
82    ) -> bool {
83        self.virtual_row_providers.register(buffer, provider)
84    }
85}