Skip to main content

Module render_state

Module render_state 

Source
Expand description

RenderState — the renderer’s read contract with the host.

Phase 5.8.AF.5 / Slice 3a.

§Why this exists

Per paramount goal #4 (CLAUDE.md):

Nothing blocks the UI — enforced architecturally, not by discipline.

Renderers must not read Editor fields directly during render — that read path needs the same &Editor reference the dispatcher holds for mutation, which couples render latency to whatever happens to be mutating Editor at the moment. RenderState is the wait-free read seam: dispatch publishes a fresh snapshot into an ArcSwap<RenderState> at the end of every tick; the renderer loads it once per frame and reads everything it needs from there.

This is the substrate for two follow-on slices:

  • Slice 3b moves every drain in run_tick_pending into per-subsystem background tasks. Each task writes through the same publication path; the renderer never sees a half-built mutation.
  • Slice 3c moves Editor to its own thread. Channels replace &mut Editor references; the renderer becomes a pure RenderState reader.

Both slices preserve the read contract this slice establishes — RenderState doesn’t change shape, just who produces it and on which thread.

§Per-subsystem sub-states

RenderState is split into 11 sub-state structs, one per UI-visible subsystem. Each is Arc-wrapped so a subsystem whose backing state didn’t change between publications can share its sub-state Arc across frames (identity-preserved). In Slice 3b, subsystem background tasks publish their own sub-state directly without re-snapshotting unrelated domains.

The active-buffer hot-path state (cursor, scroll, viewport, modal, visual selection, snapshot pointer) lives in its own ActiveDocumentRenderState — separate from the buffer registry (BuffersRenderState) because the read frequencies differ by orders of magnitude: the active-buffer state churns on every motion/edit (per-frame critical), the registry churns only on :b / :e / :bd. Splitting lets Slice 3b republish them on independent cadences.

For Slice 3a only DiagnosticsRenderState carries real data — that’s the proof-of-life migration path. The other sub-states are deliberately empty placeholders so the shape is in place when their backing fields migrate in later slices.

Structs§

ActiveDocumentRenderState
Active buffer’s hot-path render-side projection.
BufferLocalsRenderState
Buffer-locals per buffer. Slice 3c.final.B.9 — drops the per-frame read_editor(|e| e.buffer_locals.get(&buf).and_then(...)) chain in the modeline, help-render, file-tree, and oil paint paths to a wait-free Arc-bump lookup off the published snapshot.
BuffersRenderState
Buffer registry’s render-side projection — the list of buffers the editor knows about, independent of which one is currently active.
CellsRenderState
Cell-grid renderer substrate state. Mirror of SyntaxRenderState in shape (wait-free output cell + read inputs); replaces the per-frame shape_line path for code-class buffers.
CompletionRenderState
Insert-completion + cmdline-completion popup state.
DiagnosticsRenderState
Diagnostics — the proof-of-life sub-state for Slice 3a.
DiffRenderState
D.3.d.1 (2026-05-29): renderer-side projection of the active document’s diff overlay state. Carries the DiffSignMap for the gutter-sign column; future D.3.e (line tints) reads through the same map.
ExcerptSyntax
D.4.d.1.a (2026-05-29): per-visible-Document-pane build inputs for the cell-builder worker. Mirrors the shape of the top-level CellsRenderState active-doc fields but keyed by (pane_id, buffer_id) so the worker can resolve each entry’s matrix Arc via crate::editor::Editor::cells_matrix_for at publish time and rebuild per visible buffer.
InlayHintRow
One inlay-hint row published on SyntaxRenderState::inlay_hints.
LifecycleRenderState
Renderer lifecycle flags published per tick.
LspRenderState
LSP feature data the renderer reads beyond diagnostics.
MessagesRenderState
*messages* buffer + echo line state.
ModelineRenderState
Modeline status (cmdline text, search indicator, mode hints).
ModesRenderState
Active modes per buffer. Slice 3c.final.B.11 — drops the per-frame read_editor(|e| e.active_modes.get(&buf)) call in the modeline is_messages_buffer check to a wait-free Arc-bump lookup off the published snapshot.
NotificationsRenderState
NOTIF.1b: corner-anchored notifications, as the renderers see them.
OptionsRenderState
Typed-options registry handle. Slice 3c.final.B.10 — drops the per-frame read_editor(|e| e.config.get_typed::<X>()) calls in picker_display_is_minibuffer and elsewhere to a wait-free Arc bump off the published snapshot. The inner ConfigRegistry is already Arc-shared, so a publish here is one Arc clone.
PaneCellsInputs
last_edit is Some(delta) only for the active pane (edits land on the active document; the publish path take()s Editor::last_edit_for_cells exactly once); non-active panes always carry None so the worker conservatively full-rebuilds on text-version bumps for those buffers. That is correct today because non-active buffers don’t take edits in normal use; LSP-driven edits to non-active buffers also flush through apply_edit which clears the slot.
PanesRenderState
Pane tree’s render-side projection.
PickerRenderState
Active picker’s render-side projection.
PopupRenderState
Help / hover / signature popup’s render-side projection.
PublishCache
Perf plan B.4: identity-preserving sub-state cache.
RenderState
The renderer’s read contract with the host. Built fresh by [crate::dispatch::Editor::build_render_state] at the end of every dispatch tick and stored into the editor’s ArcSwap<RenderState>. Renderers load with editor.render_state.load_full() once per frame.
ResolvedOptionsRenderState
PI.4: per-buffer mode-resolved options, published so BOTH renderer peers resolve a buffer’s options (Number, Wrap, CursorLine, …) through ONE renderer-agnostic seam — RenderState::resolved_option_for — instead of the TUI reading the live editor and GPUI reading the active document’s option_cache. Mirror of the host’s Editor::resolved_options; a buffer absent from the map falls back to the global typed-option default via OptionsRenderState::config.
RowOverlayQuad
Perf plan B.2: one pre-bucketed static-overlay quad inside a row of StaticOverlayQuads. Coordinates are in source utf-8 byte space — the byte offsets into the SOURCE line text (not into any combined / inlay-spliced row text).
SignsRenderState
SG.2b — everything a renderer needs to paint a GutterDecoration::Sign, resolved on the actor thread so the render path does neither a string hash nor a theme lookup by name.
StaticOverlayQuads
Perf plan B.2: worker-published per-row pre-bucketed static-overlay quads for the active pane’s visible window.
SyntaxRenderState
Tree-sitter syntax inputs + static-overlay bucket cache.
TabRenderItem
TabsRenderState
Issue #29 (2026-05-22): published per-frame tab snapshot. Carries the user-visible label for each tab + the active index + the resolved visibility decision (auto ⇒ Multi- or-zero already evaluated by the publisher).
TranslatorRenderState
Translator inputs for the renderer’s input loop.
VirtualRowsRenderState
D.3.b.1 (2026-05-29): renderer-side projection of the virtual-rows worker’s published VirtualRowMatrix. Carries the matrix so the TUI / GPUI renderer can interleave virtual rows between document rows when painting visible content.
VisibleHighlightsKey
Cache key identifying the inputs that produced a particular StaticOverlayQuads. The overlay worker compares the current inputs against StaticOverlayQuads::computed_for_key to short-circuit re-bucketing on a no-op tick (cursor blink, unchanged scroll/viewport/folds).

Enums§

OverlayLayer
Perf plan B.2: overlay layer tag carried on each per-row pre-bucketed quad in StaticOverlayQuads. The renderer uses the tag to interleave cursor-coupled layers (current_match, visual_range) at the right precedence at prepaint time:
RowRun
One coloured run within a display row’s combined text.

Functions§

cached_or_build
Perf plan B.4: cache-or-build helper for the sub-state Arc memoisation in build_render_state. Returns the cached Arc when current_version matches the version stored in slot; otherwise calls build, stores the result, and returns it.
inlay_hints_version
Perf plan A.2 slice A.2b.2: content hash of a flattened inlay- hint list. Stable per-payload (same vec → same hash) so it can drive VisibleHighlightsKey::inlay_version for the worker’s row-cache invalidation. Empty list hashes to 0 — matches the inlay_version: 0 default and keeps the steady-state no-hint path on a single cheap branch.
static_overlay_state_version
Perf plan B.2: content hash of the three static-overlay layer payloads. Drives VisibleHighlightsKey::static_overlay_version for the worker’s overlay-bucket invalidation. All-empty payloads hash to 0 so the steady-state no-overlay path stays on a single cheap branch (matches the static_overlay_version: 0 default).