Preserve palette index through CellBuffer so re-emitters can keep the outer terminals theme
Part 2 of the palette-preservation work — first half was on
PtyHandle.readCells (commit 6248390). That change landed fgIndex /
bgIndex on the PtyCell shape but pty-layout tracing showed the round
trip broke inside the CellBuffer pipeline: setCell -> Cell (in
types.ts) had no index fields, so writeAnsi / diff / fullRender
silently dropped the index and re-emitted as truecolor.
Now the buffer-side Cell carries fgIndex / bgIndex (required,
number | null) and the pipeline plumbs them through:
- writeAnsi captures the index on SGR 30-37 / 90-97 / 38;5;N /
48;5;N, and clears it on 38;2 / 48;2 truecolor and on SGR 0 / 39 /
49 resets.
- cellsEqual compares the index so diff re-emits correctly when only
the index changed (same flattened RGB, different palette slot).
- diff + fullRender use shared emitFg / emitBg helpers that prefer
indexed SGR when fgIndex is non-null (SGR 30-37 for 0-7, 90-97 for
8-15, 38;5;N for 16-255) and fall back to truecolor SGR 38;2 /
48;2 otherwise.
- ptyView rendering path forwards cell.fgIndex / bgIndex from the
upstream PtyCell, so embedded panes re-emitted by consumers like
pty-layout keep the outer terminal's theme for indexed cells while
still supporting truecolor for programs that emit it.
Required rather than optional on Cell — nothing outside this repo
constructs Cell objects in our tree, and strict typing keeps the few
internal construction sites (emptyCell, makeCell, writeAnsi, FPS
counter literal in app.ts) honest. pty-layout's one selection-
highlight construction site will need a trivial fgIndex/bgIndex: null
addition.