lattice_host/preview.rs
1//! Preview isolation (PI series).
2//!
3//! In-pane picker preview renders buffer B as an **isolated read-only
4//! projection** in a pane — never mutating the committed buffer A, the
5//! global active-buffer hot state, or A's resolved options / mode stack.
6//! See `docs/dev/architecture/preview-isolation.md` for the contract and
7//! `docs/dev/operations/slice-plans/preview-isolation.md` (PI series) for
8//! sequencing.
9//!
10//! This module owns the two host-side pieces the design calls out:
11//!
12//! - [`PreviewOverride`] — the ephemeral per-pane sidecar value
13//! (`Editor::preview_overrides`, keyed by `PaneId`). It records the
14//! *displayed* buffer + the preview viewport (cursor / scroll) while a
15//! pane's *committed* `buffer_id` stays put. Baked into the published
16//! pane-tree leaves at render-publish time (`build_render_state`) so the
17//! renderers show the displayed buffer while `:ls` / modeline / dispatch
18//! keep reading the committed one.
19//! - [`PreviewMode`] — the `preview-mode` minor (§10.2 resolution: option
20//! (a)) that owns `ReadOnly = true` and, by its presence on B's own mode
21//! stack, the ephemeral "this buffer is being previewed" marker. It
22//! deliberately does **not** touch `CursorLine`, so a preview keeps the
23//! buffer's cursorline (the target line stays highlighted — e.g. an LSP
24//! reference preview).
25
26use lattice_core::{BufferId, BufferKind};
27use lattice_mode::{CapabilitySet, LifecycleFuture, Mode, ModeContext, ModeId, ModeKind};
28use lattice_protocol::position::Position;
29
30/// PI.1: a pane's ephemeral preview projection. Stored host-side in
31/// `Editor::preview_overrides` (keyed by `PaneId`) so the live
32/// `Editor::pane_tree` stays committed + geometry-only; the override is
33/// baked into the *published* pane-tree leaves each frame.
34///
35/// The preview cursor / scroll live here (not on `Editor::cursor` /
36/// `Editor::scroll`) so entering / leaving preview never disturbs the
37/// committed buffer's viewport — exit is dropping this value, not
38/// restoring anything.
39#[derive(Debug, Clone, Copy, PartialEq)]
40pub struct PreviewOverride {
41 /// The buffer the pane currently *displays*. A real registry buffer
42 /// with its own resolved options (computed read-only via
43 /// `mount_preview`); the pane renders it exactly like an inactive
44 /// split, plus a cursorline at [`Self::cursor`].
45 pub buffer_id: BufferId,
46 /// The displayed buffer's kind (drives the renderer's per-kind pane
47 /// dispatch). Preview is Document-only for now (design §10.4).
48 pub buffer: BufferKind,
49 /// Preview cursor inside the displayed buffer. Location previews
50 /// (`gr` / grep) seat it on the target line; file previews start at
51 /// the top.
52 pub cursor: Position,
53 /// First visible line of the displayed buffer in the pane.
54 pub scroll: u32,
55}
56
57/// PI.2 (§10.2 option (a)): the `preview-mode` minor. Contributes
58/// `ReadOnly = true` to the buffer it is active on; its *presence* on a
59/// buffer's mode stack is the ephemeral "previewing" marker (introspect
60/// via `:describe-mode`). Activated only on the previewed buffer B's own
61/// stack (never A's), so B's `resolved_options` reflect read-only while
62/// the committed buffer is untouched.
63pub struct PreviewMode;
64
65impl PreviewMode {
66 pub fn mode_id() -> ModeId {
67 ModeId::new("preview-mode")
68 }
69}
70
71impl Mode for PreviewMode {
72 type Guard = ();
73 fn id(&self) -> ModeId {
74 Self::mode_id()
75 }
76 fn kind(&self) -> ModeKind {
77 ModeKind::Minor
78 }
79 fn options(&self) -> lattice_config::OptionOverrideSet {
80 // ReadOnly only — CursorLine is intentionally left to resolve
81 // from the buffer's own layers so preview keeps the cursorline
82 // that marks the target line.
83 lattice_config::overrides! {
84 lattice_config::ReadOnly = true,
85 }
86 }
87 fn required_capabilities(&self) -> CapabilitySet {
88 CapabilitySet::empty()
89 }
90 fn on_activate(&self, _ctx: ModeContext) -> LifecycleFuture<'_, ()> {
91 Box::pin(async { Ok(()) })
92 }
93}