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:
@@ -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
|
||||
@@ -178,6 +178,17 @@ function _cs_render_case --argument-names label panel_h
|
||||
command rm -f $t
|
||||
end
|
||||
|
||||
# ── Frame-verb fragments ──────────────────────────────────────────────────
|
||||
# The shared computations pinned directly, not only through the pages that use
|
||||
# them. <END> marks the end of each fragment so trailing padding -- which is
|
||||
# the entire point of a 7-column badge or a 2-column cursor cell -- shows up in
|
||||
# a diff instead of being invisible whitespace.
|
||||
function _cs_frame_case --argument-names label
|
||||
printf '### frame %s\n' $label
|
||||
$argv[2..]
|
||||
printf '<END>\n'
|
||||
end
|
||||
|
||||
# ── Cases ─────────────────────────────────────────────────────────────────
|
||||
# 100 -> IW 76, 88 -> IW 72, 84 -> IW 68, 70 -> IW 50: one COLUMNS value per
|
||||
# width tier, each a few columns above its threshold.
|
||||
@@ -222,4 +233,47 @@ begin
|
||||
_cs_render_case "edit page=paths row=2 buf=empty" 16 \
|
||||
__config_settings_draw_value 2 paths edit ""
|
||||
end
|
||||
|
||||
# Emitted last on purpose: everything above is page output, so the page
|
||||
# section's byte offsets never move when this section grows.
|
||||
for cols in 100 88 84 70
|
||||
set -g COLUMNS $cols
|
||||
_cs_frame_case "width cols=$cols" __config_settings_frame width
|
||||
end
|
||||
set -g COLUMNS 100
|
||||
|
||||
set -l head (set_color --bold cyan)
|
||||
set -l rst (set_color normal)
|
||||
set -l p_test (string repeat -n 11 ' ')
|
||||
|
||||
for v in on off DEFAULT ''
|
||||
_cs_frame_case "badge onoff val=$v" __config_settings_frame badge $v
|
||||
end
|
||||
for v in true false DEFAULT
|
||||
_cs_frame_case "badge boolean val=$v" __config_settings_frame badge $v true false
|
||||
end
|
||||
|
||||
_cs_frame_case "cursor hit" __config_settings_frame cursor 3 3
|
||||
_cs_frame_case "cursor miss" __config_settings_frame cursor 3 4
|
||||
|
||||
_cs_frame_case "title toggle-page" __config_settings_frame title 76 $p_test \
|
||||
"$head Opinionated Settings $rst"
|
||||
_cs_frame_case "title subcat-page" __config_settings_frame title 76 $p_test \
|
||||
"$head Sub-categories: aliases (Universal)$rst "
|
||||
_cs_frame_case "title value-page" __config_settings_frame title 76 $p_test \
|
||||
"$head Sponge Settings$rst "
|
||||
|
||||
set -l badge_on (__config_settings_frame badge on)
|
||||
_cs_frame_case "row pad lw=12" __config_settings_frame row 76 $p_test \
|
||||
(__config_settings_frame cursor 0 0) Aliases 12 $badge_on "cmd shadows" pad
|
||||
_cs_frame_case "row cut lw=13" __config_settings_frame row 76 $p_test \
|
||||
(__config_settings_frame cursor 0 1) Notifications 13 $badge_on "done, WakaTime hook" cut
|
||||
_cs_frame_case "row cut lw=13 overlong" __config_settings_frame row 50 $p_test \
|
||||
(__config_settings_frame cursor 0 0) Notifications 13 $badge_on \
|
||||
"ls, cat, cd, du, mkdir, rm, mv, zoxide" cut
|
||||
_cs_frame_case "row shorten lw=12" __config_settings_frame row 76 $p_test \
|
||||
(__config_settings_frame cursor 0 0) "Log dir" 12 $badge_on \
|
||||
/home/tester/very/long/scrollback/history/directory shorten
|
||||
_cs_frame_case "row shorten lw=12 empty" __config_settings_frame row 50 $p_test \
|
||||
(__config_settings_frame cursor 1 0) "Log max" 12 $badge_on "" shorten
|
||||
end >$CS_RENDER_OUT
|
||||
|
||||
@@ -4938,3 +4938,57 @@
|
||||
│──────────────────────────────────────────────────│
|
||||
│[90m type value Enter save Esc cancel ⌫ delete [m│
|
||||
└──────────────────────────────────────────────────┘
|
||||
### frame width cols=100
|
||||
76
|
||||
<END>
|
||||
### frame width cols=88
|
||||
72
|
||||
<END>
|
||||
### frame width cols=84
|
||||
68
|
||||
<END>
|
||||
### frame width cols=70
|
||||
50
|
||||
<END>
|
||||
### frame badge onoff val=on
|
||||
[32m ON[m<END>
|
||||
### frame badge onoff val=off
|
||||
[31mOFF [m<END>
|
||||
### frame badge onoff val=DEFAULT
|
||||
[90mDEFAULT[m<END>
|
||||
### frame badge onoff val=
|
||||
[90mDEFAULT[m<END>
|
||||
### frame badge boolean val=true
|
||||
[32m ON[m<END>
|
||||
### frame badge boolean val=false
|
||||
[31mOFF [m<END>
|
||||
### frame badge boolean val=DEFAULT
|
||||
[90mDEFAULT[m<END>
|
||||
### frame cursor hit
|
||||
[35;1m▶[m <END>
|
||||
### frame cursor miss
|
||||
<END>
|
||||
### frame title toggle-page
|
||||
┌─[36;1m Opinionated Settings [m─────────────────────────────────────────────────────┐
|
||||
<END>
|
||||
### frame title subcat-page
|
||||
┌─[36;1m Sub-categories: aliases (Universal)[m ──────────────────────────────────────┐
|
||||
<END>
|
||||
### frame title value-page
|
||||
┌─[36;1m Sponge Settings[m ──────────────────────────────────────────────────────────┐
|
||||
<END>
|
||||
### frame row pad lw=12
|
||||
│ [35;1m▶[m Aliases [ [32m ON[m ] cmd shadows │
|
||||
<END>
|
||||
### frame row cut lw=13
|
||||
│ Notifications [ [32m ON[m ] done, WakaTime hook │
|
||||
<END>
|
||||
### frame row cut lw=13 overlong
|
||||
│ [35;1m▶[m Notifications [ [32m ON[m ] ls, cat, cd, du, │
|
||||
<END>
|
||||
### frame row shorten lw=12
|
||||
│ [35;1m▶[m Log dir [ [32m ON[m ] /home/tester/very/long/scrollback/history/… │
|
||||
<END>
|
||||
### frame row shorten lw=12 empty
|
||||
│ Log max [ [32m ON[m ] │
|
||||
<END>
|
||||
|
||||
Reference in New Issue
Block a user