← Overview Stage 4 / Editor & Actions
Stage 4 of 7

Editor & Actions

Editor is the central text-editing component. It receives actions from GPUI, translates them into cursor movements and buffer mutations, and drives the display pipeline through DisplayMap.

Editor Struct (selected fields)
Editor editor.rs:883
pub struct Editor { // Core text state buffer: Entity<MultiBuffer>, // owns the text display_map: Entity<DisplayMap>, selections: SelectionsCollection, // all cursors/ranges scroll_manager: ScrollManager, // Input / interaction mode: EditorMode, // full / single-line / auto-height snippet_stack: InvalidationStack<SnippetState>, columnar_selection: Option<ColumnarSelectionState>, // Language features completion_tasks: Vec<(CompletionId, Task<()>)>, signature_help_state: SignatureHelpState, inline_diagnostics: Vec<(Anchor, InlineDiagnostic)>, // UI / gutter show_gutter: bool, show_line_numbers: Option<bool>, blink_manager: Entity<BlinkManager>, }
Keystroke → Buffer Edit (Full Path)

Here is the complete chain from a keypress to a text change, using 'a' typed at cursor position 10 as an example:

1
Keymap resolves 'a' → Insert { text: "a" }
GPUI's Keymap looks up the keystroke in the active bindings. Most printable characters resolve to a generic Insert action. (See GPUI.)
2
Editor::handle_input()
input.rs:66 — validates the input (IME, read-only check), then calls self.insert(text, cx).
3
Editor::insert() — computes edits from selections
For each selection range (collapsed cursor = zero-width range at position 10), replaces the range with the typed text. Auto-pairs, snippets, and bracket-matching logic runs here.
4
MultiBuffer::edit() — transactional edit
The edit is grouped in a transaction for undo. MultiBuffer maps the display-space edit to excerpt coordinates and forwards to each underlying Buffer.
5
Buffer::edit() — CRDT op applied
The CRDT TextBuffer records the insertion. Observers (syntax re-parser, LSP notifier) receive a BufferEvent::Edited. See Buffer & Language.
6
Selections advanced, cx.notify() called
The cursor advances past the inserted character. cx.notify() queues a re-render, which flows through the display pipeline. See Rendering.
Action Categories

Defined in actions.rs. Actions are defined with the actions! macro for zero-data actions or #[derive(Action)] for actions with data.

// Movement — zero data, registered as actions!(...) MoveLeft, MoveRight, MoveUp, MoveDown MoveToEndOfLine, MoveToBeginningOfLine SelectAll, SelectLine // Editing DeleteToBeginningOfLine, DeleteToEndOfLine Undo, Redo, Cut, Copy, Paste // Language features ShowCompletions, HoverAtCursor, GoToDefinition Rename, Format, ToggleComments
Display Map — Visual Transforms

DisplayMap (display_map.rs) sits between the raw buffer and the rendered output. It answers questions like "where on screen does buffer position 42 appear?"

Transform What it does
Soft wrap Splits long lines at the viewport edge — buffer line 1 might become display rows 1 and 2
Folding Collapses a range (e.g. a function body) to a single placeholder row
Inlay hints Inserts virtual text from LSP between buffer characters (type annotations, parameter names)
Git diff hunks Inserts virtual lines for added/removed content from the current diff
Diagnostic messages Appends inline error/warning text at end of line

The rendering code always works in display-space coordinates. Conversions between buffer and display space go through DisplaySnapshot::buffer_point_to_display_point() and the inverse.

Code References