Raxol. UI. Rendering. PaintAuthority behaviour
(Raxol v2.6.1)
View Source
The single seam both inline-render emit paths go through: the printed- history append path and the pinned-viewport repaint path.
One owner module, both paths go through it: this behaviour is the CONTRACT
that makes that true — implementations execute it against the real
terminal (IOAuthority, below); tests drive it against
Raxol.Harness.Test.CaptureAuthority, which records every emit as an
origin-tagged entry instead of writing bytes. Because the tag layer is a
property of the TEST double, not the behaviour, production callers pay
nothing for it.
Callback origins (mirrors Raxol.Harness.Test.CaptureAuthority.Emit.origin):
append_sealed/2—:seal, append at the region's bottom line.repaint_footer/2—:footer, repaint the pinned footer rows.keyframe_footer/2—:keyframe, Ctrl-L / resize footer redraw.with_cursor/3—:cursor, the save -> position -> emit -> restore bracket; the sole owner of cursor save/restore so the two paths never race.resize/3— policy-bearing: which of seal-time-only / soft-owned / live-region-only a resize follows is a terminal- compatibility decision (D-PA;docs/proposals/t0-verdict-schema.mdtracks the measurement matrix that resolves it). This behaviour does not pick a policy; implementers do.region_top/1— the current split pointH - N(number of rows in the scrolling history region; rows below it are the footer).
This module intentionally carries NO implementation logic — it is the
interface implementations build against and the test harness doubles. See
Raxol.Harness.Test.CaptureAuthority for the recording test double and
Raxol.Harness.Test.SealOracle for the assertions built on top of it.
Summary
Types
Which pinned region a with_cursor/3 bracket is positioning into.
Opaque authority state; each implementation defines its own shape.
Callbacks
Append sealed lines at the bottom of the scrolling history region.
Footer-only keyframe redraw (Ctrl-L recovery, resize). Never \e[2J.
Current footer boundary: row count of the scrolling history region (H - N).
Repaint some or all of the pinned footer (live tail + strip + composer).
Applies a resize. Policy-bearing per D-PA: what happens to already-sealed
history on resize is a terminal-compatibility decision this behaviour
stays agnostic to (docs/proposals/t0-verdict-schema.md tracks the
measurement matrix that resolves it). Implementations MUST emit their DECSTBM re-set
(one Dialect.region_set/2 per resize) through their own emit path, so
INV-5's "re-set exactly once as CSI 1;(h-N) r" is byte-assertable.
Runs fun under a save -> position-into-region -> ... -> restore cursor
bracket. The single owner of the save/restore protocol; both append_sealed
and repaint_footer paths must route cursor movement through this so saves
and restores never interleave across paths.
Types
@type cursor_region() :: :history | :footer
Which pinned region a with_cursor/3 bracket is positioning into.
@type t() :: term()
Opaque authority state; each implementation defines its own shape.
Callbacks
Append sealed lines at the bottom of the scrolling history region.
@callback region_top(t()) :: pos_integer()
Current footer boundary: row count of the scrolling history region (H - N).
@callback resize(t(), width :: pos_integer(), height :: pos_integer()) :: t()
Applies a resize. Policy-bearing per D-PA: what happens to already-sealed
history on resize is a terminal-compatibility decision this behaviour
stays agnostic to (docs/proposals/t0-verdict-schema.md tracks the
measurement matrix that resolves it). Implementations MUST emit their DECSTBM re-set
(one Dialect.region_set/2 per resize) through their own emit path, so
INV-5's "re-set exactly once as CSI 1;(h-N) r" is byte-assertable.
@callback with_cursor(t(), cursor_region(), (t() -> t())) :: t()
Runs fun under a save -> position-into-region -> ... -> restore cursor
bracket. The single owner of the save/restore protocol; both append_sealed
and repaint_footer paths must route cursor movement through this so saves
and restores never interleave across paths.