MingaEditor.DisplayList (Minga v0.1.0)

Copy Markdown View Source

BEAM-side display list: a styled text run intermediate representation.

Sits between editor state and protocol encoding. The renderer produces a Frame struct containing all visual content, then to_commands/1 converts it to protocol command binaries for the TUI frontend. Other frontends (GUI, headless) can consume the frame directly.

Coordinate system

All coordinates within a WindowFrame are window-relative: row 0, col 0 is the top-left of the window's content rect. The rect field carries the absolute screen position; to_commands/1 adds the rect offset when generating protocol commands.

Other frame sections (file_tree, agent_panel, minibuffer, overlays) use absolute screen coordinates since they're not scoped to a window.

Types

  • draw() — a pending draw: {row, col, text, style}. This is the return type of all renderer modules after the display list refactor.
  • text_run() — column + text + style (no row; row is the map key).
  • display_line() — a list of text runs for one screen row.
  • render_layer() — rows mapped to their display lines.

Summary

Types

RGB color as a 24-bit integer (e.g. 0xFF6C6B).

All text runs on one screen row.

A pending draw command: {row, col, text, Face.t()}.

Screen rows mapped to their display lines.

Style: a resolved Face struct.

A single styled text span at a specific column.

Functions

Compares two render layers line-by-line and returns the set of changed rows.

Creates a draw tuple with a Face style.

Converts a list of draw tuples to protocol command binaries.

Groups a list of draws by row into a render layer.

Converts draw tuples to grayscale (luminance-weighted).

Flattens a render layer back into a list of draw tuples.

Offsets draw tuples by the given row and column amounts.

Converts a frame into a list of protocol command binaries.

Types

color()

@type color() :: non_neg_integer()

RGB color as a 24-bit integer (e.g. 0xFF6C6B).

display_line()

@type display_line() :: [text_run()]

All text runs on one screen row.

draw()

A pending draw command: {row, col, text, Face.t()}.

This is the intermediate representation that renderer modules produce.

render_layer()

@type render_layer() :: %{required(non_neg_integer()) => display_line()}

Screen rows mapped to their display lines.

style()

@type style() :: Minga.Core.Face.t()

Style: a resolved Face struct.

text_run()

@type text_run() ::
  {col :: non_neg_integer(), text :: String.t(), style :: Minga.Core.Face.t()}

A single styled text span at a specific column.

Functions

changed_rows(old_layer, new_layer)

@spec changed_rows(render_layer(), render_layer()) :: MapSet.t(non_neg_integer())

Compares two render layers line-by-line and returns the set of changed rows.

This enables incremental rendering: only rows that differ between frames need to be re-sent to the frontend.

draw(row, col, text, face \\ Face.new())

Creates a draw tuple with a Face style.

Examples

iex> DisplayList.draw(0, 5, "hello")
{0, 5, "hello", %Face{name: "_"}}

iex> DisplayList.draw(0, 5, "hello", Face.new(fg: 0xFF0000, bold: true))
{0, 5, "hello", %Face{name: "_", fg: 0xFF0000, bold: true}}

draws_to_commands(draws)

@spec draws_to_commands([draw()]) :: [binary()]

Converts a list of draw tuples to protocol command binaries.

Uses encode_draw_smart/4 which automatically selects the compact draw_text opcode for simple styles (fg/bg/bold/italic/underline/reverse) or the extended draw_styled_text opcode when the style includes strikethrough, underline_style, underline_color, or blend.

draws_to_layer(draws)

@spec draws_to_layer([draw()]) :: render_layer()

Groups a list of draws by row into a render layer.

Each draw's row becomes the map key; the draw is converted to a text_run (col, text, style) within that row's display_line.

grayscale_draws(draws)

@spec grayscale_draws([draw()]) :: [draw()]

Converts draw tuples to grayscale (luminance-weighted).

layer_to_draws(layer)

@spec layer_to_draws(render_layer()) :: [draw()]

Flattens a render layer back into a list of draw tuples.

offset_draws(draws, row_off, col_off)

@spec offset_draws([draw()], non_neg_integer(), non_neg_integer()) :: [draw()]

Offsets draw tuples by the given row and column amounts.

to_commands(frame, opts \\ [])

@spec to_commands(
  MingaEditor.DisplayList.Frame.t(),
  keyword()
) :: [binary()]

Converts a frame into a list of protocol command binaries.

Produces the same output that the old renderer sent to the port: clear, regions, content draws, cursor, batch_end.

Options:

  • batch_end: false — omit the trailing batch_end command. Used by the GUI emit path which appends Metal-critical chrome commands before sending batch_end to ensure atomic frame delivery.