Skip to main content

FrameView

Struct FrameView 

Source
pub struct FrameView<'a> {
Show 15 fields pub app: &'a App, pub folds: Arc<[Fold]>, pub show_line_numbers: bool, pub relative_line_numbers: bool, pub foldenable: bool, pub fold_index: FoldIndex, pub inlay_hints: Arc<[InlayHintRow]>, pub lsp_mode_enabled: bool, pub lsp_diagnostics_enabled: bool, pub lsp_semantic_tokens_enabled: bool, pub lsp_document_highlight_enabled: bool, pub lsp_progress_enabled: bool, pub wrap_lines: bool, pub sign_column: bool, pub content_left_pad: u32,
}
Expand description

Per-render-chain snapshot of App state the renderer reads.

Audit slice 7 / M2. The renderer is one of multiple peer renderer implementations (TUI today, GPUI as part of 1.0, future WebRenderer). The architecture is renderer-agnostic: no render path may depend on single-threaded discipline as its safety mechanism, because GPUI runs on a separate thread from the App’s input loop.

FrameView is taken once at entry to each render chain (compose_visible_lines, draw_inactive_document) and threaded into the chain’s helpers. Internal reads then go through immutable Arc-shared / by-value snapshots; an async mutator that writes the underlying App fields can no longer produce a torn mid-render view, regardless of which thread the renderer runs on.

Fields:

  • app: &App – stable App fields (cursor, modal, command_line, picker, …) that don’t mutate during a render pass even under multi-thread rendering. Read directly through this borrowed reference.
  • folds: Arc<[Fold]> – frozen snapshot. Replaces direct app.editor.folds.iter() reads.
  • show_line_numbers: bool – cached typed-options value. The typed-options ArcSwap read is wait-free per call, but caching once per chain keeps gutter computation deterministic if the option flips mid-chain under multi-thread input.

app.editor.lsp_diagnostics is left as a borrowed &DiagnosticsLayer because that layer is already wait-free behind its own ArcSwap (audit slice 2); the existing line_severity / diagnostics_on_line API is structurally safe to call from any thread.

Fields§

§app: &'a App§folds: Arc<[Fold]>§show_line_numbers: bool§relative_line_numbers: bool

M.4: resolved per-pane in for_buffer; tracks the active buffer’s setting in from_app. Reading this through the view lets per-pane render paths route consistently.

§foldenable: bool

Slice 3c.extension.fold-rs: cache foldenable at view construction. Prior to this, view.line_inside_closed_fold and friends called self.app.foldenable() per line, each triggering an actor mailbox round-trip (~µs–tens-of-µs). One pre-cached bool per frame replaces 120+ RPCs in the compose loop.

§fold_index: FoldIndex

Perf plan C: O(log folds) lookup index built once per frame from folds + foldenable. The compose loop’s per-line line_inside_closed_fold check used to walk every fold per row (iter().any(...) — O(rows × folds)); via this index it becomes a partition-point binary search with a constant-time fast path for the common non-overlapping case.

§inlay_hints: Arc<[InlayHintRow]>

Fold-bleed follow-up (2026-06-30): this pane’s OWN byte-baked inlay-hint rows, resolved via RenderState::inlay_hints_for_buffer (active → baked syntax.inlay_hints; inactive → published cells.panes entry). One source for both focus states so the compose loop splices hints through a single path — no active-vs-inactive divergence to drift.

§lsp_mode_enabled: bool

Slice 3c.extension.fold-rs: per-frame LSP-mode gates, cached once at FrameView::from_app so the compose loop’s per-line decoration checks don’t pay actor-RPC cost. Each is one read_editor at frame entry; a 120-row paint that previously triggered 120× per-line RPC for app.lsp_semantic_tokens_mode_enabled_for(...) now reads view.lsp_semantic_tokens_enabled directly.

§lsp_diagnostics_enabled: bool§lsp_semantic_tokens_enabled: bool§lsp_document_highlight_enabled: bool§lsp_progress_enabled: bool

Slice A.2b.2: inlay-hint mode gate moved to publish-time (Editor::build_active_inlay_hints returns an empty list when the mode is off). The compose loop no longer reads this field; rs.syntax.inlay_hints is already gated, so is_empty() on the published list is the cheap fast-path check.

§wrap_lines: bool

Whether soft-wrap is enabled for this pane’s buffer. Global option today (option_cache.wrap_lines); the seam for per-buffer options: when buffer-local options land, for_buffer resolves from that buffer’s local value with the global default as fallback (emacs buffer-local pattern). Compose paths read view.wrap_lines instead of touching app.ad().option_cache directly so the resolver is always in one place.

§sign_column: bool

PU.1b-1a (signcolumn): whether to reserve this pane’s gutter sign columns (diagnostics severity + diff sign). Resolved per-buffer like every other view option — from_app reads the active buffer’s option_cache.sign_column; for_buffer reads app.sign_column_for(buffer_id). The compose path reserves the two sign cells iff this is true, so a buffer with signcolumn=no (help-mode, synthetic buffers) renders gutterless without the renderer knowing it’s help.

§content_left_pad: u32

DB.4: extra leading gutter cells to horizontally centre the buffer’s content (dashboard). Added to the computed gutter width for both document lines and virtual rows, so content + cursor shift right. 0 for every non-centred buffer.

Implementations§

Source§

impl<'a> FrameView<'a>

Source

pub fn from_app(app: &'a App) -> Self

Snapshot the App’s per-render-chain state once.

Arc::from(Vec<T>) is one alloc + a memcpy of the slice metadata; the underlying span / fold data already lives in heap-allocated vecs, so the snapshot cost is O(folds.len() + viewport_height) – negligible at terminal sizes. GPUI-era multi-thread rendering can call this from the render thread without taking any App lock; the App’s main loop owns the underlying vecs and the snapshot is consistent at the moment from_app runs.

Source

pub fn for_buffer(app: &'a App, buffer_id: BufferId) -> Self

M.4: per-pane FrameView – resolves options for buffer_id instead of capturing the active buffer’s settings. Used by inactive-pane render paths so each pane’s mode stack drives its own gutter independently. DR.2: inactive panes now source decorations from their own per-pane DisplayMatrix; pane_highlights is retired.

Source

pub fn fold_start_at_any(&self, line: u32) -> Option<&Fold>

Mirror of App::fold_start_at_any but reads from the frozen view.folds snapshot instead of app.editor.folds. Used by the gutter glyph provider so the renderer’s view of folds can’t go out of sync with the snapshot it took at chain entry.

Source

pub fn fold_start_at(&self, line: u32) -> Option<&Fold>

Mirror of App::fold_start_at – only matches CLOSED folds at line. Reads from the frozen view.folds snapshot.

Source

pub fn line_inside_closed_fold(&self, line: u32) -> bool

Mirror of App::line_inside_closed_fold reading from the snapshot.

Perf plan C: routes through the per-frame lattice_host::folds::FoldIndex so the per-line cost in compose loops drops from O(folds) to O(log folds) amortized constant. The foldenable short-circuit is baked into the index at construction time — no extra branch here.

Auto Trait Implementations§

§

impl<'a> !RefUnwindSafe for FrameView<'a>

§

impl<'a> !Send for FrameView<'a>

§

impl<'a> !Sync for FrameView<'a>

§

impl<'a> !UnwindSafe for FrameView<'a>

§

impl<'a> Freeze for FrameView<'a>

§

impl<'a> Unpin for FrameView<'a>

§

impl<'a> UnsafeUnpin for FrameView<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> IntoMaybeUndefined<T> for T

§

fn into_maybe_undefined(self) -> MaybeUndefined<T>

Converts this value into a three-state builder argument.
§

impl<T> IntoOption<T> for T

§

fn into_option(self) -> Option<T>

Converts this value into an optional builder argument.
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> Pointee for T

§

type Pointer = u32

§

fn debug( pointer: <T as Pointee>::Pointer, f: &mut Formatter<'_>, ) -> Result<(), Error>

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more