Domain facade for buffer operations.
This is the only valid entry point for code outside the buffer domain. All buffer operations go through this module: reading content, moving cursors, editing text, persisting files, and managing decorations.
Internally delegates to Minga.Buffer.Process (GenServer) and
Minga.Buffer.Document (pure data structure). External callers
should never reference those modules directly.
Summary
Functions
Accept content as the saved base revision and clear dirty state.
Acknowledge the current disk metadata after keeping local edits during a file-change conflict.
Add a block decoration (multi-line annotation) anchored to a line.
Add a highlight range.
Add virtual text anchored to a line.
Append text to the end of the buffer.
Replace text in a range with new text (the general-purpose edit operation).
Apply a batch of edits atomically (for LSP workspace edits).
Apply a cursor motion inside the buffer process.
Apply a batch of decoration changes atomically.
Force the next edit to start a new undo group.
Logical name of the buffer (e.g., *Messages*), or nil for file buffers.
Buffer kind: :file, :scratch, or :special.
Byte offset of the start of a line (for tree-sitter integration).
Supervisor child spec for starting a buffer process.
Remove a face override for this buffer.
Clear the contents of a single line.
Commit a previously captured document snapshot.
Consume edit deltas accumulated since the given consumer's last read, or return :reset_required when the consumer must full-sync.
Full text content of the buffer.
Content and cursor position in a single call (avoids two round-trips).
Content of lines from start_line to end_line (inclusive, 0-indexed).
Grapheme count between two positions (end inclusive, includes the character at end_pos).
Current cursor position as {line, col}.
Current decoration state (highlights, virtual text, folds, etc.).
Version counter for decorations (for change detection).
Delete the character at the cursor.
Delete the character before the cursor.
Delete lines from start_line to end_line (inclusive).
Delete text between two positions.
Whether the buffer has unsaved changes.
Human-readable display name (file basename or buffer name).
Returns the pid for a buffer at path, starting one if it doesn't exist.
Current face override map.
File path of the buffer, or nil for scratch buffers.
Detected filetype (e.g., :elixir, :json).
Find and replace the first occurrence of old_text with new_text.
Find and replace multiple patterns atomically.
Save even if the buffer appears clean.
Read a per-buffer option (falls back to global config).
Insert a single character at the cursor.
Insert a multi-character string at the cursor.
Number of lines in the buffer.
A range of lines starting at start (0-indexed), returning count lines.
Returns only options explicitly overridden on this buffer.
Returns all buffer option values currently cached on this buffer.
Move the cursor one step in a direction.
Move cursor if possible, returning the result position and whether a boundary was hit.
Move the cursor to an exact position.
Open a file into the buffer, replacing current content.
Whether the buffer survives tab close (e.g., *Messages*).
Look up a buffer process by its file path. Returns :not_found if no buffer has that file open.
Whether the buffer is read-only.
Redo the last undone edit.
Reload content from disk, discarding unsaved changes.
Override a face's attributes for this buffer.
Remove a block decoration by ID.
Remove a highlight by ID.
Remove all highlights in a group.
Remove virtual text by ID.
Render-ready snapshot of visible lines for the rendering pipeline.
Replace the entire buffer content.
Replace buffer content and apply decorations in one atomic operation.
Replace generated/internal content, bypassing user read-only restrictions.
Retargets the buffer to a new file path without writing content.
Save the buffer to disk.
Saves all dirty file-backed buffers to disk.
Save the buffer to a new file path.
Override the detected filetype.
Set a per-buffer option override.
Capture a snapshot of the document state (for undo boundaries and tab switching).
Start a new buffer process.
Text between two positions (end inclusive, includes the character at end_pos).
Undo the last edit.
Undo all consecutive agent-sourced entries from the top of the undo stack.
Whether the buffer is hidden from buffer lists.
Monotonic version counter (incremented on every content change).
Types
@type boundary() :: Minga.Buffer.Process.boundary()
@type direction() :: :left | :right | :up | :down
@type document() :: Minga.Buffer.Document.t()
@type motion_fun() :: Minga.Buffer.Process.motion_fun()
@type position() :: {line :: non_neg_integer(), col :: non_neg_integer()}
@type replace_edit() :: Minga.Buffer.Process.replace_edit()
@type replace_result() :: Minga.Buffer.Process.replace_result()
@type server() :: t()
@type t() :: GenServer.server()
@type text_edit() :: Minga.Buffer.Process.text_edit()
Functions
Accept content as the saved base revision and clear dirty state.
@spec acknowledge_disk_change(t()) :: :ok
Acknowledge the current disk metadata after keeping local edits during a file-change conflict.
@spec add_block_decoration(t(), non_neg_integer(), keyword()) :: reference()
Add a block decoration (multi-line annotation) anchored to a line.
@spec add_highlight( t(), Minga.Core.Decorations.highlight_range_pos(), Minga.Core.Decorations.highlight_range_pos(), keyword() ) :: reference()
Add a highlight range.
@spec add_virtual_text(t(), Minga.Core.Decorations.highlight_range_pos(), keyword()) :: reference()
Add virtual text anchored to a line.
Append text to the end of the buffer.
@spec apply_edit( t(), non_neg_integer(), non_neg_integer(), non_neg_integer(), non_neg_integer(), String.t(), Minga.Buffer.EditSource.t() ) :: :ok
Replace text in a range with new text (the general-purpose edit operation).
@spec apply_edits(t(), [text_edit()], Minga.Buffer.EditSource.t()) :: :ok
Apply a batch of edits atomically (for LSP workspace edits).
@spec apply_motion(t(), motion_fun()) :: :ok
Apply a cursor motion inside the buffer process.
@spec batch_decorations(t(), (Minga.Core.Decorations.t() -> Minga.Core.Decorations.t())) :: :ok
Apply a batch of decoration changes atomically.
@spec break_undo_coalescing(t()) :: :ok
Force the next edit to start a new undo group.
Logical name of the buffer (e.g., *Messages*), or nil for file buffers.
@spec buffer_type(t()) :: :file | :scratch | :special
Buffer kind: :file, :scratch, or :special.
@spec byte_offset_for_line(t(), non_neg_integer()) :: non_neg_integer()
Byte offset of the start of a line (for tree-sitter integration).
@spec child_spec([Minga.Buffer.Process.start_opt()]) :: Supervisor.child_spec()
Supervisor child spec for starting a buffer process.
Remove a face override for this buffer.
@spec clear_line(t(), non_neg_integer()) :: {:ok, String.t()}
Clear the contents of a single line.
Commit a previously captured document snapshot.
@spec consume_edit_deltas(t(), atom()) :: Minga.Buffer.Process.edit_delta_update()
Consume edit deltas accumulated since the given consumer's last read, or return :reset_required when the consumer must full-sync.
Full text content of the buffer.
Content and cursor position in a single call (avoids two round-trips).
@spec content_on_lines(t(), non_neg_integer(), non_neg_integer()) :: String.t()
Content of lines from start_line to end_line (inclusive, 0-indexed).
@spec content_range_length(t(), position(), position()) :: non_neg_integer()
Grapheme count between two positions (end inclusive, includes the character at end_pos).
Current cursor position as {line, col}.
@spec decorations(t()) :: Minga.Core.Decorations.t()
Current decoration state (highlights, virtual text, folds, etc.).
@spec decorations_version(t()) :: non_neg_integer()
Version counter for decorations (for change detection).
@spec delete_at(t()) :: :ok
Delete the character at the cursor.
@spec delete_before(t()) :: :ok
Delete the character before the cursor.
@spec delete_lines(t(), non_neg_integer(), non_neg_integer()) :: :ok
Delete lines from start_line to end_line (inclusive).
Delete text between two positions.
Whether the buffer has unsaved changes.
Human-readable display name (file basename or buffer name).
@spec ensure_for_path(String.t(), Minga.Events.registry(), keyword()) :: {:ok, pid()} | {:error, term()}
Returns the pid for a buffer at path, starting one if it doesn't exist.
If a buffer is already registered for path, returns its pid immediately.
Otherwise, starts a new buffer under Minga.Buffer.Supervisor and
broadcasts a :buffer_opened event so the Editor and other subscribers
can pick it up.
Used by agent tools to guarantee every edited file has a buffer with undo integration, without depending on the Editor (Layer 2).
Current face override map.
File path of the buffer, or nil for scratch buffers.
Detected filetype (e.g., :elixir, :json).
@spec find_and_replace(t(), String.t(), String.t(), boundary()) :: {:ok, String.t()} | {:error, String.t()}
Find and replace the first occurrence of old_text with new_text.
@spec find_and_replace_batch(t(), [replace_edit()], boundary()) :: {:ok, [replace_result()]} | {:error, String.t()}
Find and replace multiple patterns atomically.
Save even if the buffer appears clean.
Read a per-buffer option (falls back to global config).
@spec insert_char(t(), String.t(), Minga.Buffer.EditSource.t()) :: :ok
Insert a single character at the cursor.
@spec insert_text(t(), String.t(), Minga.Buffer.EditSource.t()) :: :ok
Insert a multi-character string at the cursor.
@spec line_count(t()) :: pos_integer()
Number of lines in the buffer.
@spec lines(t(), non_neg_integer(), non_neg_integer()) :: [String.t()]
A range of lines starting at start (0-indexed), returning count lines.
Returns only options explicitly overridden on this buffer.
Returns all buffer option values currently cached on this buffer.
Move the cursor one step in a direction.
Move cursor if possible, returning the result position and whether a boundary was hit.
Move the cursor to an exact position.
Open a file into the buffer, replacing current content.
Whether the buffer survives tab close (e.g., *Messages*).
Look up a buffer process by its file path. Returns :not_found if no buffer has that file open.
Whether the buffer is read-only.
@spec redo(t()) :: :ok | :empty
Redo the last undone edit.
Reload content from disk, discarding unsaved changes.
Override a face's attributes for this buffer.
Remove a block decoration by ID.
Remove a highlight by ID.
Remove all highlights in a group.
Remove virtual text by ID.
@spec render_snapshot(t(), non_neg_integer(), non_neg_integer()) :: Minga.Buffer.RenderSnapshot.t()
Render-ready snapshot of visible lines for the rendering pipeline.
@spec replace_content(t(), String.t(), Minga.Buffer.State.edit_source()) :: :ok | {:error, term()}
Replace the entire buffer content.
Replace buffer content and apply decorations in one atomic operation.
Replace generated/internal content, bypassing user read-only restrictions.
Retargets the buffer to a new file path without writing content.
Save the buffer to disk.
@spec save_all_dirty() :: {non_neg_integer(), [String.t()]}
Saves all dirty file-backed buffers to disk.
Enumerates the Buffer.Registry, filters for dirty buffers, and saves each one. Read-only buffers and save failures are logged as warnings but do not block other saves. Returns the count of successfully saved buffers and a list of any warnings (path + error reason).
Save the buffer to a new file path.
Override the detected filetype.
Set a per-buffer option override.
Capture a snapshot of the document state (for undo boundaries and tab switching).
@spec start_link([Minga.Buffer.Process.start_opt()]) :: GenServer.on_start()
Start a new buffer process.
@spec storage(t()) :: Minga.Buffer.State.storage()
Text between two positions (end inclusive, includes the character at end_pos).
@spec undo(t()) :: :ok | :empty
Undo the last edit.
@spec undo_agent_session(t()) :: {:ok, non_neg_integer()} | :empty
Undo all consecutive agent-sourced entries from the top of the undo stack.
Whether the buffer is hidden from buffer lists.
@spec version(t()) :: non_neg_integer()
Monotonic version counter (incremented on every content change).