Merge pull request 'feat(config-settings): rename config-toggle → config-settings; add __fish_user_dots_path UI' (#64) from feat/config-settings-rename-path-var into main
Generate documentation / build-docs (push) Successful in 30s
Offline docs drift reminder / remind (push) Successful in 11s

Reviewed-on: #64
This commit was merged in pull request #64.
This commit is contained in:
2026-06-23 18:28:29 +00:00
9 changed files with 313 additions and 198 deletions
+3 -3
View File
@@ -47,7 +47,7 @@ This config layers on top of the CachyOS base Fish configuration and adds:
> set -U __fish_config_op_logging off
> ```
>
> Or run **`config-toggle`** for an interactive menu to flip logging (and any
> Or run **`config-settings`** for an interactive menu to flip logging (and any
> other opinionated category) on or off — no variable names to remember.
>
> This takes effect immediately in every open shell. See [Session Logging](#session-logging)
@@ -89,7 +89,7 @@ set -U __fish_config_op_logging off # disable; takes effect in every open shel
set -Ue __fish_config_op_logging # re-enable (erase the override)
```
Prefer an interactive interface? Run **`config-toggle`** for a full-screen
Prefer an interactive interface? Run **`config-settings`** for a full-screen
picker that flips logging — and every other opinionated category — on or off
per session or universally, without memorizing variable names.
@@ -255,7 +255,7 @@ test -f "$__fish_user_dots_path/local.fish"
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 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.
> **The easy way — `config-settings`:** Run `config-settings` 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:
+3 -2
View File
@@ -155,8 +155,9 @@ yt-dlp=### yt-dlp
miscfns=## 5.14 Miscellaneous
config-help=### config-help
config-update=### config-update
config-toggle=### config-toggle
toggle=### config-toggle
config-settings=### config-settings
config-toggle=### config-settings
toggle=### config-settings
bash=### bash
cheat=### cheat
dockup=### dockup
+35 -13
View File
@@ -48,7 +48,7 @@ A production-grade Fish shell configuration targeting Fish 4.x. It provides:
> your machine, but the files persist locally.
>
> - Disable all logging with: `set -U __fish_config_op_logging off`
> - Prefer a menu? Run the interactive picker: `config-toggle`
> - Prefer a menu? Run the interactive picker: `config-settings`
> - See Section 7 (C5 - Logging and Capture) for the full breakdown.
The configuration is split across:
@@ -1347,19 +1347,24 @@ Add -i (interactive confirmation) to destructive commands:
config-update --dry-run
config-update --force
### config-toggle
### config-settings
Synopsis: config-toggle [-h]
Synopsis: config-settings [-h]
Opens an interactive TUI for toggling the six opinionated component
categories (C1C6) 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 managing fish configuration settings. Handles
the six opinionated component categories (C1C6), the master disable
variable, and the __fish_user_dots_path path variable — without having to
type or remember variable names. Two scope tabs allow independent per-scope
configuration for category toggles:
Universal — persists across all sessions (set -U)
Session — current shell only (set -g)
Changes apply immediately on each value keypress. Always available
The Dots Path row always operates on the universal scope regardless of the
active tab.
Changes to category toggles apply immediately on each keypress. Changes to
the path variable use an inline edit prompt (Enter). Always available
regardless of the __fish_config_opinionated master state.
The panel adapts to the terminal width automatically, selecting from
@@ -1374,17 +1379,30 @@ Add -i (interactive confirmation) to destructive commands:
Navigation:
↑ ↓ / k j Move cursor
← → / h l Set value: OFF ← DEFAULT → ON (clamped)
← → / h l Set value: OFF ← DEFAULT → ON (toggle rows); LEFT clears path
Enter Edit the Dots Path (path row only)
Tab Switch scope (Universal ↔ Session)
q / Escape Exit
Left/Right (or vim-style h/l) move the highlighted value one step along
the OFFDEFAULTON scale and stop at the ends. DEFAULT erases the
variable so the master switch / built-in default applies.
Left/Right (or vim-style h/l) move the highlighted toggle value one step
along the OFFDEFAULTON scale and stop at the ends. DEFAULT erases the
variable so the master switch / built-in default applies. On the Dots Path
row, LEFT/h clears the universal variable; RIGHT/l is a no-op (use Enter).
Dots Path row [U] tag: the tag confirms this row always writes to the
universal scope, regardless of which tab is active. Setting it per-session
would have no effect on startup sourcing.
Flags:
--help / -h Show usage.
config-settings
### config-toggle (deprecated)
Deprecated alias for config-settings. Prints a deprecation notice to
stderr, then delegates all arguments to config-settings.
config-toggle
### bash
@@ -1659,7 +1677,7 @@ Examples:
# (erase both to go back to full-flavor defaults)
For an interactive alternative to setting these variables by hand, run
config-toggle — a full-screen TUI that flips any category (including C5
config-settings — a full-screen TUI that flips any category (including C5
logging) on or off, per session or universally. See its entry in Section 5.
Notes:
@@ -2098,6 +2116,10 @@ control in a private directory. The path defaults to
set -U __fish_user_dots_path /path/to/your/dots/fish
Or use the interactive TUI — run `config-settings` and navigate to the
"Dots Path" row (last row). Press Enter to type a new path, or ← / h to
reset to the default.
config.fish sources local.fish from that directory on every interactive
session. local.fish is responsible for sourcing its own secrets.fish:
@@ -2,11 +2,11 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __config_toggle_apply <varname> <scope> <value>
# __config_settings_apply <varname> <scope> <value>
#
# DESCRIPTION
# Applies a state value to an opinionated-component variable in the given
# scope, immediately and persistently. Used by config-toggle's Left/Right
# scope, immediately and persistently. Used by config-settings's Left/Right
# (and vim h/l) directional handlers so the set/erase logic lives in one
# place. A value of "DEFAULT" erases the variable in that scope so the
# master switch / built-in default takes over again.
@@ -17,15 +17,15 @@
# ARGUMENTS
# varname Variable name without the $ prefix
# scope "universal" or "session"
# value "on", "off", or "DEFAULT"
# value "on", "off", "DEFAULT", or any arbitrary string (universal scope only)
#
# RETURNS
# 0 Always
#
# EXAMPLE
# __config_toggle_apply __fish_config_op_aliases universal off
# __config_toggle_apply __fish_config_op_greeting session DEFAULT
function __config_toggle_apply
# __config_settings_apply __fish_config_op_aliases universal off
# __config_settings_apply __fish_config_op_greeting session DEFAULT
function __config_settings_apply
set -l varname $argv[1]
set -l scope $argv[2]
set -l value $argv[3]
@@ -33,7 +33,7 @@ function __config_toggle_apply
# stderr is suppressed because setting a value in one scope while the
# other scope already holds the same variable makes interactive fish
# emit a shadowing warning ("set: successfully set universal 'X'; but a
# global by that name shadows it"). config-toggle intentionally edits
# global by that name shadows it"). config-settings intentionally edits
# both scopes independently, so the warning is expected noise — and if
# it reached the terminal it would push the cursor down a row and
# corrupt the in-place panel redraw (leaving a stacked top border
@@ -48,6 +48,8 @@ function __config_toggle_apply
set -U $varname off 2>/dev/null
case DEFAULT
set -Ue $varname 2>/dev/null
case '*'
set -U $varname $value 2>/dev/null
end
case session
switch $value
@@ -2,10 +2,10 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __config_toggle_draw <cur_row> <cur_scope> <var1> ... <var7>
# __config_settings_draw <cur_row> <cur_scope> <var1> ... <var8>
#
# DESCRIPTION
# Renders the 14-line config-toggle TUI panel to stdout. Panel width and
# Renders the 16-line config-settings 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:
@@ -16,24 +16,24 @@
# COLUMNS < 8252-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
# output line. \e[16A\e[J erases by line count so the horizontal offset
# does not interfere with the redraw loop.
#
# ARGUMENTS
# cur_row 06, the currently highlighted row
# cur_row 07, the currently highlighted row
# cur_scope "universal" or "session"
# var1var7 Variable names for rows 06 (in order per Variable Reference)
# var1var8 Variable names for rows 07 (in order per Variable Reference)
#
# RETURNS
# 0 Always
#
# EXAMPLE
# __config_toggle_draw 0 universal \
# __config_settings_draw 0 universal \
# __fish_config_op_aliases __fish_config_op_autoexec \
# __fish_config_op_overrides __fish_config_op_integrations \
# __fish_config_op_logging __fish_config_op_greeting \
# __fish_config_opinionated
function __config_toggle_draw
# __fish_config_opinionated __fish_user_dots_path
function __config_settings_draw
set -l cur_row $argv[1]
set -l cur_scope $argv[2]
set -l vars $argv[3..]
@@ -50,7 +50,7 @@ function __config_toggle_draw
# ── 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.
# All four layouts are exactly 16 lines tall — panel_h in caller stays 16.
set -l iw 50
set -l descs \
"cmd shadows" \
@@ -131,7 +131,7 @@ function __config_toggle_draw
set -l label $labels[$idx]
set -l desc $descs[$idx]
set -l val (__config_toggle_get_val $var $cur_scope)
set -l val (__config_settings_get_val $var $cur_scope)
# Badge: 7 visible chars, coloured
set -l badge
@@ -161,7 +161,7 @@ function __config_toggle_draw
printf '%s│ %s │\n' $p (string repeat -n (math $iw - 6) '─')
# ── Master row (index 6) ──────────────────────────────────────────────
set -l val (__config_toggle_get_val $vars[7] $cur_scope)
set -l val (__config_settings_get_val $vars[7] $cur_scope)
set -l badge
switch $val
case on
@@ -181,12 +181,42 @@ function __config_toggle_draw
$badge \
(string pad -r -w (math $iw - 33) -- $descs[7])
# ── Separator before Path Settings ───────────────────────────────────
printf '%s│ %s │\n' $p (string repeat -n (math $iw - 6) '─')
# ── Path row (index 7) — always universal scope ───────────────────────
set -l path_var $vars[8]
set -l raw_path (__config_settings_get_val $path_var universal)
set -l path_badge
set -l path_dpad
if test "$raw_path" = DEFAULT
set path_badge "$c_dim""DEFAULT$c_reset"
set path_dpad (string pad -r -w (math $iw - 33) -- "—default— [U]")
else
set path_badge "$c_ok"" PATH $c_reset"
set -l max_path (math $iw - 37)
set -l truncated (string shorten -m $max_path -- "$raw_path")
set path_dpad (string pad -r -w (math $iw - 33) -- "$truncated [U]")
end
set -l path_curs " "
if test $cur_row -eq 7
set path_curs "$c_sel$c_reset "
end
printf '%s│ %s%s [ %s ] %s │\n' \
$p $path_curs \
(string pad -r -w 12 -- "Dots Path") \
$path_badge \
$path_dpad
# ── Bottom divider ────────────────────────────────────────────────────
printf '%s│%s│\n' $p $HBR
# ── Keybind hint ──────────────────────────────────────────────────────
# string pad is width-aware (arrows count as 1 column)
set -l hint " ↑↓/kj move ←→/hl set Tab scope q quit"
set -l hint " ↑↓/kj move ←→/hl set Enter edit path q quit"
printf '%s│%s%s%s│\n' $p $c_dim (string pad -r -w $iw -- $hint) $c_reset
# ── Bottom border ─────────────────────────────────────────────────────
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __config_toggle_get_val <varname> <scope>
# __config_settings_get_val <varname> <scope>
#
# DESCRIPTION
# Returns the current value of a named variable in the specified scope by
@@ -18,9 +18,9 @@
# 0 Always; prints "on", "off", or "DEFAULT" to stdout
#
# EXAMPLE
# set result (__config_toggle_get_val __fish_config_op_aliases universal)
# set result (__config_settings_get_val __fish_config_op_aliases universal)
# # result == "on" | "off" | "DEFAULT"
function __config_toggle_get_val
function __config_settings_get_val
set -l varname $argv[1]
set -l scope $argv[2]
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __config_toggle_read_key
# __config_settings_read_key
#
# DESCRIPTION
# Reads a single keypress directly from the controlling terminal in raw
@@ -31,13 +31,13 @@
# 1 The terminal could not be put into raw mode (stdin is not a TTY)
#
# EXAMPLE
# set -l key (__config_toggle_read_key)
# set -l key (__config_settings_read_key)
# or return # not a TTY — bail
# switch $key
# case up; echo "moved up"
# case space; echo "toggled"
# end
function __config_toggle_read_key
function __config_settings_read_key
# Snapshot current terminal settings; failure means stdin is not a TTY.
set -l saved (stty -g </dev/tty 2>/dev/null)
or return 1
+206
View File
@@ -0,0 +1,206 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# config-settings [-h | --help]
#
# DESCRIPTION
# Opens an interactive full-screen TUI for managing fish config settings,
# including the six opinionated component categories (C1C6) and the master
# disable variable, without having to remember variable names. Two scope
# tabs allow independent per-scope configuration:
#
# Universal — persists across all sessions (set -U / set -Ue)
# Session — active for the current shell only (set -g / set -eg)
#
# Values are changed directionally with the arrow keys (or vim-style h/l)
# along an OFF ← DEFAULT → ON scale, and apply immediately — no confirm
# step. Always available regardless of __fish_config_opinionated state.
#
# ARGUMENTS
# -h, --help Print usage and exit
#
# RETURNS
# 0 Exited normally (q or Escape pressed)
# 1 Unknown flag passed
#
# EXAMPLE
# config-settings
function config-settings --description 'Interactive TUI for managing fish config settings'
set -l c_head (set_color --bold cyan)
set -l c_cmd (set_color --bold white)
set -l c_flag (set_color yellow)
set -l c_dim (set_color brblack)
set -l c_err (set_color red)
set -l c_reset (set_color normal)
# ── Argument parsing ──────────────────────────────────
for arg in $argv
switch $arg
case -h --help
echo "$c_head""Usage:$c_reset $c_cmd""config-settings$c_reset $c_flag""[-h]$c_reset"
echo
echo " Interactive TUI for managing fish config settings."
echo " Changes apply immediately — no confirm step required."
echo
echo "$c_head""Navigation:$c_reset"
echo " $c_flag↑ ↓$c_reset or $c_flag""k j$c_reset Move cursor up / down"
echo " $c_flag← →$c_reset or $c_flag""h l$c_reset Set value: OFF ← DEFAULT → ON"
echo " $c_flag""Tab$c_reset Switch scope (Universal ↔ Session)"
echo " $c_flag""Enter$c_reset Edit path (on Dots Path row)"
echo " $c_flag""q$c_reset / $c_flag""Esc$c_reset Exit"
echo
echo "$c_head""Scopes:$c_reset"
echo " $c_flag""Universal$c_reset Persistent across all sessions ($c_dim""set -U$c_reset)"
echo " $c_flag""Session$c_reset Current session only ($c_dim""set -g$c_reset)"
return 0
case '*'
echo "$c_err""Unknown option: $arg$c_reset" >&2
echo "Run $c_cmd""config-settings --help$c_reset for usage." >&2
return 1
end
end
# ── Variable list (matches Panel Layout Reference) ────
set -l vars \
__fish_config_op_aliases \
__fish_config_op_autoexec \
__fish_config_op_overrides \
__fish_config_op_integrations \
__fish_config_op_logging \
__fish_config_op_greeting \
__fish_config_opinionated \
__fish_user_dots_path
set -l cur_row 0 # 07
set -l cur_scope universal # or "session"
set -l panel_h 16 # total panel lines (all width tiers are 16 lines)
set -l last_cols $COLUMNS # COLUMNS at the time of the last draw
# ── Terminal setup ────────────────────────────────────
printf '\e[?25l' # hide cursor
trap 'printf "\e[?25h"; set -g __config_settings_exit 1' INT
# ── Initial draw ──────────────────────────────────────
__config_settings_draw $cur_row $cur_scope $vars
# ── Event loop ────────────────────────────────────────
# __config_settings_read_key reads a single keypress from /dev/tty in raw
# mode and returns a normalized token (up/down/tab/space/escape/quit or a
# literal char). It bypasses fish's `read`, whose line editor swallows Tab
# and arrow keys and prints a `read> ` prompt — unusable for a TUI.
while true
# Check for Ctrl-C signal (trap sets this flag during redraw, when the
# terminal is briefly back in cooked mode and SIGINT can fire).
if set -q __config_settings_exit
set -eg __config_settings_exit
break
end
set -l key (__config_settings_read_key)
or break # not a TTY — exit instead of spinning
set -l did_redraw 0
switch $key
case up k
set cur_row (math "max(0, $cur_row - 1)")
case down j
set cur_row (math "min(7, $cur_row + 1)")
case tab # Tab — switch scope
if test $cur_scope = universal
set cur_scope session
else
set cur_scope universal
end
case enter
if test $cur_row -eq 7
# Erase panel (wrap-aware, same formula as cleanup)
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
printf '\e[?25h' # restore cursor
printf 'User Dots Path (leave blank to reset to default): '
read -l new_path
if test -n "$new_path"
set -U __fish_user_dots_path $new_path
else
set -Ue __fish_user_dots_path
end
printf '\e[?25l' # hide cursor
set last_cols $COLUMNS
__config_settings_draw $cur_row $cur_scope $vars
set did_redraw 1
end
case right l # → / l — step toward ON (clamped, no wrap)
if test $cur_row -eq 7
# no-op for path var; use Enter to set
else
set -l varname $vars[(math $cur_row + 1)]
set -l cur_val (__config_settings_get_val $varname $cur_scope)
set -l next_val on
switch $cur_val
case off
set next_val DEFAULT
case on
set next_val on
case '*'
set next_val on
end
__config_settings_apply $varname $cur_scope $next_val
end
case left h # ← / h — step toward OFF (clamped, no wrap)
if test $cur_row -eq 7
# Clear the universal path var (restore default)
__config_settings_apply __fish_user_dots_path universal DEFAULT
else
set -l varname $vars[(math $cur_row + 1)]
set -l cur_val (__config_settings_get_val $varname $cur_scope)
set -l next_val off
switch $cur_val
case on
set next_val DEFAULT
case off
set next_val off
case '*'
set next_val off
end
__config_settings_apply $varname $cur_scope $next_val
end
case q Q quit escape
break
end
# Skip redraw entirely when the key reader timed out with no resize
if test -z "$key" -a "$COLUMNS" = "$last_cols"
continue
end
# Skip redraw if the Enter handler already redrew (e.g. after path edit)
if test $did_redraw -eq 1
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_settings_draw $cur_row $cur_scope $vars
end
# ── Cleanup ───────────────────────────────────────────
trap - INT # remove the signal handler
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
+9 -155
View File
@@ -2,167 +2,21 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# config-toggle [-h | --help]
# config-toggle [args...]
#
# DESCRIPTION
# Opens an interactive full-screen TUI for toggling the six opinionated
# component categories (C1C6) and the master disable variable without
# having to remember variable names. Two scope tabs allow independent
# per-scope configuration:
#
# Universal — persists across all sessions (set -U / set -Ue)
# Session — active for the current shell only (set -g / set -eg)
#
# Values are changed directionally with the arrow keys (or vim-style h/l)
# along an OFF ← DEFAULT → ON scale, and apply immediately — no confirm
# step. Always available regardless of __fish_config_opinionated state.
# Deprecated alias for config-settings. Prints a one-line deprecation
# notice to stderr, then delegates all arguments to config-settings.
#
# ARGUMENTS
# -h, --help Print usage and exit
# args Passed through verbatim to config-settings
#
# RETURNS
# 0 Exited normally (q or Escape pressed)
# 1 Unknown flag passed
# Same as config-settings
#
# EXAMPLE
# config-toggle
function config-toggle --description 'Interactive TUI for toggling opinionated component settings'
set -l c_head (set_color --bold cyan)
set -l c_cmd (set_color --bold white)
set -l c_flag (set_color yellow)
set -l c_dim (set_color brblack)
set -l c_err (set_color red)
set -l c_reset (set_color normal)
# ── Argument parsing ──────────────────────────────────
for arg in $argv
switch $arg
case -h --help
echo "$c_head""Usage:$c_reset $c_cmd""config-toggle$c_reset $c_flag""[-h]$c_reset"
echo
echo " Interactive TUI for toggling opinionated component categories."
echo " Changes apply immediately — no confirm step required."
echo
echo "$c_head""Navigation:$c_reset"
echo " $c_flag↑ ↓$c_reset or $c_flag""k j$c_reset Move cursor up / down"
echo " $c_flag← →$c_reset or $c_flag""h l$c_reset Set value: OFF ← DEFAULT → ON"
echo " $c_flag""Tab$c_reset Switch scope (Universal ↔ Session)"
echo " $c_flag""q$c_reset / $c_flag""Esc$c_reset Exit"
echo
echo "$c_head""Scopes:$c_reset"
echo " $c_flag""Universal$c_reset Persistent across all sessions ($c_dim""set -U$c_reset)"
echo " $c_flag""Session$c_reset Current session only ($c_dim""set -g$c_reset)"
return 0
case '*'
echo "$c_err""Unknown option: $arg$c_reset" >&2
echo "Run $c_cmd""config-toggle --help$c_reset for usage." >&2
return 1
end
end
# ── Variable list (matches Panel Layout Reference) ────
set -l vars \
__fish_config_op_aliases \
__fish_config_op_autoexec \
__fish_config_op_overrides \
__fish_config_op_integrations \
__fish_config_op_logging \
__fish_config_op_greeting \
__fish_config_opinionated
set -l cur_row 0 # 06
set -l cur_scope universal # or "session"
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
trap 'printf "\e[?25h"; set -g __config_toggle_exit 1' INT
# ── Initial draw ──────────────────────────────────────
__config_toggle_draw $cur_row $cur_scope $vars
# ── Event loop ────────────────────────────────────────
# __config_toggle_read_key reads a single keypress from /dev/tty in raw
# mode and returns a normalized token (up/down/tab/space/escape/quit or a
# literal char). It bypasses fish's `read`, whose line editor swallows Tab
# and arrow keys and prints a `read> ` prompt — unusable for a TUI.
while true
# Check for Ctrl-C signal (trap sets this flag during redraw, when the
# terminal is briefly back in cooked mode and SIGINT can fire).
if set -q __config_toggle_exit
set -eg __config_toggle_exit
break
end
set -l key (__config_toggle_read_key)
or break # not a TTY — exit instead of spinning
switch $key
case up k
set cur_row (math "max(0, $cur_row - 1)")
case down j
set cur_row (math "min(6, $cur_row + 1)")
case tab # Tab — switch scope
if test $cur_scope = universal
set cur_scope session
else
set cur_scope universal
end
case right l # → / l — step toward ON (clamped, no wrap)
set -l varname $vars[(math $cur_row + 1)]
set -l cur_val (__config_toggle_get_val $varname $cur_scope)
# Order: OFF ← DEFAULT → ON
set -l next_val on
switch $cur_val
case off
set next_val DEFAULT
case on
set next_val on # already at the right end
case '*' # DEFAULT or unrecognised
set next_val on
end
__config_toggle_apply $varname $cur_scope $next_val
case left h # ← / h — step toward OFF (clamped, no wrap)
set -l varname $vars[(math $cur_row + 1)]
set -l cur_val (__config_toggle_get_val $varname $cur_scope)
# Order: OFF ← DEFAULT → ON
set -l next_val off
switch $cur_val
case on
set next_val DEFAULT
case off
set next_val off # already at the left end
case '*' # DEFAULT or unrecognised
set next_val off
end
__config_toggle_apply $varname $cur_scope $next_val
case q Q quit escape
break
end
# 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
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
# config-toggle # opens config-settings with a deprecation notice
function config-toggle --description 'Deprecated alias for config-settings'
echo "config-toggle is deprecated, use config-settings instead" >&2
config-settings $argv
end