Pure reply scanner: raw input chunk in, {parsed_replies_acc, leak_free_residual} out (test-suite design 04 §1a).
Generalizes Raxol.Terminal.Driver.BackgroundQuery.scan/1 to all F0 §3
reply framings. Replies are classified by grammar and echoed
parameters (?2026 in CSI ? 2026 ; 1 $ y), never by position.
Invariants (pinned by the CAP-F fuzz suite):
- Conservation -- every input byte is either consumed as a
recognized reply/control frame or returned in
leak_free, in the original order. User keystrokes are never eaten; reply bytes never leak to the key parser. - Both terminators -- OSC/DCS/APC close on BEL (
0x07) or ST (ESC \). - Chunk-split invariance -- a chunk ending mid-reply parks the
fragment in
partial; the nextscan/2resumes byte-identically.
The scanner is a pure function; it has no process, no clock, and no
side effects. The driver-facing shim (BackgroundQuery) and the probe
reducer (Probe) compose it.
Summary
Functions
Fresh scanner accumulator.
Scans a raw input chunk, resuming from any parked partial reply.
Types
@type mode_value() :: integer() | nil
@type t() :: %Raxol.Terminal.Capabilities.ReplyScanner{ cell_px: {pos_integer(), pos_integer()} | nil, cpr: {pos_integer(), pos_integer()} | nil, da1: [non_neg_integer()] | nil, da2: [non_neg_integer()] | nil, kitty_graphics: boolean() | nil, kitty_kbd: non_neg_integer() | nil, mode: %{optional(non_neg_integer()) => mode_value()}, osc10: {:ok, Raxol.Terminal.Driver.BackgroundQuery.rgb()} | {:invalid, binary()} | nil, osc11: {:ok, Raxol.Terminal.Driver.BackgroundQuery.rgb()} | {:invalid, binary()} | nil, partial: binary(), sentinel_seen?: boolean(), sixel_regs: non_neg_integer() | nil, xtgettcap: %{optional(String.t()) => String.t() | true}, xtversion: {String.t(), String.t() | nil} | nil, xtversion_raw: String.t() | nil }