pub struct Span {
pub line: u16,
pub left: u16,
pub right: u16,
pub cells: Vec<Cell>,
pub combining: BTreeMap<usize, Vec<char>>,
pub links: BTreeMap<usize, NonZeroU32>,
pub ucolors: BTreeMap<usize, Color>,
}Expand description
A damaged column run on one line, with its cells.
combining and links map a span-relative column to what that cell carries —
combining clusters (#45) and hyperlinks (#46) live in per-row maps, so neither
rides the cell. Since v14 (#621) both are sparse wire groups of their own,
not indices in the cell record, which is what removed the u16 ceilings the
engine could legitimately exceed.
The two are deliberately not symmetric, and the asymmetry is measured rather than stylistic:
combiningholds the cluster inline.Term::framepushes one entry per combining cell with no interning, so an index bought nothing but a level of indirection and a table to count. Inlining is size-neutral (measured: −0.5% on a combining-heavy frame) and buys the deletion of both.linksholds a 1-based index intoFrame::link_table, because that table is interned (Term::frame’slink_remapships each referenced URI once). Inlining a URI at every linked cell was measured at +171…403% on link-dense frames, and all three references share one copy across cells — ghostty ref-counts its hyperlink set explicitly “so that a set of cells can share the same hyperlink without duplicating the data”, xterm.js keys cells to anOscLinkServiceid, alacritty holdsArc<HyperlinkInner>.
A column is present in either map iff its cell carries the matching bit — and,
as with ucolors below, that bit does not travel on the wire (the record
encodes cell.c() and encode_color(bg), which drop C_COMBINED and
LINK_PRESENT respectively). decode re-arms both from these maps’ own entries.
A Span built by hand for a test owes the same pairing.
Fields§
§line: u16§left: u16§right: u16§cells: Vec<Cell>§combining: BTreeMap<usize, Vec<char>>§links: BTreeMap<usize, NonZeroU32>§ucolors: BTreeMap<usize, Color>Underline colours (SGR 58, #520): span-relative column → the Color
reference the cell’s coloured underline draws in. Sparse — only cells that
carry a non-default underline colour appear (gated on the UNDERLINE
attribute at parse time). Unlike combining/links this is a colour
reference, not a side-table index, so it ships inline (no _table on the
Frame). Kept off the per-cell record so a plain-text frame pays nothing
(ADR-0020: no inert per-cell payload).
Like combining and links, a column here is present iff its cell carries
the matching bit (Cell::is_ucolored) — but that bit does not travel on
the wire (encode_color keeps only mode+value, and CellFlags holds no
presence bits), so decode re-arms it from this map’s own entries. A Span
built by hand for a test owes the same pairing: an entry here without
Cell::set_ucolored on the cell is a column the gated readers cannot see.
(#531)