A frame for a terminal: text with ANSI colour escapes.
Coloured frames take each cell's palette colour, as 24-bit colour
(:truecolor, the default), the nearest of xterm's 256 (:ansi256), or
none at all (:mono). Escapes are emitted once a run of one colour, and
spaces never start a run, so a frame costs little more than its text. A
piece with a ground gets it as the background, unless ground: false.
Each line ends by resetting the colours, so nothing bleeds past the
picture.
Frames without colours (text pieces, or color: false) are plain text in
every mode, in the terminal's own colours. A nil in a palette (cells in
no coloured part of a piece, see Ascii.Parts) is the terminal's own
foreground too, and a CSS variable (see Ascii.Ink) is its fallback
colour, or the terminal's own without one.
To animate in place, move the cursor home before each frame:
IO.write([ANSI.hide_cursor(), ANSI.clear()])
IO.write([ANSI.home(), ANSI.render(frame)])
# ...
IO.write([ANSI.reset(), ANSI.show_cursor()])Ascii.Player and mix ascii.play do this for you.
Summary
Functions
What changed from prev to frame, as iodata that moves the cursor to
each run of cells that changed and writes it (see
Ascii.Frame.changes/3); nothing at all when the picture did not
change. With prev nil, the whole frame, each row placed.
Clears the screen.
Hides the cursor.
Moves the cursor to the top left.
Moves the cursor to row, column, counting from 1.
The frame as iodata.
Resets colours.
Shows the cursor.
The xterm-256 colour nearest an RGB colour: a step of the 6×6×6 cube or of the grey ramp.
Types
Functions
@spec changes( prev :: Ascii.Frame.t() | nil, frame :: Ascii.Frame.t(), opts :: [mode: mode(), ground: boolean(), at: {pos_integer(), pos_integer()}] ) :: iodata()
What changed from prev to frame, as iodata that moves the cursor to
each run of cells that changed and writes it (see
Ascii.Frame.changes/3); nothing at all when the picture did not
change. With prev nil, the whole frame, each row placed.
A terminal that already shows prev needs only this, which for most
pieces is a few cells in a hundred: over SSH or a serial console, far less
to send than render/2 every frame.
Options
:mode,:ground- as forrender/2.:at-{row, column}of the screen where the frame's top left cell is, counting from 1 (default{1, 1}).
@spec clear() :: String.t()
Clears the screen.
@spec hide_cursor() :: String.t()
Hides the cursor.
@spec home() :: String.t()
Moves the cursor to the top left.
@spec move(row :: pos_integer(), column :: pos_integer()) :: String.t()
Moves the cursor to row, column, counting from 1.
@spec render(frame :: Ascii.Frame.t(), opts :: [mode: mode(), ground: boolean()]) :: iodata()
The frame as iodata.
Options
:mode-:truecolor(default),:ansi256or:mono.:ground- paint the piece's ground behind it (defaulttrue).
@spec reset() :: String.t()
Resets colours.
@spec show_cursor() :: String.t()
Shows the cursor.
The xterm-256 colour nearest an RGB colour: a step of the 6×6×6 cube or of the grey ramp.