arizona_terminal_default_driver (arizona v0.4.0)

View Source

The framework's default arizona_terminal_driver implementation -- a sensible terminal experience any ?terminal app gets for free.

arizona_terminal_session falls back to these for any callback a driver doesn't implement, so a custom driver overrides only what it changes; passing this module itself as the driver uses all the defaults.

The defaults:

  • keys/2 translates the read with arizona_terminal_io:keys/1 (printable -> $a, named keys -> atoms, {ctrl, _} / {alt, _}). Ctrl-D (EOF) quits -- the one always-available escape, so any app is quittable. Every other key, Ctrl-C included, becomes a ~"key" event carrying the idiomatic key value, so a view matches handle_event(~"key", #{key := $j}, B), #{key := up}, #{key := {ctrl, $c}}, etc. An app decides what Ctrl-C does (cancel, confirm-quit, ...) by handling that event; nothing happens by default.
  • setup/1 hides the cursor for the session; teardown/1 restores it on quit.
  • paint/3 repaints the frame in place (cursor home, clear-to-end-of-line per line, then clear below) so it does not flicker, and interprets the framework terminal effects (arizona_terminal_effect): quit stops the session, set_title sets the terminal title, bell rings it. Unknown effects are ignored.

Frame must fit the terminal

The in-place repaint homes with \e[H (absolute top-left) and writes every line, so it assumes the frame fits within the terminal's visible rows. A frame taller than the window scrolls on each paint: \e[H no longer addresses the true top and each repaint appends another screenful to the scrollback (a continuous flood under the periodic tick). Clamping to the visible rows would need the terminal geometry, which this default driver is not given (the SSH transport knows it, but a local TTY cannot read its own size). Keep a ?terminal view's rendered height within the smallest terminal you target, or supply a custom driver that clamps against a size it tracks.

Summary

Functions

The default driver is stateless; its state is an empty map.

Translate the read and turn keys into events; Ctrl-D (EOF) quits. An escape sequence split across reads (a transport delivers bytes in chunks) would otherwise mis-decode -- a trailing \\e[ dropped, the next read's A surfacing as a spurious $a. So the incomplete trailing escape prefix is buffered in the driver state (pending) and prepended to the next read.

Repaint the frame in place and interpret framework terminal effects: a quit effect stops the session; set_title / bell emit their escape sequences; unknown effects are ignored. Repaints with home + per-line clear-to-EOL + clear-below rather than a \\e[2J full clear, so the screen does not flicker.

Hide the cursor for the session.

Restore the cursor on quit.

Functions

init(Arg)

-spec init(term()) -> map().

The default driver is stateless; its state is an empty map.

keys(Bytes, State)

-spec keys(binary(), State) -> {[arizona_terminal_driver:command()], State}.

Translate the read and turn keys into events; Ctrl-D (EOF) quits. An escape sequence split across reads (a transport delivers bytes in chunks) would otherwise mis-decode -- a trailing \\e[ dropped, the next read's A surfacing as a spurious $a. So the incomplete trailing escape prefix is buffered in the driver state (pending) and prepended to the next read.

paint(Frame, Effects, State)

-spec paint(binary(), [arizona_effect:cmd()], State) -> {iodata(), continue | stop, State}.

Repaint the frame in place and interpret framework terminal effects: a quit effect stops the session; set_title / bell emit their escape sequences; unknown effects are ignored. Repaints with home + per-line clear-to-EOL + clear-below rather than a \\e[2J full clear, so the screen does not flicker.

setup(State)

-spec setup(State) -> {iodata(), State}.

Hide the cursor for the session.

teardown(State)

-spec teardown(term()) -> iodata().

Restore the cursor on quit.