TerminalInterface
The terminal surface a TUI loop talks to. The PHP analog of pi-tui's `Terminal` interface. A `RetainedTuiLoop` (or any other TUI runtime) writes to, reads from, and controls a terminal through this seam — so the same loop can drive a real STDIN/STDOUT terminal, an in-memory test terminal, or a remote PTY-backed terminal without the loop body branching on the concrete backend. Implementations are expected to be cheap to construct and to be driven explicitly via {@see start()} / {@see stop()} — no implicit I/O in the constructor. `columns()` / `rows()` reflect the current size and may change between calls when the terminal is resized; {@see start()}'s `$onResize` callback lets the loop react.
TerminalInterface::start()
abstract public function start(callable $onInput, callable $onResize): voidEnters raw mode (or whatever the backend needs) and begins delivering input bytes to `$onInput`. `$onResize` is called when the terminal's columns/rows change so the loop can re-layout.
Parameters
| Name | Type | Description |
|---|---|---|
| $onInput | callable(string): void | |
| $onResize | callable(): void |
TerminalInterface::stop()
abstract public function stop(): voidRestores the terminal to its pre-{@see start()} state (cooked mode, visible cursor, etc.). Safe to call after {@see start()} or when {@see start()} was never called.
TerminalInterface::write()
abstract public function write(string $data): voidWrites `$data` to the terminal output stream. The caller is responsible for framing; this method does no buffering.
Parameters
| Name | Type | Description |
|---|---|---|
| $data | string |
TerminalInterface::pollInput()
abstract public function pollInput(): stringAny input bytes waiting right now, or `''` when there are none. Never blocks. The contract carries BOTH input models on purpose. {@see self::start()} pushes bytes to its `$onInput` callback, which suits an event-driven host; a retained loop, which owns its own tick, needs to pull instead. Without this method a pulling loop has to reach past the contract to a concrete terminal's stream — which is exactly what kept the interactive loop untestable.
TerminalInterface::atEndOfInput()
abstract public function atEndOfInput(): boolWhether no further input will ever arrive. {@see self::pollInput()} returns `''` for "nothing waiting right now", which a loop that idles between ticks reads as "keep going". A loop whose exit condition is the end of its input needs to tell that apart from "the input is over" — and only the terminal knows which it is. A real terminal answers false for its whole life; one backed by a finite stream answers true once the stream is drained.
TerminalInterface::columns()
abstract public function columns(): intThe terminal's current width in columns.
TerminalInterface::rows()
abstract public function rows(): intThe terminal's current height in rows.
TerminalInterface::moveBy()
abstract public function moveBy(int $lines): voidMoves the cursor by the given number of lines, negative being upwards.
Parameters
| Name | Type | Description |
|---|---|---|
| $lines | int |
TerminalInterface::hideCursor()
abstract public function hideCursor(): voidHides the hardware cursor.
TerminalInterface::showCursor()
abstract public function showCursor(): voidShows the hardware cursor.
TerminalInterface::clearLine()
abstract public function clearLine(): voidClears the line the cursor is on.
TerminalInterface::clearFromCursor()
abstract public function clearFromCursor(): voidClears from the cursor to the end of the screen.
TerminalInterface::clearScreen()
abstract public function clearScreen(): voidClears the whole screen.
TerminalInterface::setTitle()
abstract public function setTitle(string $title): voidSets the terminal window title.
Parameters
| Name | Type | Description |
|---|---|---|
| $title | string |