TermUI.Renderer.SequenceBuffer (TermUI v0.2.0)

View Source

Batches escape sequences for efficient terminal output.

Accumulates escape sequences and text in an iolist, then flushes to output when threshold is reached or frame completes. This reduces system call overhead and ensures atomic frame updates.

Features

  • Iolist accumulator - Efficient append without copying
  • Size threshold - Auto-flush when buffer exceeds limit
  • SGR combining - Merges adjacent style sequences
  • Statistics - Tracks bytes written and flush count

Usage

buffer = SequenceBuffer.new()
buffer = SequenceBuffer.append(buffer, "\e[1;31m")
buffer = SequenceBuffer.append(buffer, "Hello")
{data, buffer} = SequenceBuffer.flush(buffer)
IO.binwrite(data)

SGR Combining

Adjacent SGR sequences are combined into a single sequence:

# Instead of: ESC[1m ESC[31m ESC[4m
# Produces:   ESC[1;31;4m

This reduces output bytes and terminal parsing overhead.

Summary

Functions

Appends multiple SGR parameters to be combined into a single sequence.

Appends data to the buffer.

Appends data to the buffer, ignoring auto-flush result.

Appends a style, emitting SGR sequence with delta from last style.

Clears the buffer without flushing.

Emits any pending SGR parameters as a combined sequence.

Returns whether the buffer is empty.

Flushes the buffer, returning accumulated data and resetting.

Creates a new sequence buffer with default threshold (4KB).

Creates a new sequence buffer with specified threshold.

Resets the style tracking, useful when style is explicitly reset.

Returns the current buffer size in bytes.

Returns buffer statistics.

Returns the current buffer contents as iodata without flushing.

Types

t()

@type t() :: %TermUI.Renderer.SequenceBuffer{
  buffer: iolist(),
  flush_count: non_neg_integer(),
  last_style: TermUI.Renderer.Style.t() | nil,
  pending_sgr: [String.t()],
  size: non_neg_integer(),
  threshold: pos_integer(),
  total_bytes: non_neg_integer()
}

Functions

add_sgr_param(buffer, param)

@spec add_sgr_param(t(), String.t()) :: t()

Appends multiple SGR parameters to be combined into a single sequence.

Call emit_pending_sgr/1 to output the combined sequence.

append(buffer, data)

@spec append(t(), iodata()) :: {:ok, t()} | {:flush, iodata(), t()}

Appends data to the buffer.

Returns {:ok, buffer} normally, or {:flush, data, buffer} if the threshold was exceeded and an auto-flush occurred.

append!(buffer, data)

@spec append!(t(), iodata()) :: t()

Appends data to the buffer, ignoring auto-flush result.

Simpler API when you don't need to handle auto-flush immediately.

append_style(buffer, style)

@spec append_style(t(), TermUI.Renderer.Style.t()) :: t()

Appends a style, emitting SGR sequence with delta from last style.

Only emits parameters that changed from the previous style.

clear(buffer)

@spec clear(t()) :: t()

Clears the buffer without flushing.

emit_pending_sgr(buffer)

@spec emit_pending_sgr(t()) :: t()

Emits any pending SGR parameters as a combined sequence.

empty?(sequence_buffer)

@spec empty?(t()) :: boolean()

Returns whether the buffer is empty.

flush(buffer)

@spec flush(t()) :: {iodata(), t()}

Flushes the buffer, returning accumulated data and resetting.

Returns {iodata, new_buffer}.

new()

@spec new() :: t()

Creates a new sequence buffer with default threshold (4KB).

new(opts)

@spec new(keyword()) :: t()

Creates a new sequence buffer with specified threshold.

Options

  • :threshold - Flush threshold in bytes (default: 4096)

reset_style(buffer)

@spec reset_style(t()) :: t()

Resets the style tracking, useful when style is explicitly reset.

size(sequence_buffer)

@spec size(t()) :: non_neg_integer()

Returns the current buffer size in bytes.

stats(sequence_buffer)

@spec stats(t()) :: {non_neg_integer(), non_neg_integer()}

Returns buffer statistics.

Returns {total_bytes, flush_count}.

to_iodata(sequence_buffer)

@spec to_iodata(t()) :: iodata()

Returns the current buffer contents as iodata without flushing.