feat(config-toggle): adaptive width, centering, and resize handling
Panel now selects from four width tiers based on $COLUMNS (with a 6-col buffer per side before stepping up): 52-wide (default), 70, 74, or 78. Each tier carries richer category descriptions sized to fit the layout. The box is horizontally centered on every draw via a left-padding prefix. Key reader switches from stty min 1 to min 0 / time 3, giving a 0.3 s poll interval so COLUMNS changes are detected without a keypress. The erase formula is now wrap-aware: prev_max_line_width / COLUMNS gives the wrap factor, ensuring old wider panels are fully cleared after narrowing. Idle timeout ticks that detect no resize are skipped entirely.
This commit is contained in:
@@ -168,7 +168,7 @@ end
|
||||
|
||||
Everything opinionated in this config — command shadows, startup side-effects, key and environment overrides, terminal integrations, logging, and the first-run greeting — is active by default but can be switched off.
|
||||
|
||||
> **The easy way — `config-toggle`:** Run `config-toggle` for an interactive TUI that flips every setting below on, off, or back to default — per-session or universally — without typing a single variable name. Use the arrow keys (or `h`/`j`/`k`/`l`) to navigate and adjust, `Tab` to switch scope, and `q` to quit. Changes apply instantly.
|
||||
> **The easy way — `config-toggle`:** Run `config-toggle` for an interactive TUI that flips every setting below on, off, or back to default — per-session or universally — without typing a single variable name. Use the arrow keys (or `h`/`j`/`k`/`l`) to navigate and adjust, `Tab` to switch scope, and `q` to quit. Changes apply instantly. The panel auto-sizes to your terminal width (four tiers from 52- to 78-wide with a 6-column margin), centers itself horizontally, and redraws within ~0.3 s of a resize.
|
||||
|
||||
If you'd rather set them by hand, each category is controlled by a universal variable. Six category toggles and one master switch are available:
|
||||
|
||||
|
||||
+14
-4
@@ -1246,10 +1246,10 @@ Add -i (interactive confirmation) to destructive commands:
|
||||
|
||||
Synopsis: config-toggle [-h]
|
||||
|
||||
Opens an interactive full-screen TUI for toggling the six opinionated
|
||||
component categories (C1–C6) and the master disable variable without
|
||||
having to type or remember variable names. Two scope tabs allow
|
||||
independent per-scope configuration:
|
||||
Opens an interactive TUI for toggling the six opinionated component
|
||||
categories (C1–C6) and the master disable variable without having to
|
||||
type or remember variable names. Two scope tabs allow independent
|
||||
per-scope configuration:
|
||||
|
||||
Universal — persists across all sessions (set -U)
|
||||
Session — current shell only (set -g)
|
||||
@@ -1257,6 +1257,16 @@ Add -i (interactive confirmation) to destructive commands:
|
||||
Changes apply immediately on each value keypress. Always available
|
||||
regardless of the __fish_config_opinionated master state.
|
||||
|
||||
The panel adapts to the terminal width automatically, selecting from
|
||||
four layout tiers (with a 6-column buffer on each side before stepping
|
||||
up to the next tier) and horizontally centering the box. The panel
|
||||
redraws within ~0.3 s of a terminal resize with no keypress required.
|
||||
|
||||
COLUMNS >= 90 → 78-wide panel (most detail)
|
||||
COLUMNS >= 86 → 74-wide panel
|
||||
COLUMNS >= 82 → 70-wide panel
|
||||
COLUMNS < 82 → 52-wide panel (default)
|
||||
|
||||
Navigation:
|
||||
↑ ↓ / k j Move cursor
|
||||
← → / h l Set value: OFF ← DEFAULT → ON (clamped)
|
||||
|
||||
@@ -5,10 +5,19 @@
|
||||
# __config_toggle_draw <cur_row> <cur_scope> <var1> ... <var7>
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Renders the 14-line config-toggle TUI panel to stdout. Intended to be
|
||||
# called once on startup, then again after each keypress preceded by
|
||||
# `printf '\e[14A\e[J'` (cursor-up 14 lines + clear-to-end) to redraw
|
||||
# in place. Does not move the cursor — caller manages positioning.
|
||||
# Renders the 14-line config-toggle TUI panel to stdout. Panel width and
|
||||
# horizontal position are chosen automatically from $COLUMNS each call,
|
||||
# so a terminal resize takes effect on the next keypress without any
|
||||
# extra bookkeeping. Four width tiers with a 6-col buffer per side:
|
||||
#
|
||||
# COLUMNS ≥ 90 → 78-wide (IW=76, desc=43 chars)
|
||||
# COLUMNS ≥ 86 → 74-wide (IW=72, desc=39 chars)
|
||||
# COLUMNS ≥ 82 → 70-wide (IW=68, desc=35 chars)
|
||||
# COLUMNS < 82 → 52-wide (IW=50, desc=17 chars) ← default
|
||||
#
|
||||
# The box is horizontally centered via a left-padding prefix on every
|
||||
# output line. \e[14A\e[J erases by line count so the horizontal offset
|
||||
# does not interfere with the redraw loop.
|
||||
#
|
||||
# ARGUMENTS
|
||||
# cur_row 0–6, the currently highlighted row
|
||||
@@ -37,14 +46,60 @@ function __config_toggle_draw
|
||||
set -l c_head (set_color --bold cyan)
|
||||
set -l c_reset (set_color normal)
|
||||
|
||||
set -l labels Aliases Auto-exec Overrides Integrations Logging Greeting Master
|
||||
set -l descs "cmd shadows" startup "keys/env/prompt" "terminal coupling" scrollback fish_greeting "disable all"
|
||||
set -l labels Aliases Auto-exec Overrides Integrations Logging Greeting Master
|
||||
|
||||
# Panel dimensions
|
||||
set -l IW 50 # inner width (chars between │ │)
|
||||
set -l HBR (string repeat -n $IW '─')
|
||||
# ── Width tier: 6-col buffer per side before stepping up ──────────────
|
||||
# IW = inner width (chars between │ │); desc field = IW - 33.
|
||||
# All four layouts are exactly 14 lines tall — panel_h in caller stays 14.
|
||||
set -l iw 50
|
||||
set -l descs \
|
||||
"cmd shadows" \
|
||||
startup \
|
||||
"keys/env/prompt" \
|
||||
"terminal coupling" \
|
||||
scrollback \
|
||||
fish_greeting \
|
||||
"disable all"
|
||||
|
||||
# ── Scope tabs ────────────────────────────────────────
|
||||
if test "$COLUMNS" -ge 90
|
||||
set iw 76
|
||||
set descs \
|
||||
"shadows: ls→eza, cat→bat, cd→z, rm→trash" \
|
||||
"Fisher bootstrap, themes, py-venv activate" \
|
||||
"vi-mode, bang-bang, PAGER, CDPATH, starship" \
|
||||
"Kitty/WezTerm tab/split fns, notifications" \
|
||||
"scrollback capture & paru/yay AUR wrappers" \
|
||||
"fish_greeting & first-run welcome banner" \
|
||||
"master off-switch: overrides all categories"
|
||||
else if test "$COLUMNS" -ge 86
|
||||
set iw 72
|
||||
set descs \
|
||||
"ls→eza, cat→bat, cd→zoxide, rm→trash" \
|
||||
"Fisher bootstrap, themes, py-venv auto" \
|
||||
"vi-mode, bang-bang, PAGER, starship" \
|
||||
"Kitty/WezTerm fns, done notifications" \
|
||||
"scrollback capture & paru/yay wrappers" \
|
||||
"fish_greeting: first-run welcome banner" \
|
||||
"master off-switch for all categories"
|
||||
else if test "$COLUMNS" -ge 82
|
||||
set iw 68
|
||||
set descs \
|
||||
"ls→eza, cat→bat, cd→z, rm→trash" \
|
||||
"Fisher, themes, py-venv activate" \
|
||||
"vi-mode, bang-bang, PAGER, starship" \
|
||||
"Kitty/WezTerm, done notifications" \
|
||||
"scrollback & paru/yay log wrappers" \
|
||||
"fish_greeting & first-run banner" \
|
||||
"master disable for all categories"
|
||||
end
|
||||
|
||||
set -l HBR (string repeat -n $iw '─')
|
||||
|
||||
# ── Center padding ────────────────────────────────────────────────────
|
||||
# ponytail: floor division — left margin may be 1 col less than right if gap is odd
|
||||
set -l p (string repeat -n (math --scale=0 "max(0, ($COLUMNS - ($iw + 2)) / 2)") ' ')
|
||||
|
||||
# ── Scope tabs ────────────────────────────────────────────────────────
|
||||
set -l u_label
|
||||
set -l s_label
|
||||
if test $cur_scope = universal
|
||||
@@ -55,27 +110,26 @@ function __config_toggle_draw
|
||||
set s_label "$c_hi● Session $c_reset"
|
||||
end
|
||||
|
||||
# ── Top border ────────────────────────────────────────
|
||||
# Visible: ┌(1) ─(1) space(1) "Opinionated Settings"(20) space(1) N×─ ┐(1) = 52
|
||||
# N = 52 - 25 = 27 = IW - 23
|
||||
printf '┌─%s Opinionated Settings %s┐\n' \
|
||||
$c_head $c_reset(string repeat -n (math $IW - 23) '─')
|
||||
# ── Top border ────────────────────────────────────────────────────────
|
||||
# ┌─ Opinionated Settings (iw-23)×─ ┐ total = iw+2
|
||||
printf '%s┌─%s Opinionated Settings %s┐\n' \
|
||||
$p $c_head $c_reset(string repeat -n (math $iw - 23) '─')
|
||||
|
||||
# ── Scope tab line ────────────────────────────────────
|
||||
# Visible inner (50): space(1) + u_label(11) + 2spaces + s_label(11) + 10spaces + "Tab to switch "(15) = 50
|
||||
printf '│ %s %s%s│\n' \
|
||||
$u_label $s_label \
|
||||
(string repeat -n 10 ' ')"Tab to switch "
|
||||
# ── Scope tab line ────────────────────────────────────────────────────
|
||||
# Inner: " ●/○ Universal ●/○ Session " (25) + (iw-40)×space + "Tab to switch " (15) = iw
|
||||
printf '%s│ %s %s%s│\n' \
|
||||
$p $u_label $s_label \
|
||||
(string repeat -n (math $iw - 40) ' ')"Tab to switch "
|
||||
|
||||
# ── Top divider ───────────────────────────────────────
|
||||
printf '│%s│\n' $HBR
|
||||
# ── Top divider ───────────────────────────────────────────────────────
|
||||
printf '%s│%s│\n' $p $HBR
|
||||
|
||||
# ── Category rows 0–5 ─────────────────────────────────
|
||||
# ── Category rows 0–5 ─────────────────────────────────────────────────
|
||||
for i in (seq 0 5)
|
||||
set -l idx (math $i + 1)
|
||||
set -l var $vars[$idx]
|
||||
set -l label $labels[$idx]
|
||||
set -l desc $descs[$idx]
|
||||
set -l idx (math $i + 1)
|
||||
set -l var $vars[$idx]
|
||||
set -l label $labels[$idx]
|
||||
set -l desc $descs[$idx]
|
||||
|
||||
set -l val (__config_toggle_get_val $var $cur_scope)
|
||||
|
||||
@@ -96,17 +150,17 @@ function __config_toggle_draw
|
||||
set curs "$c_sel▶$c_reset "
|
||||
end
|
||||
|
||||
# Label padded to 12, desc padded to 17, right margin 3
|
||||
# Label padded to 12, desc padded to (iw-33), right margin 3
|
||||
set -l lpad (string pad -r -w 12 -- $label)
|
||||
set -l dpad (string pad -r -w 17 -- $desc)
|
||||
set -l dpad (string pad -r -w (math $iw - 33) -- $desc)
|
||||
|
||||
printf '│ %s%s [ %s ] %s │\n' $curs $lpad $badge $dpad
|
||||
printf '%s│ %s%s [ %s ] %s │\n' $p $curs $lpad $badge $dpad
|
||||
end
|
||||
|
||||
# ── Separator before Master ───────────────────────────
|
||||
printf '│ %s │\n' (string repeat -n (math $IW - 6) '─')
|
||||
# ── Separator before Master ───────────────────────────────────────────
|
||||
printf '%s│ %s │\n' $p (string repeat -n (math $iw - 6) '─')
|
||||
|
||||
# ── Master row (index 6) ──────────────────────────────
|
||||
# ── Master row (index 6) ──────────────────────────────────────────────
|
||||
set -l val (__config_toggle_get_val $vars[7] $cur_scope)
|
||||
set -l badge
|
||||
switch $val
|
||||
@@ -121,21 +175,20 @@ function __config_toggle_draw
|
||||
if test $cur_row -eq 6
|
||||
set curs "$c_sel▶$c_reset "
|
||||
end
|
||||
printf '│ %s%s [ %s ] %s │\n' \
|
||||
$curs \
|
||||
printf '%s│ %s%s [ %s ] %s │\n' \
|
||||
$p $curs \
|
||||
(string pad -r -w 12 -- Master) \
|
||||
$badge \
|
||||
(string pad -r -w 17 -- "disable all")
|
||||
(string pad -r -w (math $iw - 33) -- $descs[7])
|
||||
|
||||
# ── Bottom divider ────────────────────────────────────
|
||||
printf '│%s│\n' $HBR
|
||||
# ── Bottom divider ────────────────────────────────────────────────────
|
||||
printf '%s│%s│\n' $p $HBR
|
||||
|
||||
# ── Keybind hint ──────────────────────────────────────
|
||||
# Padded to the inner width so the right border stays aligned regardless
|
||||
# of the hint text. string pad is width-aware (arrows count as 1 column).
|
||||
# ── Keybind hint ──────────────────────────────────────────────────────
|
||||
# string pad is width-aware (arrows count as 1 column)
|
||||
set -l hint " ↑↓/kj move ←→/hl set Tab scope q quit"
|
||||
printf '│%s%s%s│\n' $c_dim (string pad -r -w $IW -- $hint) $c_reset
|
||||
printf '%s│%s%s%s│\n' $p $c_dim (string pad -r -w $iw -- $hint) $c_reset
|
||||
|
||||
# ── Bottom border ─────────────────────────────────────
|
||||
printf '└%s┘\n' $HBR
|
||||
# ── Bottom border ─────────────────────────────────────────────────────
|
||||
printf '%s└%s┘\n' $p $HBR
|
||||
end
|
||||
|
||||
@@ -42,9 +42,10 @@ function __config_toggle_read_key
|
||||
set -l saved (stty -g </dev/tty 2>/dev/null)
|
||||
or return 1
|
||||
|
||||
# Raw, no-echo. min 1 / time 1: block for the first byte, then wait up to
|
||||
# 0.1s for the rest of a burst (escape sequence) before returning.
|
||||
stty raw -echo min 1 time 1 </dev/tty 2>/dev/null
|
||||
# Raw, no-echo. min 0 / time 3: return after 0.3s even with no bytes (poll
|
||||
# interval for resize detection), or immediately when any bytes arrive.
|
||||
# Escape sequences (e.g. arrow keys) arrive fast enough to land in one read.
|
||||
stty raw -echo min 0 time 3 </dev/tty 2>/dev/null
|
||||
|
||||
# One read() of up to 3 bytes — covers ESC [ A style sequences. od emits
|
||||
# the bytes as space-separated decimal codes.
|
||||
|
||||
@@ -72,7 +72,8 @@ function config-toggle --description 'Interactive TUI for toggling opinionated c
|
||||
|
||||
set -l cur_row 0 # 0–6
|
||||
set -l cur_scope universal # or "session"
|
||||
set -l panel_h 14 # total panel lines
|
||||
set -l panel_h 14 # total panel lines (all width tiers are 14 lines)
|
||||
set -l last_cols $COLUMNS # COLUMNS at the time of the last draw
|
||||
|
||||
# ── Terminal setup ────────────────────────────────────
|
||||
printf '\e[?25l' # hide cursor
|
||||
@@ -142,13 +143,26 @@ function config-toggle --description 'Interactive TUI for toggling opinionated c
|
||||
break
|
||||
end
|
||||
|
||||
# Redraw in place
|
||||
printf '\e[%dA\e[J' $panel_h
|
||||
# Skip redraw entirely when the key reader timed out with no resize
|
||||
if test -z "$key" -a "$COLUMNS" = "$last_cols"
|
||||
continue
|
||||
end
|
||||
|
||||
# Wrap-aware erase: a panel drawn on a wider terminal has longer lines
|
||||
# (due to center-padding) that wrap into extra physical rows when the
|
||||
# terminal narrows. 78 = widest box (IW=76+2); the formula gives the
|
||||
# worst-case old line width for any tier drawn at last_cols.
|
||||
set -l prev_max_lw (math --scale=0 "($last_cols + 78) / 2")
|
||||
set -l erase_h (math --scale=0 "$panel_h * max(1, ceil($prev_max_lw / $COLUMNS))")
|
||||
printf '\e[%dA\e[J' $erase_h
|
||||
set last_cols $COLUMNS
|
||||
__config_toggle_draw $cur_row $cur_scope $vars
|
||||
end
|
||||
|
||||
# ── Cleanup ───────────────────────────────────────────
|
||||
trap - INT # remove the signal handler
|
||||
printf '\e[%dA\e[J' $panel_h # erase the panel
|
||||
set -l prev_max_lw (math --scale=0 "($last_cols + 78) / 2")
|
||||
set -l erase_h (math --scale=0 "$panel_h * max(1, ceil($prev_max_lw / $COLUMNS))")
|
||||
printf '\e[%dA\e[J' $erase_h # erase the panel (wrap-aware)
|
||||
printf '\e[?25h' # restore cursor
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user