Raxol.Terminal.Capabilities.ReplyScanner (Raxol Terminal v2.6.1)

Copy Markdown View Source

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 next scan/2 resumes 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

mode_value()

@type mode_value() :: integer() | nil

t()

@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
}

Functions

new()

@spec new() :: t()

Fresh scanner accumulator.

scan(chunk, acc)

@spec scan(binary(), t()) :: {t(), binary()}

Scans a raw input chunk, resuming from any parked partial reply.

Returns {acc, leak_free} where leak_free is safe to hand to the key-event parser.