etui/buffer
Types
A diff operation: move cursor to position, write a run of cells.
pub type BufferOp {
Patch(position: geometry.Position, cells: List(Cell))
}
Constructors
-
Patch(position: geometry.Position, cells: List(Cell))
One cell in the terminal grid: a grapheme + its style + optional hyperlink.
The style is resolved (see style.resolve): whatever it turns off has
already been taken off, so two cells that look the same compare equal and
the diff leaves them alone.
pub type Cell {
Cell(content: CellContent, style: style.Style, link: String)
}
Constructors
-
Cell(content: CellContent, style: style.Style, link: String)Arguments
- link
-
OSC 8 hyperlink URI. Empty string = no link. Emitted on render.
Content variant for a terminal cell.
pub type CellContent {
Content(symbol: String, width: Int)
Continuation
}
Constructors
-
Content(symbol: String, width: Int)A normal or wide grapheme.
width= 1 or 2. -
ContinuationMarker for the second cell of a wide grapheme. Never drawn directly.
A run of writes.
The JavaScript store has to copy the cell array to keep an old buffer intact, so writing a cell at a time makes filling a buffer quadratic in its size: a 200x50 fill cost about 35 ms, more than a whole 60 fps frame. A draft copies once and writes many times. Erlang’s array is a persistent trie already, so there a draft is the array itself.
A draft must not escape the loop that made it. Every use below takes one, writes, and commits within a single function.
pub type Draft
Values
pub fn blit(
dst: Buffer,
src: Buffer,
src_rect: geometry.Rect,
dst_pos: geometry.Position,
) -> Buffer
Copy src_rect out of src into dst, placing its top-left at dst_pos.
Clipped against both buffers; anything outside either is skipped.
Use to composite an off-screen buffer (a scroll canvas, a cached panel) into the frame without going cell by cell from the caller.
pub fn buffer_new(area: geometry.Rect) -> Buffer
New buffer with given area. All cells start as empty_cell().
pub fn buffer_new_filled(
area: geometry.Rect,
row_text: String,
s: style.Style,
) -> Buffer
Create a buffer with every row pre-filled with row_text.
Uses bulk array construction: one pass instead of buffer_new followed by
a set_string for every row.
pub fn cell_link(cell: Cell) -> String
Accessor: OSC 8 hyperlink URI of a cell (empty = no link).
pub fn cell_symbol(cell: Cell) -> String
Symbol string of a cell. Returns “ “ for Continuation cells.
pub fn cell_underline_color(cell: Cell) -> style.Color
Underline color of a cell.
pub fn clear(buffer: Buffer, rect: geometry.Rect) -> Buffer
Clear all cells in a rect (reset to empty_cell).
The rect is clipped to the buffer first, so the inner loop needs no
per-cell bounds check and the Buffer record is rebuilt once, not per cell.
pub fn continuation_cell(s: style.Style) -> Cell
Continuation cell (second column of a wide grapheme).
pub fn diff(prev: Buffer, next: Buffer) -> List(BufferOp)
Compute minimal diff between two buffers as a list of patches.
pub fn diff_to_ansi(prev: Buffer, curr: Buffer) -> String
Diff prev against curr and return the minimal ANSI to bring the
terminal from prev’s state to curr’s state.
On the first frame (or after resize) pass an empty buffer as prev.
pub fn get_cell(buffer: Buffer, pos: geometry.Position) -> Cell
Get cell at position. Returns empty_cell() for out-of-bounds.
pub fn is_continuation(cell: Cell) -> Bool
True if this cell is the second column of a wide grapheme (never rendered directly).
pub fn patches_to_ansi(ops: List(BufferOp)) -> String
Convert a list of BufferOp patches to an ANSI string.
Each patch moves the cursor once, then writes a run of cells.
Style is tracked across the entire patch list, cursor moves do not
reset terminal style, so we avoid redundant escape sequences.
Cheaper than to_ansi when only a small fraction of cells changed.
pub fn set_cell(
buffer: Buffer,
pos: geometry.Position,
cell: Cell,
) -> Buffer
Set cell at position. Out-of-bounds writes are ignored.
The cell’s style is resolved on the way in, like every other write path,
so a hand-built Cell cannot smuggle an unspent sub_modifier into the
grid and make an identical-looking cell compare unequal.
pub fn set_string(
buffer: Buffer,
pos: geometry.Position,
str: String,
s: style.Style,
) -> Buffer
Set cells from a string starting at pos. No hyperlink.
Wide graphemes (width=2) take one Cell + one Continuation cell.
pub fn set_string_linked(
buffer: Buffer,
pos: geometry.Position,
str: String,
s: style.Style,
link: String,
) -> Buffer
Set cells from a string with an OSC 8 hyperlink URI.
Pass "" for no link (same as set_string).
pub fn set_style(
buffer: Buffer,
rect: geometry.Rect,
s: style.Style,
) -> Buffer
Restyle every cell in rect, keeping its content.
Use to tint a region (selection highlight, disabled panel) after the
content has been drawn.
pub fn to_ansi(buf: Buffer) -> String
Full-buffer render to an ANSI string. Emits a MoveCursor for every row, then each cell with style transitions only when the style actually changes between adjacent cells. Use for the first frame or after a terminal resize.