feat(config-settings): add __config_settings_frame shared renderer

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.
This commit is contained in:
2026-09-07 20:00:59 -04:00
parent 574b235b6f
commit 2ac8e5c0d4
3 changed files with 263 additions and 0 deletions
+155
View File
@@ -0,0 +1,155 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __config_settings_frame width
# __config_settings_frame title <iw> <p> <segment>
# __config_settings_frame badge <value> [<on_word> <off_word>]
# __config_settings_frame cursor <row> <cur_row>
# __config_settings_frame row <iw> <p> <curs> <label> <label_w> <badge> <field> <fit>
#
# DESCRIPTION
# The pieces of the config-settings panel that every page draws identically:
# the width tier, the title border, the ON/OFF/DEFAULT badge, the cursor cell
# and one table row. __config_settings_draw, __config_settings_draw_subcat
# and __config_settings_draw_value each keep their own sequence of lines and
# their own per-tier text; only these shared computations live here.
#
# Deliberately owns no page height. Every verb prints exactly one line or one
# fragment, so how tall a page is remains a property of its caller's line
# sequence: __config_settings_draw and __config_settings_draw_value are a
# fixed 16 lines, __config_settings_draw_subcat is 7 + <sub-category count>,
# and config-settings.fish's wrap-aware erase (\e[<N>A\e[J, sized from
# panel_h) depends on that difference surviving exactly as it is.
#
# Row geometry. A row is
# │ + 2 spaces + cursor(2) + label(label_w) + " [ " + badge(7) + " ] "
# + field(field_w) + 3 spaces + │
# which totals 23 + label_w + field_w and must equal iw + 2. So
# field_w = iw - 21 - label_w
# and that single sum reproduces both hand-maintained constants: label_w 12
# gives iw-33 (the toggle and value pages), label_w 13 gives iw-34 (the
# sub-category page, whose description field absorbs its wider label).
#
# Title geometry. "┌─" + segment + dashes + "┐" totals iw + 2, so
# dashes = iw - visible(segment) - 1
# The segment arrives already coloured because the three pages place their
# set_color reset at different byte offsets around the same visible text
# (__config_settings_draw resets after the trailing space, the other two
# before it). That difference is invisible on screen and visible to cmp, so
# each page keeps its own bytes while sharing the arithmetic; --visible
# discounts the escapes.
#
# ARGUMENTS
# width No arguments. Prints the inner width for the current $COLUMNS:
# >= 90 -> 76, >= 86 -> 72, >= 82 -> 68, otherwise 50.
# title iw, the centering prefix, and the pre-coloured title segment.
# badge The stored value, then optionally the words this page uses for true
# and false (default on/off; the value pages store true/false).
# Anything else renders DEFAULT.
# cursor This row's index and the highlighted row's index.
# row iw, centering prefix, cursor cell, label, label field width,
# rendered badge, field text, and the fit policy:
# pad pad label and field, never shrink either
# cut truncate both to their field width, then pad
# shorten pad the label, ellipsise the field with string shorten
#
# EXIT STATUS
# 0 Verb recognised
# 1 Unknown verb
#
# RETURNS
# The requested panel line or fragment, printed to stdout
#
# NOTES
# `string pad` only ever grows a string, never shrinks it. That is the whole
# reason `cut` and `shorten` exist: a caller whose text can exceed its field
# must shrink it first, or the box stops being rectangular.
#
# `pad` is not "the default when you don't care". __config_settings_draw's
# descriptions are authored per width tier to fit their field exactly -- at
# every tier the longest is precisely the field width -- so applying `cut`
# there would be a byte-for-byte no-op that silently discards that property
# and passes the render golden. Which policy a page uses is a real decision,
# named at each call site. See tests/config-settings-render.fish.
#
# EXAMPLE
# set -l iw (__config_settings_frame width)
# __config_settings_frame row $iw $p (__config_settings_frame cursor 0 0) \
# Aliases 12 (__config_settings_frame badge on) "cmd shadows" pad
function __config_settings_frame
switch $argv[1]
# ── Width tier: 6-col buffer per side before stepping up ──────────
case width
if test "$COLUMNS" -ge 90
echo 76
else if test "$COLUMNS" -ge 86
echo 72
else if test "$COLUMNS" -ge 82
echo 68
else
echo 50
end
# ── Title border: ┌─<segment><dashes>┐ ────────────────────────────
case title
set -l iw $argv[2]
set -l vis (string length --visible -- "$argv[4]")
set -l dashes (math "max(0, $iw - $vis - 1)")
printf '%s┌─%s%s┐\n' $argv[3] "$argv[4]" (string repeat -n $dashes '─')
# ── Badge: 7 visible columns, coloured ────────────────────────────
# The truthy/falsy words are arguments rather than one merged
# vocabulary: merging would make a hand-set "on" in a true/false
# variable render as ON where it renders DEFAULT today.
case badge
set -l on_word on
set -l off_word off
if test (count $argv) -ge 4
set on_word $argv[3]
set off_word $argv[4]
end
switch "$argv[2]"
case $on_word
printf '%s ON%s' (set_color green) (set_color normal)
case $off_word
printf '%sOFF %s' (set_color red) (set_color normal)
case '*'
printf '%sDEFAULT%s' (set_color brblack) (set_color normal)
end
# ── Cursor cell: 2 visible columns ────────────────────────────────
case cursor
if test $argv[2] -eq $argv[3]
printf '%s▶%s ' (set_color --bold magenta) (set_color normal)
else
printf ' '
end
# ── One table row ─────────────────────────────────────────────────
case row
set -l iw $argv[2]
set -l p $argv[3]
set -l curs $argv[4]
set -l label "$argv[5]"
set -l label_w $argv[6]
set -l badge $argv[7]
set -l field "$argv[8]"
set -l fit $argv[9]
set -l field_w (math $iw - 21 - $label_w)
switch $fit
case cut
set label (string sub -l $label_w -- "$label")
set field (string sub -l $field_w -- "$field")
case shorten
set field (string shorten -m $field_w -- "$field")
end
printf '%s│ %s%s [ %s ] %s │\n' $p $curs \
(string pad -r -w $label_w -- "$label") $badge \
(string pad -r -w $field_w -- "$field")
case '*'
echo "__config_settings_frame: unknown verb '$argv[1]'" >&2
return 1
end
end