Terminal

View Source

TermUI selects a backend, parses its input into TermUI.Event structs, and restores owned terminal state at shutdown.

Raw and TTY modes

RawTTY
Minimum OTP2826
Terminal modecharacter-at-a-timecooked; may buffer until Enter
Typical usestandalone Unix TUIIEx, remsh, constrained terminals
Runtime alternate screenyesyes
Runtime buffer strategydouble-buffered differentialtemporary full frame
Local mouse setupenabled except WSL/ConPTYnot enabled by runtime

With backend: :auto, a standalone runtime tries Raw and falls back to TTY. Inside IEx it selects TTY directly so the shell keeps terminal ownership.

TermUI.Runtime.run(root: MyApp)                # automatic
TermUI.Runtime.run(root: MyApp, backend: :raw)
TermUI.Runtime.run(root: MyApp, backend: :tty)

Forcing Raw fails if native Raw mode cannot be acquired. TTY calls can block in their dedicated input process while the render loop continues.

Alternate screen and cursor

The runtime enters the alternate screen for both local backends, hides the cursor, and restores both on normal shutdown. TermUI.Backend.TTY has a standalone alternate_screen: false default, but TermUI.Runtime explicitly passes true.

Direct TermUI.Terminal calls are Raw/local primitives and can conflict with a running runtime. Prefer runtime ownership. If you use them independently, pair every setup operation with cleanup:

{:ok, _state} = TermUI.Terminal.enable_raw_mode()
:ok = TermUI.Terminal.enter_alternate_screen()
:ok = TermUI.Terminal.hide_cursor()

# later
:ok = TermUI.Terminal.show_cursor()
:ok = TermUI.Terminal.leave_alternate_screen()
:ok = TermUI.Terminal.disable_raw_mode()

Use TermUI.ANSI to generate low-level clear or cursor-position sequences; TermUI.Terminal does not expose clear_screen/0 or set_cursor_position/2.

Mouse

Raw runtime setup requests all mouse reporting modes and parses SGR mouse input into 0-based %TermUI.Event.Mouse{x: column, y: row} coordinates. WSL/ConPTY mouse tracking is intentionally disabled because cleanup sequences are not reliable. TTY may parse mouse sequences if an external host emits them, but the runtime does not enable local TTY mouse reporting.

Always provide keyboard alternatives for mouse interactions.

Focus and paste

The input parser understands focus sequences and bracketed paste payloads, but the runtime does not automatically enable either terminal reporting mode in 1.0. TermUI.Focus and TermUI.Clipboard provide enable/disable sequences for custom terminal integrations. When enabled by the host:

def event_to_msg(%TermUI.Event.Focus{action: :gained}, _state),
  do: {:msg, :focused}

def event_to_msg(%TermUI.Event.Paste{content: text}, _state),
  do: {:msg, {:paste, text}}

Without bracketed-paste reporting, pasted bytes arrive as ordinary key input.

Size and resize

TermUI.Terminal.get_terminal_size/0 returns {:ok, {rows, cols}} for a local terminal. Runtime resize events use %TermUI.Event.Resize{width: cols, height: rows}.

OTP 26 TTY operation can query size, but its signal API does not expose SIGWINCH to application handlers. Automatic local resize therefore requires a newer OTP. Raw already requires OTP 28. An SSH host must forward channel window changes to the session runtime.

Capabilities and character sets

TermUI.Runtime.capabilities/0 exposes detected TTY color, Unicode, dimension, and terminal information. TermUI.App.supports?/1 provides convenience color and Unicode queries. Capability values describe detection, not a guarantee that the runtime enabled every reporting feature.

Runtime context selects Unicode/ASCII from detected capabilities; the application character_set setting is only the fallback when no runtime-managed value exists in 1.0. Use TermUI.CharacterSet helpers when drawing UI glyphs. Common widgets degrade to ASCII, but Braille visuals and a few specialized/legacy code paths have limitations documented in the widget compatibility guide. Color options range from monochrome through 16/256 colors and true color.

SSH

TermUI.Backend.SSH is an explicit custom backend for an OTP SSH channel device, not an automatic TTY fallback. Each connection gets independent runtime and buffer state. The channel host sends {:ssh_input, event} and {:ssh_resize, rows, cols} to that runtime.

Platform support

  • Linux and macOS Unix terminals are the supported local targets.
  • WSL uses Unix paths with mouse disabled; verify the specific deployment terminal.
  • Native Windows support is experimental. TermUI does not configure Win32 console modes or implement native Raw input and resize handling.

Cleanup

Runtime cleanup stops input first, shuts down the backend/buffers, restores the terminal and cursor, restores local logger output, and uses defensive local TTY/stty cleanup. Custom backends perform their own device cleanup. A root Elm terminate/2 callback is not invoked by the runtime.

Next: Commands.