Atui.Terminal (Atui v0.1.0)

Copy Markdown View Source

Terminal setup, teardown and the handful of ANSI sequences the runtime needs.

Getting keys one at a time

Putting the terminal in raw mode is not enough. When the BEAM finds a usable terminal it starts its own line editor (prim_tty), which reads stdin, echoes what you type and hands the reader a whole line once you press Enter — no matter what stty says. So raw mode is asked for the way OTP intends: :shell.start_interactive({:noshell, :raw}), which switches that driver into raw mode and delivers each character as it is typed.

That path needs a VM started with -noshell, which is how mix run and release start scripts run. Where it is not available — inside IEx, or on OTP older than 26.2 — we fall back to stty against /dev/tty, which is enough when the BEAM has not claimed the terminal (no TERM, output redirected).

Ctrl-C

In raw mode prim_tty still treats byte 3 as the emulator break, popping the BREAK menu over the UI. The VM flag +Bc makes it a normal byte instead, so the runtime can act on it. Pass it however the application starts:

elixir --erl "+Bc" -S mix run --no-halt
ELIXIR_ERL_OPTIONS="+Bc" mix run --no-halt

In a release, put +Bc on a line of its own in rel/vm.args.eex.

Summary

Functions

Draws a frame, homing the cursor first so rows land where they belong.

Switches to the alternate screen buffer and hides the cursor.

Shows the cursor and returns to the normal screen buffer.

Puts the terminal into raw mode with echo off.

Restores a stty state captured by raw_mode/0.

The terminal size as {columns, rows}, falling back to 80x24.

Functions

draw(iodata)

Draws a frame, homing the cursor first so rows land where they belong.

enter()

Switches to the alternate screen buffer and hides the cursor.

leave()

Shows the cursor and returns to the normal screen buffer.

raw_mode()

Puts the terminal into raw mode with echo off.

Returns {:ok, saved} where saved is the previous stty state to hand back to restore/1 (nil if there was no terminal to ask), or :error if raw mode could not be established at all — tests and CI, where the runtime falls back to rendering blind.

restore(saved)

Restores a stty state captured by raw_mode/0.

size()

The terminal size as {columns, rows}, falling back to 80x24.