Phosphor::Backend
Abstraction layer between the renderer and the actual output target — a live ANSI terminal, or a substitute (in-memory test double, a file, a network transport).
Terminal is the real-terminal Backend: it already implements all
five behaviors below, just not yet expressed as a Backend subclass
— that refactor is a later phase (see TASKS.md § "Phase 27: Pluggable
backends"). This class defines the contract only; nothing in the
framework constructs or depends on a Backend instance yet.
The motivation isn't multi-platform support — it's testability. A
TestBackend (a later phase) lets the integration test suite drive
App#run without a real PTY: faster, deterministic, and able to
assert directly on what was rendered.
See TASKS.md § "Phase 27: Pluggable backends" for the full rationale.
Instance methods
Prepares the output target for rendering.
For a real terminal: enter raw mode, switch to the alternate screen
buffer, hide the cursor, and enable mouse tracking if mouse is
true (bracketed paste is enabled unconditionally either way). A
non-terminal backend performs whatever equivalent setup it needs (or
nothing, if none applies) and may ignore mouse entirely.
Restores the output target to its pre-session state — the exact
inverse of #enter.
For a real terminal: restore the saved termios settings, leave the alternate screen buffer, show the cursor again.
Non-blocking read of the next input event from the output target,
or nil if none is available right now.
Called from within a Port's own poll loop, never directly by
App#run — this must not block, the same contract every Port#poll
implementation already follows (see .claude/rules/async.md).
Returns the output target's current {width, height}.
Called on every render to size the frame being drawn into — must never cache: callers expect the live value, so a resized terminal (or an equivalent change in a non-terminal backend) is picked up on the very next call with no special-case handling anywhere else.
Writes a set of changed cells to the output target.
diff carries each changed cell's absolute position and new Cell
value (see Buffer#diff). The backend is responsible for
translating Cell/Style into whatever the output target actually
accepts — ANSI escape sequences for a real terminal, raw cell data
for a test backend.