Expand description
Modeline element model + descriptor registry (slice ML.0a).
The configurable modeline (see
docs/dev/architecture/modeline.md) is a registry of styled,
positioned, optionally-interactive elements contributed by host
built-ins, modes, and (later) plugins. This module holds the
mode-facing data model + the descriptor registry.
Split of concerns (mirrors lsp_progress): the descriptor
(ModelineElement) is registered once and changes rarely; the
content (ElementContent) churns and lives in the host
content store, published as a render snapshot and updated over the
event bus (ML.0b / ML.3). The renderers lay out zones (ML.1 / ML.2).
Interaction (Interaction) is designed here but wired in ML.4 —
shipping the field now keeps that slice additive (no model churn).
Structs§
- Element
Content - The dynamic, frequently-updated value of an element. Empty (no non-empty span text) ⇒ the element is hidden this frame — the cheap way a producer hides itself without deregistering.
- Element
Id - Stable, namespaced element identifier —
"core.mode","lsp","<plugin-id>.<name>". The namespace doubles as the owner key (feedback_mode_owns_its_surface): a mode/plugin owns the elements under its namespace end to end. - Hover
Spec - Hover payload — a GPUI tooltip; ignored in the terminal (no hover). Realized in ML.4.
- Interaction
- Interaction spec — designed in ML.0, behaviour wired in ML.4.
on_clickis dispatched through the host action registry; the handler body lives in the registering mode/plugin crate (feedback_mode_owns_its_surface,feedback_effect_vocabulary_is_host_boundary) — the host is only a router.hoveris GPUI-only. - Modeline
Element - Static descriptor for a modeline element. Registered once into the
ModelineRegistry; itsElementContentlives separately in the host content store and updates over the event bus (ML.3). - Modeline
Element Update - A typed event a producer (mode / plugin) publishes on the event bus
to set an element’s content (ML.3). The host forwarder fires the §12
render-wake on arrival; the actor thread drains the event into the
content store in
run_tick_pending(single-writer). Emptycontenthides the element (the drain treats it as aModelineService::clear). - Modeline
Registry - Descriptor registry. Host-owned storage; modes register in
on_activateand remove when their Guard drops (there is noon_deactivate); plugins via WIT, ML.6. Holds only descriptors — the churning content lives in the host content store, not here, so registration is rare and cheap. - Modeline
Role - Theme role key for a
Span. Resolved by the renderer against theResolvedTheme(T-series). Kept as a string key solattice-modeneed not depend on the theme crate (dep-inversion, same pattern as the service registry). Unknown roles fall back to the default modeline style at render time. - Modeline
Service - Shared modeline service: descriptor registry + content store, each
behind an [
ArcSwap] for wait-free reads and lock-free updates. The host holds anArcand readsSelf::snapshoteachbuild_render_state; modes/plugins hold the sameArc(viactx.service::<ModelineServiceHandle>(), ML.0b-2 / ML.3) and register / remove descriptors. Content normally arrives as aModelineElementUpdateon the event bus, which also wakes the render; callingupdatedirectly changes the store without a wake. - Modeline
Snapshot - A published, wait-free snapshot of the modeline state the renderer
reads: descriptors + content, each an
Arc(cheap clone). The host takes one perbuild_render_stateand stores it inRenderState(ML.0b-2). - Span
- A styled run of text within an element’s content.
Enums§
- Modeline
Key - Content-store key discriminator (ML.3). Content is keyed by
(ModelineKey, ElementId)so a single descriptor can carry distinct content per pane:Buffer(id)for aScope::PaneLocalelement (resolved against the pane’s buffer),Globalfor aScope::Globalelement (one value, rendered only on the active pane). A producer pushes per-buffer content for each buffer it serves — e.g. each side of a split diff shows its own+N ~M. Seedocs/dev/architecture/modeline.md§4 (per-pane content resolution). - Scope
- Whether an element renders on every pane (
PaneLocal, default) or only the active pane (Global).Globalcarries project-wide content (clock, git branch) without per-pane duplication and without reintroducing a global chrome bar (Option A stays). - Zone
- Horizontal placement zone.
Leftfills left→right,Rightfills right→left,Centersits in the gap between them and is the default zone for custom / plugin content.
Constants§
- ROLE_
MODE_ ITEM - The modeline role a mode tags content with when it
contributes a segment to the modeline (e.g. diff-mode’s
+N ~Mstats) (DX.4, BC.6). Lives inlattice-mode(not host) because it is the role modes reach for —ModelineRole::new(ROLE_MODE_ITEM)— so it belongs with the mode-contribution substrate, lettinglattice-diffreach it without the host. The host’s own element roles (modeline.path,modeline.position,modeline.lang,modeline.mode) stay host-side; the host re-exports this one so renderer style maps +crate::modelinecall sites are unchanged.
Type Aliases§
- Modeline
Service Handle - Shared handle to the
ModelineService.