Guide
The terminal contract
What the runner does to the terminal, and how each way that a run ends restores it.
CounterKyoApp.scala
object CounterKyoApp extends KyoApp:
run(Tui.run(quit => Counter.ui(quit)))
Tui.run runs a UI in the real terminal until the UI calls its quit action. A TuiApp calls it for you.
What the run changes
| When | What the runner does |
|---|---|
| Before the start | It checks that stdin is a terminal (else TuiError.NotATerminal) and that the native library loads (else TuiError.NativeLoadFailed or NativeAccessDenied). The terminal does not change before these checks. |
| At the start | It enters raw mode and the alternate screen, hides the cursor, turns on bracketed paste, and captures the output of the JVM. |
| While it runs | One input thread reads the keys, the pastes and the resizes. One fiber draws. A frame sends only the cells that changed. The cursor shows the caret of the focused text input. |
| At the end | It stops the drawing, stops the input thread, leaves the alternate screen, shows the cursor, ends raw mode, and then prints the captured output. |
Each way that a run ends
The release is one stack of steps that runs once, the last acquire first. A failing step does not stop the next steps.
| The run ends by | The terminal |
|---|---|
Tui.quit, or the key Ctrl-C | Restored. Exit code 0 in a TuiApp. |
| A failure of the UI | Restored. The failure is printed after the restore. |
| An interrupt of the caller | Restored at once. |
kill -TERM, kill -INT, kill -HUP, System.exit | The shutdown hook restores it, and waits at most 2 s. |
After a quit, Tui.run closes the Scope of the UI before the release: the fibers that the UI started stop first. A fiber that does not stop on an interrupt (a blocking call in Sync.defer) keeps the terminal in raw mode until it ends.
Limits
- No mouse input.
- A typed emoji arrives wrong (jatatui 0.31.0 cuts it to 16 bits). A paste keeps it.
- CI checks the terminal path on Linux only. Windows is experimental.
The PTY kit checks this contract: raw mode while the app runs, the same stty -a before and after each run, the exit codes, and the signals.