Handles writing characters and strings to the Raxol.Terminal.ScreenBuffer. Responsible for character width, bidirectional text segmentation, and cell creation.
Summary
Types
One bulk write: {x, y, char, style} with the same per-cell semantics
as write_char/5.
Functions
Creates a cell style by merging the provided style with default formatting.
Bulk-writes a list of cells into the buffer in one pass per touched row.
Logs character write operations for debugging purposes.
Updates cells in the buffer at the specified position.
Updates a row in the buffer at the specified position.
Writes a character to the buffer at the specified position. Handles wide characters by taking up two cells when necessary. Accepts an optional style to apply to the cell.
Writes a segment of text to the buffer.
Writes a string to the buffer at the specified position. Handles wide characters and bidirectional text.
Types
@type cell_write() :: {non_neg_integer(), non_neg_integer(), String.t() | nil, Raxol.Terminal.ANSI.TextFormatting.text_style() | map() | nil}
One bulk write: {x, y, char, style} with the same per-cell semantics
as write_char/5.
Functions
@spec create_cell_style(Raxol.Terminal.ANSI.TextFormatting.text_style() | nil) :: Raxol.Terminal.ANSI.TextFormatting.t()
Creates a cell style by merging the provided style with default formatting.
Parameters
style- The style to merge with default formatting, or nil for default style
Returns
A map containing the merged text formatting style.
Examples
iex> Writer.create_cell_style(%{fg: :red})
%{fg: :red, bg: :default, bold: false, ...}
@spec fill_cells( Raxol.Terminal.ScreenBuffer.t() | map(), [cell_write()], (Raxol.Terminal.ANSI.TextFormatting.text_style() | map() | nil, Raxol.Terminal.Cell.t() -> Raxol.Terminal.ANSI.TextFormatting.text_style() | map() | nil) | nil ) :: Raxol.Terminal.ScreenBuffer.t() | map()
Bulk-writes a list of cells into the buffer in one pass per touched row.
cells are applied IN LIST ORDER and the result is exactly the buffer
that folding write_char/5 over the list produces -- overwrites,
wide-char placeholders, and bounds handling included -- at O(row)
instead of O(cells x row) cost. Rows the list does not touch keep
their original cell terms.
style_resolver (optional) is invoked per in-bounds write with the
cell's raw style and the cell currently at the target position --
including cells written earlier in the same batch, matching the
sequential fold where every write sees the buffer its predecessors
built. Its return value is the style used for the write. Out-of-bounds
writes are skipped without consulting the resolver (the sequential
fold resolved and then discarded; resolution is pure, so skipping is
unobservable).
Two per-cell allocation sources of the sequential fold are shared
here: cells with equal resolved styles share one merged style term
(create_cell_style/1 runs once per distinct style), and character
widths are memoized per distinct character.
@spec log_char_write( String.t(), non_neg_integer(), non_neg_integer(), Raxol.Terminal.ANSI.TextFormatting.text_style() ) :: :ok
Logs character write operations for debugging purposes.
Parameters
char- The character being writtenx- The x-coordinate where the character is being writteny- The y-coordinate where the character is being writtencell_style- The style being applied to the cell
Returns
:ok
Examples
iex> Writer.log_char_write("A", 0, 0, %{fg: :red})
:ok
@spec update_cells( Raxol.Terminal.ScreenBuffer.t() | map(), non_neg_integer(), non_neg_integer(), String.t(), Raxol.Terminal.ANSI.TextFormatting.text_style(), 1..2 ) :: [[Raxol.Terminal.Cell.t()]]
Updates cells in the buffer at the specified position.
Parameters
buffer- The screen buffer to updatex- The x-coordinate to updatey- The y-coordinate to updatechar- The character to writecell_style- The style to applywidth- The width of the character (1 or 2 for wide characters)
Returns
The updated list of cells.
Examples
iex> buffer = ScreenBuffer.new(80, 24)
iex> Writer.update_cells(buffer, 0, 0, "A", %{fg: :red}, 1)
[%Cell{char: "A", style: %{fg: :red}}, ...]
@spec update_row( [Raxol.Terminal.Cell.t()], non_neg_integer(), String.t(), Raxol.Terminal.ANSI.TextFormatting.text_style(), 1..2, non_neg_integer() ) :: [Raxol.Terminal.Cell.t()]
Updates a row in the buffer at the specified position.
Parameters
row- The row to updatex- The x-coordinate to updatechar- The character to writecell_style- The style to applywidth- The width of the character (1 or 2 for wide characters)buffer_width- The total width of the buffer
Returns
The updated row of cells.
Examples
iex> row = List.duplicate(Cell.new(), 80)
iex> Writer.update_row(row, 0, "A", %{fg: :red}, 1, 80)
[%Cell{char: "A", style: %{fg: :red}}, ...]
@spec write_char( Raxol.Terminal.ScreenBuffer.t() | map(), non_neg_integer(), non_neg_integer(), String.t(), Raxol.Terminal.ANSI.TextFormatting.text_style() | nil ) :: Raxol.Terminal.ScreenBuffer.t() | map()
Writes a character to the buffer at the specified position. Handles wide characters by taking up two cells when necessary. Accepts an optional style to apply to the cell.
@spec write_segment( Raxol.Terminal.ScreenBuffer.t() | map(), non_neg_integer(), non_neg_integer(), String.t(), Raxol.Terminal.ANSI.TextFormatting.text_style() | nil ) :: {Raxol.Terminal.ScreenBuffer.t() | map(), non_neg_integer()}
Writes a segment of text to the buffer.
Parameters
buffer- The screen buffer to write tox- The x-coordinate to start writing aty- The y-coordinate to write atsegment- The text segment to write
Returns
A tuple containing the updated buffer and the new x-coordinate.
Examples
iex> buffer = ScreenBuffer.new(80, 24)
iex> {new_buffer, new_x} = Writer.write_segment(buffer, 0, 0, "Hello")
iex> new_x
5
@spec write_string( Raxol.Terminal.ScreenBuffer.t() | map(), non_neg_integer(), non_neg_integer(), String.t(), Raxol.Terminal.ANSI.TextFormatting.text_style() | nil ) :: Raxol.Terminal.ScreenBuffer.t() | map()
Writes a string to the buffer at the specified position. Handles wide characters and bidirectional text.