Tela.Renderer (tela v0.1.0)

Copy Markdown View Source

Produces minimal ANSI output to update the terminal from one frame to the next.

The renderer compares the previous frame's lines against the next frame's lines and emits ANSI escape sequences only for lines that have changed. This avoids full-screen redraws on every update, preventing flicker.

Usage

prev = ["Hello", "World"]
next = ["Hello", "Tela"]

iodata = Tela.Renderer.diff(prev, next)
:io.put_chars(:user, iodata)

On the first render, pass an empty list as prev to clear the screen and write all lines.

iodata = Tela.Renderer.diff([], ["Hello", "Tela"])

Cursor parking

After every render the cursor is moved to the row immediately below the last line of the frame. This keeps the cursor out of the visible UI area.

ANSI sequences used

SequenceMeaning
\e[2JClear entire screen
\e[HMove cursor to top-left (home)
\e[R;CHMove cursor to row R, column C
\e[KClear from cursor to end of line

Summary

Functions

Produces iodata to update the terminal from prev_lines to next_lines.

Functions

diff(prev_lines, next_lines)

@spec diff(prev_lines :: [String.t()], next_lines :: [String.t()]) :: iodata()

Produces iodata to update the terminal from prev_lines to next_lines.

Compares each line by index. For lines that differ, emits a cursor-move sequence followed by the new content and an end-of-line clear. Lines that are identical produce no output.

When prev_lines is empty, performs a full clear (\e[2J\e[H) before writing all lines.

After writing, the cursor is parked one row below the last line.

Examples

iex> Tela.Renderer.diff([], ["Hello"]) |> IO.iodata_to_binary()
"\e[2J\e[H\e[1;1HHello\e[K\e[2;1H"

iex> Tela.Renderer.diff(["Hello"], ["Hello"]) |> IO.iodata_to_binary()
""