pub struct BufferRegistry { /* private fields */ }Expand description
The App’s buffer registry. Methods take &self and lock
internally; the registry is Clone so the App’s
BufferStore service impl can hold a clone for cross-thread
access.
Perf plan B.4.b: carries an AtomicU64 version counter
alongside the inner. Every mutating method (insert, remove,
set_flags, set_name, and every with_*_mut closure
accessor) bumps it. Versioned<T>’s DerefMut discipline can’t
fire here because the registry uses interior mutability —
callers take &self rather than &mut self, so autoref through
DerefMut is impossible. The atomic is shared via the same
Arc<...> clone as inner so every registry handle sees the
same counter; Clone is one Arc bump for the pair.
version() is the read API. The BuffersRenderState /
TabsRenderState caches on Editor::publish_cache compare
against the prior captured value to decide cache reuse vs.
rebuild.
Implementations§
Source§impl BufferRegistry
impl BufferRegistry
Sourcepub fn version(&self) -> u64
pub fn version(&self) -> u64
Perf plan B.4.b: monotonic mutation counter. Read by the
publish cache (see crate::render_state::PublishCache)
to decide whether the cached buffers / tabs Arcs can be
reused across publishes. Relaxed ordering is fine because
the publish path runs on the actor thread; we only need the
counter to advance after a mutation, not to synchronise
memory order with other writers.
Source§impl BufferRegistry
impl BufferRegistry
pub fn new() -> BufferRegistry
pub fn insert(&self, entry: BufferEntry)
pub fn remove(&self, id: BufferId) -> Option<BufferEntry>
pub fn contains(&self, id: BufferId) -> bool
pub fn len(&self) -> usize
pub fn is_empty(&self) -> bool
Sourcepub fn kind_of(&self, id: BufferId) -> Option<BufferKind>
pub fn kind_of(&self, id: BufferId) -> Option<BufferKind>
Kind of the entry at id, or None if absent.
Sourcepub fn name_of(&self, id: BufferId) -> Option<String>
pub fn name_of(&self, id: BufferId) -> Option<String>
Synthetic name of the entry at id, or None if absent
or if the entry has no name set.
Sourcepub fn flags_of(&self, id: BufferId) -> Option<BufferFlags>
pub fn flags_of(&self, id: BufferId) -> Option<BufferFlags>
Per-buffer flags. BufferFlags is Copy so this returns
owned without locking issues.
Sourcepub fn set_flags(&self, id: BufferId, flags: BufferFlags) -> bool
pub fn set_flags(&self, id: BufferId, flags: BufferFlags) -> bool
Mutate the per-buffer flags via callback (e.g. flip
listed on :setlocal nobuflisted once that lands).
Sourcepub fn set_name(&self, id: BufferId, name: Option<String>) -> bool
pub fn set_name(&self, id: BufferId, name: Option<String>) -> bool
Rename the entry’s synthetic name slot. Used by the
supervisor when an actor exits and the per-instance buffer
gets renamed *lsp:rust:/path* → *lsp:rust:/path (exited)*.
Sourcepub fn document_handle(&self, id: BufferId) -> Option<Arc<dyn Document>>
pub fn document_handle(&self, id: BufferId) -> Option<Arc<dyn Document>>
Kind-specific convenience: clone the Arc<dyn Document>
for id. The handle is Send + Sync and can be held
across thread boundaries. M.0: returns the polymorphic
shape (was RopeDocumentHandle pre-M.0) so the registry
serves multibuffer handles (M.1) through the same path.
Sourcepub fn buffer_id_for_document(
&self,
document_id: DocumentId,
) -> Option<BufferId>
pub fn buffer_id_for_document( &self, document_id: DocumentId, ) -> Option<BufferId>
D.3.a.1 (2026-05-29): reverse lookup —
DocumentId → BufferId. Used by the
diff subsystem’s DocumentBufferResolver impl: bus
events carry DocumentId, host-side state is keyed by
BufferId. Scans the registry’s document entries —
O(N_documents) per call, acceptable at v1 buffer counts
(~tens; the LSP fan-in and the keymap registry do
similar walks). Future inverse index lives behind the
same method signature.
Sourcepub fn document_path(&self, id: BufferId) -> Option<PathBuf>
pub fn document_path(&self, id: BufferId) -> Option<PathBuf>
Kind-specific convenience: path of the document at id.
Sourcepub fn document_dirty(&self, id: BufferId) -> bool
pub fn document_dirty(&self, id: BufferId) -> bool
Kind-specific convenience: dirty flag for the document
at id. Returns false for absent / non-document.
pub fn contains_document(&self, id: BufferId) -> bool
Sourcepub fn contains_messages(&self, id: BufferId) -> bool
pub fn contains_messages(&self, id: BufferId) -> bool
True iff the entry at id is the *messages* transcript.
Symmetric with Self::contains_help /
Self::contains_oil / Self::contains_file_tree —
callers that need to differentiate the Messages identity
from a regular Document branch on this.
pub fn contains_file_tree(&self, id: BufferId) -> bool
pub fn contains_help(&self, id: BufferId) -> bool
pub fn contains_oil(&self, id: BufferId) -> bool
Sourcepub fn entry_summary(
&self,
id: BufferId,
) -> Option<(BufferId, BufferKind, BufferFlags, Option<String>)>
pub fn entry_summary( &self, id: BufferId, ) -> Option<(BufferId, BufferKind, BufferFlags, Option<String>)>
Compact snapshot of an entry: (id, kind, flags, name, is_document_path_set). Used by :ls and the buffer picker
to render rows without holding the lock through complex
display logic. Returns None if the entry is absent.
Sourcepub fn sorted_ids(&self) -> Vec<BufferId>
pub fn sorted_ids(&self) -> Vec<BufferId>
All ids in ascending order. Used by :bn / :bp for
deterministic cycling order independent of HashMap
hash-randomization.
Sourcepub fn listed_ids_sorted(&self) -> Vec<BufferId>
pub fn listed_ids_sorted(&self) -> Vec<BufferId>
All listed ids in ascending order. :bn / :bp skip
unlisted buffers (vim semantics); :ls shows them under a
separate header (post-v1 polish).
Sourcepub fn document_ids_sorted(&self) -> Vec<BufferId>
pub fn document_ids_sorted(&self) -> Vec<BufferId>
Document buffers only, sorted by id. The *messages*
transcript stores as BufferData::Messages (see
Self::messages_ids_sorted) so it is excluded from
this list even though storage is identical; callers that
want every rope-backed-doc kind should walk both.
Sourcepub fn messages_ids_sorted(&self) -> Vec<BufferId>
pub fn messages_ids_sorted(&self) -> Vec<BufferId>
*messages* (and any future Messages-kind) buffers,
sorted by id. Symmetric with Self::document_ids_sorted.
Sourcepub fn multibuffer_ids_sorted(&self) -> Vec<BufferId>
pub fn multibuffer_ids_sorted(&self) -> Vec<BufferId>
K.4.8 (2026-06-02): Multibuffer-kind buffers, sorted by id.
Symmetric with Self::messages_ids_sorted /
Self::document_ids_sorted. Used by :ls to count the
Multibuffer entries separately from Messages now that
Multibuffer has its own listing row.
Sourcepub fn file_tree_ids_sorted(&self) -> Vec<BufferId>
pub fn file_tree_ids_sorted(&self) -> Vec<BufferId>
File-tree buffers only, sorted by id.
Sourcepub fn help_ids_sorted(&self) -> Vec<BufferId>
pub fn help_ids_sorted(&self) -> Vec<BufferId>
Help buffers only, sorted by id.
pub fn oil_ids_sorted(&self) -> Vec<BufferId>
Sourcepub fn file_tree_ids(&self) -> Vec<BufferId>
pub fn file_tree_ids(&self) -> Vec<BufferId>
IDs of every registered file-tree buffer, in arbitrary
order. The App-side file_tree_with_root walks these +
probes each one’s FileTreeRoot buffer-local for the
dedup lookup; the registry can’t do that walk because it
doesn’t own buffer-locals.
Sourcepub fn by_name(&self, name: &str) -> Option<BufferId>
pub fn by_name(&self, name: &str) -> Option<BufferId>
First buffer whose name matches exactly. Used by
subsystem-owned synthetic buffers (*lsp*, *messages*,
per-instance LSP log buffers) so re-running the
owner’s create-or-activate path surfaces the existing
entry rather than allocating a duplicate.
Sourcepub fn help_with_title(&self, title: &str) -> Option<BufferId>
pub fn help_with_title(&self, title: &str) -> Option<BufferId>
First help buffer with the given title, if any. Used by the
:lsp-log / :lsp-trace-log openers so re-running the
command surfaces the existing buffer rather than allocating
a duplicate.
Sourcepub fn document_with_path(&self, path: &Path) -> Option<BufferId>
pub fn document_with_path(&self, path: &Path) -> Option<BufferId>
First document buffer with the given path, if any. Used by
:e FILE to detect “already open”.
Sourcepub fn with_entry<R>(
&self,
id: BufferId,
f: impl FnOnce(&BufferEntry) -> R,
) -> Option<R>
pub fn with_entry<R>( &self, id: BufferId, f: impl FnOnce(&BufferEntry) -> R, ) -> Option<R>
Run f against the BufferEntry at id while holding
the registry lock. Returns None if the entry is absent.
Sourcepub fn with_entry_mut<R>(
&self,
id: BufferId,
f: impl FnOnce(&mut BufferEntry) -> R,
) -> Option<R>
pub fn with_entry_mut<R>( &self, id: BufferId, f: impl FnOnce(&mut BufferEntry) -> R, ) -> Option<R>
Mutable variant of Self::with_entry.
Perf plan B.4.b: conservatively bumps the version after the closure runs, even if the closure didn’t actually mutate. Over-bumping causes a one-time cache miss on the next publish — safe and bounded — versus the alternative of missing a real mutation, which would leave stale Arcs visible to renderers indefinitely.
pub fn with_document<R>( &self, id: BufferId, f: impl FnOnce(&DocumentEntry) -> R, ) -> Option<R>
pub fn with_document_mut<R>( &self, id: BufferId, f: impl FnOnce(&mut DocumentEntry) -> R, ) -> Option<R>
Sourcepub fn help_content_view(&self, id: BufferId) -> Option<HelpBuffer>
pub fn help_content_view(&self, id: BufferId) -> Option<HelpBuffer>
PU.1a: reconstruct a transient HelpBuffer view from the
registry Document at id. Help content is now an actor-backed
synthetic Document; this builds the slim view value the bespoke
help renderers still consume (PU.1b deletes both). The view’s
scroll / cursor default to 0 — callers overlay the live
popup (popup_scroll/popup_cursor) or pane scroll+cursor.
None when id is not a help buffer.
pub fn with_terminal<R>( &self, id: BufferId, f: impl FnOnce(&TerminalBuffer) -> R, ) -> Option<R>
pub fn with_terminal_mut<R>( &self, id: BufferId, f: impl FnOnce(&mut TerminalBuffer) -> R, ) -> Option<R>
Sourcepub fn for_each<F>(&self, f: F)where
F: FnMut(&BufferEntry),
pub fn for_each<F>(&self, f: F)where
F: FnMut(&BufferEntry),
Run f against every entry under the registry lock.
Callers must not re-enter the registry from inside.
Trait Implementations§
Source§impl BufferStore for BufferRegistry
impl BufferStore for BufferRegistry
Source§fn contains_buffer(&self, id: BufferId) -> bool
fn contains_buffer(&self, id: BufferId) -> bool
Answered exactly rather than through the trait’s best-effort default: this registry holds the map, so it can see a registered buffer that has no name, no path and no document handle — which the default reports as absent.
Source§fn insert_document_buffer(
&self,
id: BufferId,
kind: BufferKind,
handle: Arc<dyn Document>,
flags: BufferFlags,
name: Option<String>,
)
fn insert_document_buffer( &self, id: BufferId, kind: BufferKind, handle: Arc<dyn Document>, flags: BufferFlags, name: Option<String>, )
H.1 (2026-05-31): generic Document-shaped buffer
insertion for extension crates (lattice-multibuffer
today; future plugin-defined Document-shaped kinds).
Maps kind to the appropriate BufferData variant;
other kinds (FileTree, Oil, Terminal, Help)
log + skip — their payload is not a Document.
Source§fn find_by_name(&self, name: &str) -> Option<BufferId>
fn find_by_name(&self, name: &str) -> Option<BufferId>
name matches exactly.
Returns None when no buffer with that synthetic name is
registered yet.Source§fn handle_for(&self, id: BufferId) -> Option<Arc<dyn Document>>
fn handle_for(&self, id: BufferId) -> Option<Arc<dyn Document>>
Arc<dyn Document> for id,
suitable for holding across thread boundaries. M.0: the
return type is the polymorphic shape so the same
surface serves both regular-document handles and (M.1+)
multibuffer handles uniformly. The handle is the only
way for a mode-owned background task to write into the
buffer (handle.apply_edit_batch(...)). Read moreSource§fn name_for(&self, id: BufferId) -> Option<String>
fn name_for(&self, id: BufferId) -> Option<String>
None when the buffer is
unnamed (the default for path-less scratch documents) or
when id is not registered. B’.7: lets a mode derive its
own identity from the buffer it’s attached to without the
host having to seed a buffer-local first.Source§impl Clone for BufferRegistry
impl Clone for BufferRegistry
Source§fn clone(&self) -> BufferRegistry
fn clone(&self) -> BufferRegistry
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for BufferRegistry
impl Debug for BufferRegistry
Source§impl Default for BufferRegistry
impl Default for BufferRegistry
Source§fn default() -> BufferRegistry
fn default() -> BufferRegistry
Source§impl TerminalStore for BufferRegistry
impl TerminalStore for BufferRegistry
Source§fn install_synthetic(&self, id: BufferId) -> bool
fn install_synthetic(&self, id: BufferId) -> bool
true if
a terminal buffer existed for id (and the doc was
installed); false otherwise. Idempotent — re-calling
rebuilds the doc.Source§fn clear_synthetic(&self, id: BufferId) -> bool
fn clear_synthetic(&self, id: BufferId) -> bool
true if a terminal buffer existed for id;
false otherwise.Auto Trait Implementations§
impl Freeze for BufferRegistry
impl RefUnwindSafe for BufferRegistry
impl Send for BufferRegistry
impl Sync for BufferRegistry
impl Unpin for BufferRegistry
impl UnsafeUnpin for BufferRegistry
impl UnwindSafe for BufferRegistry
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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