- Print the missing exit-repaint after the inline editor's
__cs_dispatch_draw call (was silently changed to capture-only earlier
in the branch; this call site was missed, blanking the panel on
commit/cancel of an inline edit).
- Hoist (count $prev_edit_frame) out of a quoted math string in the
inline editor's per-keystroke redraw -- fish doesn't expand a command
substitution there, so math silently errored.
- Add a >= 52 column floor to both diff-path guards: below the
narrowest tier's own 52-column box width, lines wrap and the diff
path's one-physical-row-per-logical-line walk corrupts the display.
- Reword a stale test comment that described panel_h as mirroring a
hand-set constant in __cs_dispatch_draw; it derives panel_h from real
output now.
- Declare prev_edit_frame with -l alongside edit_frame instead of a
bare set, matching the file's convention.
- Move prev_frame's declaration to its point of use instead of an
empty top-level placeholder, matching old_h in the same block.
A byte-identity gate CI never runs will rot, and a rotted gate is worse
than no gate. Adds the render harness as Phase 4, in the same shape as the
vault suite: its own process, its own sandbox, no loaded config needed.
Kept to one self-contained block so it can be dropped or re-applied by
hand if the runner is restructured. The functional suite's 317/317 count
is untouched; the render cases report separately.
Width tier, title border, boolean badge, cursor cell and row line now come
from __config_settings_frame. The type badges (PATH/INT/LIST/STR) stay
here -- they are this page's own vocabulary, used nowhere else -- and so
does the STR default arm, which covers a user-settable value rather than
being dead code.
Introduces the `shorten` fit policy: these fields hold arbitrary user
values and want an ellipsis, unlike the toggle page's per-tier text. The
inline editor keeps `pad`, because its field is already length-constrained
and carries a reverse-video caret whose escapes string shorten miscounts.
The panel stays exactly 16 lines -- chrome(6) + nrows + blanks -- so
config-settings.fish's panel_h and its erase are untouched.
Rendering unchanged: 377/377 render cases byte-identical, golden untouched.
Code lines 123 -> 98 (-25).
Width tier, title border, badge, cursor cell and row line now come from
__config_settings_frame, and the hand-verified title dash count
(iw - L - S - 22) is derived from the segment's visible width instead.
Introduces the `cut` fit policy, which is this page's documented
divergence from the category list: its labels and descriptions are static
data from __config_settings_subcats rather than per-tier authored text,
and several exceed the narrower tiers' fields. `string pad` only ever
grows a string, so they are truncated before padding. That reason now
lives in two places -- the frame's NOTES and each call site -- and the
DESCRIPTION block stating it here is unchanged.
Drops label_w and desc_w, both left assigned and never read once the
frame derives the field width; the comment recording the 13-wide label
field and how the description field absorbs it stays.
Rendering unchanged: 377/377 render cases byte-identical, golden untouched.
Code lines 85 -> 49 (-36).
Width tier, title border, badge, cursor cell and row line now come from
__config_settings_frame. The per-tier description sets stay here -- they
are this page's data, authored to fit each tier's field exactly -- and are
selected by width rather than by re-testing $COLUMNS.
Rows pass the `pad` fit policy explicitly. That is a decision, not a
default: `cut` would be a byte-for-byte no-op on these strings today and
would silently discard the property that they are tuned to their field.
Drops c_hi, which was assigned and never read.
Rendering unchanged: 377/377 render cases byte-identical, golden untouched.
Code lines 114 -> 80 (-34).
The width tier, title-border arithmetic, ON/OFF/DEFAULT badge, cursor cell
and table row are currently hand-copied across the three draw functions.
This adds them once, with the two geometry identities derived rather than
hand-maintained: a row's chrome is a fixed 21 columns, so field_w is
iw - 21 - label_w (reproducing both iw-33 and iw-34), and a title border is
dashes = iw - visible(segment) - 1 (reproducing all three of iw-23,
iw-len-3 and iw-L-S-22).
The frame owns no page height. Every verb prints exactly one line or
fragment, so the fixed-16 category and value pages and the dynamic
7+n sub-category page keep their heights, and config-settings.fish's
erase is unaffected.
No caller yet, so rendering cannot move: the golden's existing page
section is byte-identical (verified with cmp -n over its previous size)
and the file only gains frame-verb cases appended after it.
The three config-settings draw functions are hand-tuned layout code whose
field widths, dash counts and pad targets are arithmetic on the width tier.
Any refactor of them has to be byte-identical, and nothing until now could
prove that.
Renders all 356 page/width/scope/cursor-row combinations -- every page at
COLUMNS 100/88/84/70, both scopes, cursor on every row, plus the inline
editor -- and byte-compares against a committed baseline.
The golden holds raw output: set_color escapes and box drawing exactly as
emitted, plus the wrap-aware \e[<N>A\e[J erase config-settings.fish would
emit for each panel, and per case the declared panel height against the
measured line count. Nothing is normalized; the gate is cmp(1) and a
one-space change anywhere fails it. Proven by four deliberate mutations,
one per draw function plus a panel-height change, each caught and reverted.
Runs entirely inside a throwaway HOME/XDG_CONFIG_HOME sandbox: the fixtures
must be real universal variables, and this repo doubles as a live
~/.config/fish. fish --no-config cannot be used, as -N silently degrades
set -U to global scope. Every utility is called through `command`, since
the config itself shadows rm, cat and mkdir and aliases cp -i.