← Overview Stage 5 / Buffer & Language
Stage 5 of 7

Buffer & Language

Text lives in a CRDT TextBuffer, wrapped by Buffer (adds language, syntax tree, diagnostics), and optionally composed into a MultiBuffer (multiple excerpts, shared undo history).

Text Storage Layers
MultiBuffer Composite of one or more buffer excerpts + undo history
Buffer Single file: text + syntax tree + diagnostics + language
TextBuffer (CRDT) Rope of characters with operation log for collaborative editing

An Editor always owns a MultiBuffer. For normal single-file editing, the MultiBuffer wraps exactly one Buffer with a single excerpt covering the whole file.

Buffer Struct
Buffer buffer.rs:98
pub struct Buffer { text: TextBuffer, // CRDT rope syntax_map: Mutex<SyntaxMap>, // tree-sitter parse state language: Option<Arc<Language>>, diagnostics: TreeMap<LanguageServerId, DiagnosticSet>, remote_selections: TreeMap<ReplicaId, SelectionSet>, parse_status: (watch::Sender<ParseStatus>, ...), reparse: Option<Task<()>>, // pending background parse file: Option<Arc<dyn File>>, saved_mtime: Option<MTime>, }

Every edit to text invalidates the syntax tree. A background_spawn task runs SyntaxMap::reparse() and then drops its result back onto the foreground by updating the Buffer entity and calling cx.notify().

BufferSnapshot buffer.rs:186

An immutable, point-in-time copy of all buffer state. EditorElement takes a snapshot once per frame and uses it for rendering — changes during the frame don't affect what's painted. The snapshot owns the parsed tree and all diagnostics.

MultiBuffer — Composite View
MultiBuffer multi_buffer.rs:73
pub struct MultiBuffer { buffers: BTreeMap<BufferId, BufferState>, excerpts: RefCell<MultiBufferSnapshot>, history: History, // unified undo/redo across all excerpts diffs: HashMap<BufferId, DiffState>, }

Use-cases for MultiBuffer with multiple excerpts: search results (grep matches from many files shown inline), go-to-definition peek panel, and multi-file refactor previews.

Language & Syntax Parsing
Language language.rs:849
pub struct Language { id: LanguageId, config: LanguageConfig, // name, file extensions, LSP config grammar: Option<Arc<Grammar>>, // tree-sitter grammar context_provider: Option<Arc<dyn ContextProvider>>, }

Languages are registered in LanguageRegistry. When a buffer's file path changes or content hints at a language (shebangs, magic bytes), the registry detects and assigns the right Language.

Syntax Parse Flow
1
Buffer edit applied
TextBuffer records the op and emits a range of changed bytes.
2
Syntax tree invalidated
The changed byte range is passed to SyntaxMap::did_edit(), marking the affected tree nodes as stale.
3
Background reparse launched
cx.background_spawn runs tree-sitter's incremental parser using the grammar. Only the stale subtrees are re-parsed.
4
Parse result written back
The new tree is stored in Buffer::syntax_map. cx.notify() triggers a re-render which picks up the updated token highlights.
Incremental parsing: tree-sitter only re-parses the changed subtree. For a 10,000-line file with a one-character edit, reparsing is typically sub-millisecond.
Code References