Merge pull request 'feat(config-settings): four-page TUI (Universal · Session · Sponge · Paths)' (#66) from feat/config-settings-pages into main
Reviewed-on: #66
This commit was merged in pull request #66.
This commit is contained in:
@@ -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.
|
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-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.
|
> **The easy way — `config-settings`:** Run `config-settings` for an interactive TUI that manages settings across four pages — **Universal** and **Session** (the opinionated category toggles below, persistent or per-shell), **Sponge** (history-scrubbing: delay, exit codes, purge-on-exit, and extra sensitive variable names), and **Paths** (scrollback log dir, max files, and the user-dots path) — without typing a single variable name. Navigate with the arrow keys (or `h`/`j`/`k`/`l`); toggle rows step OFF ← DEFAULT → ON, value rows edit inline with `Enter` and clear with `←`. `Tab`/`Shift-Tab` cycle pages and `q` quits. 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:
|
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:
|
||||||
|
|
||||||
|
|||||||
@@ -95,8 +95,19 @@ function __sponge_register_secret_values --on-event fish_prompt
|
|||||||
|
|
||||||
set -l secret_values
|
set -l secret_values
|
||||||
|
|
||||||
set -l sensitive_vars (set --names --export | string match --regex -- \
|
# Base credential-name tokens, plus any user-supplied extras from
|
||||||
'(?i)(?:TOKEN|PASSWORD|PASSWD|SECRET|API[_-]KEY|PRIVATE[_-]KEY|ACCESS[_-]KEY|AUTH[_-]KEY|CREDENTIAL|KOPIA_PASSWORD)')
|
# __fish_sponge_extra_sensitive (set via config-settings → Sponge page).
|
||||||
|
set -l _sensitive_names \
|
||||||
|
TOKEN PASSWORD PASSWD SECRET 'API[_-]KEY' 'PRIVATE[_-]KEY' \
|
||||||
|
'ACCESS[_-]KEY' 'AUTH[_-]KEY' CREDENTIAL KOPIA_PASSWORD \
|
||||||
|
$__fish_sponge_extra_sensitive
|
||||||
|
set -l _sensitive_alt (string join '|' $_sensitive_names)
|
||||||
|
|
||||||
|
# --entire returns the full matching variable NAME (e.g. GITHUB_TOKEN), not
|
||||||
|
# just the matched token substring (TOKEN) — required so $$var below
|
||||||
|
# dereferences the real variable instead of an unset partial name.
|
||||||
|
set -l sensitive_vars (set --names --export | string match --regex --entire -- \
|
||||||
|
"(?i)(?:$_sensitive_alt)")
|
||||||
|
|
||||||
for var in $sensitive_vars
|
for var in $sensitive_vars
|
||||||
# Take only the first element — array vars yield multiple values.
|
# Take only the first element — array vars yield multiple values.
|
||||||
|
|||||||
+10
-2
@@ -116,10 +116,18 @@ set -gx SUDO_EDITOR $EDITOR
|
|||||||
set -gx GPG_TTY (tty)
|
set -gx GPG_TTY (tty)
|
||||||
|
|
||||||
# ────────────────────────── Scrollback History ──────────────────────────
|
# ────────────────────────── Scrollback History ──────────────────────────
|
||||||
# Directory where scrollback history is saved into log files.
|
# Optional fish-style source of truth (set -U via config-settings); exported
|
||||||
|
# for the POSIX wrappers (paru/yay/tmux/zellij/_prune_terminal_logs) that read
|
||||||
|
# them. We export the default unconditionally, then override from the universal
|
||||||
|
# var only if set — deliberately NOT creating a global, which would shadow the
|
||||||
|
# universal and stop live edits (config-settings → Paths) from taking effect.
|
||||||
set -gx SCROLLBACK_HISTORY_DIR "$HOME/.terminal_history"
|
set -gx SCROLLBACK_HISTORY_DIR "$HOME/.terminal_history"
|
||||||
# Maximum number of scrollback history files to keep
|
set -q __fish_scrollback_history_dir
|
||||||
|
and set -gx SCROLLBACK_HISTORY_DIR $__fish_scrollback_history_dir
|
||||||
|
|
||||||
set -gx SCROLLBACK_HISTORY_MAX_FILES 100
|
set -gx SCROLLBACK_HISTORY_MAX_FILES 100
|
||||||
|
set -q __fish_scrollback_history_max_files
|
||||||
|
and set -gx SCROLLBACK_HISTORY_MAX_FILES $__fish_scrollback_history_max_files
|
||||||
# Wire up a clean exit function that won't fire on background subshells
|
# Wire up a clean exit function that won't fire on background subshells
|
||||||
# Replacing the exit builtin is opinionated (C3 overrides); smart_exit also
|
# Replacing the exit builtin is opinionated (C3 overrides); smart_exit also
|
||||||
# guards itself so a live toggle takes effect without restarting the shell.
|
# guards itself so a live toggle takes effect without restarting the shell.
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ toolhomes=## Tool Homes (XDG-compliant)
|
|||||||
editor=## Editor and Pager
|
editor=## Editor and Pager
|
||||||
pager=## Editor and Pager
|
pager=## Editor and Pager
|
||||||
scrollback=## Scrollback History
|
scrollback=## Scrollback History
|
||||||
|
__fish_scrollback_history_dir=## Scrollback History
|
||||||
|
__fish_scrollback_history_max_files=## Scrollback History
|
||||||
|
scrollback-dir=## Scrollback History
|
||||||
|
|
||||||
# ── Section 2: PATH ───────────────────────────────────────────
|
# ── Section 2: PATH ───────────────────────────────────────────
|
||||||
path=# 2. PATH SETUP
|
path=# 2. PATH SETUP
|
||||||
@@ -258,6 +261,9 @@ sponge=## Fisher-Managed Plugins
|
|||||||
sponge-filtering=## Sponge History Filtering
|
sponge-filtering=## Sponge History Filtering
|
||||||
history-filtering=## Sponge History Filtering
|
history-filtering=## Sponge History Filtering
|
||||||
privacy=## Sponge History Filtering
|
privacy=## Sponge History Filtering
|
||||||
|
__fish_sponge_extra_sensitive=## Sponge History Filtering
|
||||||
|
extra-sensitive=## Sponge History Filtering
|
||||||
|
sponge-settings=### config-settings
|
||||||
bundled-plugins=## Bundled Plugin Functionality
|
bundled-plugins=## Bundled Plugin Functionality
|
||||||
fish-plugins-manifest=## fish_plugins Manifest
|
fish-plugins-manifest=## fish_plugins Manifest
|
||||||
|
|
||||||
|
|||||||
+57
-28
@@ -166,8 +166,19 @@ Tools that respect XDG are directed to these paths rather than polluting $HOME.
|
|||||||
|
|
||||||
## Scrollback History
|
## Scrollback History
|
||||||
|
|
||||||
SCROLLBACK_HISTORY_DIR ~/.terminal_history
|
__fish_scrollback_history_dir (unset → ~/.terminal_history)
|
||||||
SCROLLBACK_HISTORY_MAX_FILES 100
|
__fish_scrollback_history_max_files (unset → 100)
|
||||||
|
SCROLLBACK_HISTORY_DIR ~/.terminal_history (exported mirror)
|
||||||
|
SCROLLBACK_HISTORY_MAX_FILES 100 (exported mirror)
|
||||||
|
|
||||||
|
The __fish_scrollback_history_* universal variables are the fish-style source
|
||||||
|
of truth — set them via `config-settings` → Paths, or `set -U` directly.
|
||||||
|
config.fish exports the SCROLLBACK_HISTORY_* mirrors from them, because the
|
||||||
|
POSIX wrapper scripts (paru/yay/tmux/zellij logging and _prune_terminal_logs)
|
||||||
|
read the exported names from the environment. When the __fish_ vars are unset,
|
||||||
|
the documented defaults are exported. config.fish deliberately does not create
|
||||||
|
a global source var, which would shadow the universal and stop live edits from
|
||||||
|
taking effect.
|
||||||
|
|
||||||
Scrollback logs accumulate in SCROLLBACK_HISTORY_DIR as timestamped files.
|
Scrollback logs accumulate in SCROLLBACK_HISTORY_DIR as timestamped files.
|
||||||
When the count exceeds SCROLLBACK_HISTORY_MAX_FILES the oldest are pruned
|
When the count exceeds SCROLLBACK_HISTORY_MAX_FILES the oldest are pruned
|
||||||
@@ -1352,21 +1363,33 @@ Add -i (interactive confirmation) to destructive commands:
|
|||||||
|
|
||||||
Synopsis: config-settings [-h]
|
Synopsis: config-settings [-h]
|
||||||
|
|
||||||
Opens an interactive TUI for managing fish configuration settings. Handles
|
Opens an interactive TUI for managing fish configuration settings across
|
||||||
the six opinionated component categories (C1–C6), the master disable
|
four pages, without having to type or remember variable names. Tab cycles
|
||||||
variable, and the __fish_user_dots_path path variable — without having to
|
forward through the pages; Shift-Tab cycles backward.
|
||||||
type or remember variable names. Two scope tabs allow independent per-scope
|
|
||||||
configuration for category toggles:
|
|
||||||
|
|
||||||
Universal — persists across all sessions (set -U)
|
Universal — opinionated category toggles (C1–C6) + master, persistent (set -U)
|
||||||
Session — current shell only (set -g)
|
Session — the same toggles, current shell only (set -g)
|
||||||
|
Sponge — sponge history-scrubbing settings: delay, successful exit
|
||||||
|
codes, purge-only-on-exit, allow-previously-successful, and
|
||||||
|
extra sensitive variable-name tokens
|
||||||
|
Paths — scrollback log directory, scrollback max files, and the
|
||||||
|
user-dots path
|
||||||
|
|
||||||
The Dots Path row always operates on the universal scope regardless of the
|
Toggle rows use ← → (or h/l) along an OFF ← DEFAULT → ON scale; DEFAULT
|
||||||
active tab.
|
erases the variable so the master switch / built-in default applies. Value
|
||||||
|
rows (the path/int/list settings on the Sponge and Paths pages) use Enter to
|
||||||
|
edit inline; ← / h clears the value back to its default. List rows (e.g.
|
||||||
|
Extra secret, OK codes) accept values separated by commas and/or whitespace
|
||||||
|
— "A, B", "A,B" and "A B" all yield the same two entries. Changes apply
|
||||||
|
immediately. Always available regardless of the __fish_config_opinionated
|
||||||
|
master state.
|
||||||
|
|
||||||
Changes to category toggles apply immediately on each keypress. Changes to
|
The Sponge and Paths pages always write universal variables — these are
|
||||||
the path variable use an inline edit prompt (Enter). Always available
|
persistent, set-and-forget settings with no per-session scope. Editing a
|
||||||
regardless of the __fish_config_opinionated master state.
|
scrollback row updates both the __fish_scrollback_history_* source-of-truth
|
||||||
|
variables and the exported SCROLLBACK_HISTORY_* mirrors, so the AUR/tmux/
|
||||||
|
zellij log wrappers (which read the exported names) see the change in the
|
||||||
|
running session.
|
||||||
|
|
||||||
The panel adapts to the terminal width automatically, selecting from
|
The panel adapts to the terminal width automatically, selecting from
|
||||||
four layout tiers (with a 6-column buffer on each side before stepping
|
four layout tiers (with a 6-column buffer on each side before stepping
|
||||||
@@ -1379,20 +1402,12 @@ Add -i (interactive confirmation) to destructive commands:
|
|||||||
COLUMNS < 82 → 52-wide panel (default)
|
COLUMNS < 82 → 52-wide panel (default)
|
||||||
|
|
||||||
Navigation:
|
Navigation:
|
||||||
↑ ↓ / k j Move cursor
|
↑ ↓ / k j Move cursor
|
||||||
← → / h l Set value: OFF ← DEFAULT → ON (toggle rows); LEFT clears path
|
← → / h l Toggle rows: OFF ← DEFAULT → ON
|
||||||
Enter Edit the Dots Path (path row only)
|
← / h Value rows: clear to default
|
||||||
Tab Switch scope (Universal ↔ Session)
|
Enter Value rows: edit inline (Sponge / Paths pages)
|
||||||
q / Escape Exit
|
Tab / S-Tab Next / previous page
|
||||||
|
q / Escape Exit
|
||||||
Left/Right (or vim-style h/l) move the highlighted toggle value one step
|
|
||||||
along the OFF–DEFAULT–ON 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:
|
Flags:
|
||||||
--help / -h Show usage.
|
--help / -h Show usage.
|
||||||
@@ -2043,6 +2058,20 @@ To add your own persistent patterns:
|
|||||||
|
|
||||||
set -U -a sponge_regex_patterns 'your-regex-here'
|
set -U -a sponge_regex_patterns 'your-regex-here'
|
||||||
|
|
||||||
|
To mark additional variable NAMES as credential-bearing (so Layer 2 scrubs
|
||||||
|
their values), add name tokens — via `config-settings` → Sponge, or directly:
|
||||||
|
|
||||||
|
set -U -a __fish_sponge_extra_sensitive ACME_API VAULT_PW
|
||||||
|
|
||||||
|
Tokens are folded into the Layer 2 name match case-insensitively as substrings,
|
||||||
|
so ACME_API also covers ACME_API_KEY. (The match uses `--entire` to return the
|
||||||
|
full variable name, so partial-name tokens dereference the right value.)
|
||||||
|
|
||||||
|
The `config-settings` Sponge page also surfaces sponge's own tuning variables —
|
||||||
|
sponge_delay, sponge_successful_exit_codes, sponge_purge_only_on_exit, and
|
||||||
|
sponge_allow_previously_successful — so they can be changed without typing
|
||||||
|
variable names.
|
||||||
|
|
||||||
## Bundled Plugin Functionality
|
## Bundled Plugin Functionality
|
||||||
|
|
||||||
The remaining plugin functionality is bundled directly with this config rather
|
The remaining plugin functionality is bundled directly with this config rather
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# __config_settings_draw <cur_row> <cur_scope> <var1> ... <var8>
|
# __config_settings_draw <cur_row> <cur_scope> <var1> ... <var7>
|
||||||
#
|
#
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
# Renders the 16-line config-settings TUI panel to stdout. Panel width and
|
# Renders the 16-line config-settings TUI panel to stdout. Panel width and
|
||||||
@@ -20,9 +20,9 @@
|
|||||||
# does not interfere with the redraw loop.
|
# does not interfere with the redraw loop.
|
||||||
#
|
#
|
||||||
# ARGUMENTS
|
# ARGUMENTS
|
||||||
# cur_row 0–7, the currently highlighted row
|
# cur_row 0–6, the currently highlighted row
|
||||||
# cur_scope "universal" or "session"
|
# cur_scope "universal" or "session"
|
||||||
# var1–var8 Variable names for rows 0–7 (in order per Variable Reference)
|
# var1–var7 Variable names for rows 0–6 (6 categories + master)
|
||||||
#
|
#
|
||||||
# RETURNS
|
# RETURNS
|
||||||
# 0 Always
|
# 0 Always
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
# __fish_config_op_aliases __fish_config_op_autoexec \
|
# __fish_config_op_aliases __fish_config_op_autoexec \
|
||||||
# __fish_config_op_overrides __fish_config_op_integrations \
|
# __fish_config_op_overrides __fish_config_op_integrations \
|
||||||
# __fish_config_op_logging __fish_config_op_greeting \
|
# __fish_config_op_logging __fish_config_op_greeting \
|
||||||
# __fish_config_opinionated __fish_user_dots_path
|
# __fish_config_opinionated
|
||||||
function __config_settings_draw
|
function __config_settings_draw
|
||||||
set -l cur_row $argv[1]
|
set -l cur_row $argv[1]
|
||||||
set -l cur_scope $argv[2]
|
set -l cur_scope $argv[2]
|
||||||
@@ -99,27 +99,17 @@ function __config_settings_draw
|
|||||||
# ponytail: floor division — left margin may be 1 col less than right if gap is odd
|
# 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)") ' ')
|
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
|
|
||||||
set u_label "$c_hi● Universal$c_reset"
|
|
||||||
set s_label "○ Session "
|
|
||||||
else
|
|
||||||
set u_label "○ Universal"
|
|
||||||
set s_label "$c_hi● Session $c_reset"
|
|
||||||
end
|
|
||||||
|
|
||||||
# ── Top border ────────────────────────────────────────────────────────
|
# ── Top border ────────────────────────────────────────────────────────
|
||||||
# ┌─ Opinionated Settings (iw-23)×─ ┐ total = iw+2
|
# ┌─ Opinionated Settings (iw-23)×─ ┐ total = iw+2
|
||||||
printf '%s┌─%s Opinionated Settings %s┐\n' \
|
printf '%s┌─%s Opinionated Settings %s┐\n' \
|
||||||
$p $c_head $c_reset(string repeat -n (math $iw - 23) '─')
|
$p $c_head $c_reset(string repeat -n (math $iw - 23) '─')
|
||||||
|
|
||||||
# ── Scope tab line ────────────────────────────────────────────────────
|
# ── Page-tab header ───────────────────────────────────────────────────
|
||||||
# Inner: " ●/○ Universal ●/○ Session " (25) + (iw-40)×space + "Tab to switch " (15) = iw
|
set -l active_idx 0
|
||||||
printf '%s│ %s %s%s│\n' \
|
if test $cur_scope = session
|
||||||
$p $u_label $s_label \
|
set active_idx 1
|
||||||
(string repeat -n (math $iw - 40) ' ')"Tab to switch "
|
end
|
||||||
|
printf '%s│%s│\n' $p (__config_settings_pagetab $active_idx $iw)
|
||||||
|
|
||||||
# ── Top divider ───────────────────────────────────────────────────────
|
# ── Top divider ───────────────────────────────────────────────────────
|
||||||
printf '%s│%s│\n' $p $HBR
|
printf '%s│%s│\n' $p $HBR
|
||||||
@@ -181,42 +171,18 @@ function __config_settings_draw
|
|||||||
$badge \
|
$badge \
|
||||||
(string pad -r -w (math $iw - 33) -- $descs[7])
|
(string pad -r -w (math $iw - 33) -- $descs[7])
|
||||||
|
|
||||||
# ── Separator before Path Settings ───────────────────────────────────
|
# ── Filler (Dots Path moved to the Paths page) ────────────────────────
|
||||||
printf '%s│ %s │\n' $p (string repeat -n (math $iw - 6) '─')
|
printf '%s│ %s%s│\n' $p \
|
||||||
|
"$c_dim→ Tab for Sponge & Path settings$c_reset" \
|
||||||
# ── Path row (index 7) — always universal scope ───────────────────────
|
(string repeat -n (math $iw - 34) ' ')
|
||||||
set -l path_var $vars[8]
|
printf '%s│%s│\n' $p (string repeat -n $iw ' ')
|
||||||
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 ────────────────────────────────────────────────────
|
# ── Bottom divider ────────────────────────────────────────────────────
|
||||||
printf '%s│%s│\n' $p $HBR
|
printf '%s│%s│\n' $p $HBR
|
||||||
|
|
||||||
# ── Keybind hint ──────────────────────────────────────────────────────
|
# ── Keybind hint ──────────────────────────────────────────────────────
|
||||||
# string pad is width-aware (arrows count as 1 column)
|
# string pad is width-aware (arrows count as 1 column)
|
||||||
set -l hint " ↑↓/kj move ←→/hl set Enter edit path q quit"
|
set -l hint " ↑↓/kj move ←→/hl set Tab page q quit"
|
||||||
printf '%s│%s%s%s│\n' $p $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 ─────────────────────────────────────────────────────
|
# ── Bottom border ─────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -0,0 +1,184 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
# __config_settings_draw_value <cur_row> <page>
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
# Renders a config-settings value page (Sponge or Paths) as exactly 16
|
||||||
|
# lines, matching the box geometry of the opinionated toggle page so the
|
||||||
|
# caller's wrap-aware erase (panel_h=16) is unchanged. Each row shows a
|
||||||
|
# label, a badge, and the variable's current value (or its default hint).
|
||||||
|
# Toggle-type rows (the two sponge booleans) reuse the ON/OFF/DEFAULT badge;
|
||||||
|
# value rows (path/int/list/string) show a type badge and the live value.
|
||||||
|
#
|
||||||
|
# Page width follows the same $COLUMNS tiers as the toggle page for a
|
||||||
|
# consistent look; exact width is not required for the erase (the erase
|
||||||
|
# over-clears to end of screen using the 78-col worst case).
|
||||||
|
#
|
||||||
|
# ARGUMENTS
|
||||||
|
# cur_row 0-based highlighted row within the page
|
||||||
|
# page "sponge" or "paths"
|
||||||
|
#
|
||||||
|
# RETURNS
|
||||||
|
# 0 Always
|
||||||
|
#
|
||||||
|
# EXAMPLE
|
||||||
|
# __config_settings_draw_value 0 sponge
|
||||||
|
function __config_settings_draw_value
|
||||||
|
set -l cur_row $argv[1]
|
||||||
|
set -l page $argv[2]
|
||||||
|
# Inline-edit state: when argv[3] is "edit", the cur_row field renders the
|
||||||
|
# live input buffer (argv[4]) with a caret instead of its stored value.
|
||||||
|
set -l edit_mode $argv[3]
|
||||||
|
set -l edit_buf $argv[4]
|
||||||
|
|
||||||
|
set -l c_ok (set_color green)
|
||||||
|
set -l c_err (set_color red)
|
||||||
|
set -l c_dim (set_color brblack)
|
||||||
|
set -l c_sel (set_color --bold magenta)
|
||||||
|
set -l c_head (set_color --bold cyan)
|
||||||
|
set -l c_reset (set_color normal)
|
||||||
|
|
||||||
|
# ── Page row metadata (parallel lists) ────────────────────────────────
|
||||||
|
set -l title
|
||||||
|
set -l vars
|
||||||
|
set -l labels
|
||||||
|
set -l types
|
||||||
|
set -l hints # default hint shown when unset
|
||||||
|
set -l active_idx
|
||||||
|
if test $page = sponge
|
||||||
|
set title "Sponge Settings"
|
||||||
|
set active_idx 2
|
||||||
|
set vars sponge_delay sponge_purge_only_on_exit sponge_allow_previously_successful sponge_successful_exit_codes __fish_sponge_extra_sensitive
|
||||||
|
set labels Delay "Purge@exit" "Allow prev" "OK codes" "Extra secret"
|
||||||
|
set types int bool bool list list
|
||||||
|
set hints 2 false true 0 "(none)"
|
||||||
|
else
|
||||||
|
set title "Path Settings"
|
||||||
|
set active_idx 3
|
||||||
|
set vars __fish_scrollback_history_dir __fish_scrollback_history_max_files __fish_user_dots_path
|
||||||
|
set labels "Log dir" "Log max" "Dots path"
|
||||||
|
set types path int path
|
||||||
|
set hints "~/.terminal_history" 100 "(default)"
|
||||||
|
end
|
||||||
|
set -l nrows (count $vars)
|
||||||
|
|
||||||
|
# ── Width tier (same thresholds as the toggle page) ───────────────────
|
||||||
|
set -l iw 50
|
||||||
|
if test "$COLUMNS" -ge 90
|
||||||
|
set iw 76
|
||||||
|
else if test "$COLUMNS" -ge 86
|
||||||
|
set iw 72
|
||||||
|
else if test "$COLUMNS" -ge 82
|
||||||
|
set iw 68
|
||||||
|
end
|
||||||
|
set -l HBR (string repeat -n $iw '─')
|
||||||
|
set -l p (string repeat -n (math --scale=0 "max(0, ($COLUMNS - ($iw + 2)) / 2)") ' ')
|
||||||
|
|
||||||
|
# ── Line 1: top border with title ─────────────────────────────────────
|
||||||
|
set -l title_dashes (math $iw - (string length -- $title) - 3)
|
||||||
|
printf '%s┌─%s %s %s┐\n' \
|
||||||
|
$p $c_head "$title$c_reset" (string repeat -n $title_dashes '─')
|
||||||
|
|
||||||
|
# ── Line 2: page-tab header ───────────────────────────────────────────
|
||||||
|
printf '%s│%s│\n' $p (__config_settings_pagetab $active_idx $iw)
|
||||||
|
|
||||||
|
# ── Line 3: divider ───────────────────────────────────────────────────
|
||||||
|
printf '%s│%s│\n' $p $HBR
|
||||||
|
|
||||||
|
# ── Value rows ────────────────────────────────────────────────────────
|
||||||
|
for i in (seq 0 (math $nrows - 1))
|
||||||
|
set -l idx (math $i + 1)
|
||||||
|
set -l var $vars[$idx]
|
||||||
|
set -l label $labels[$idx]
|
||||||
|
set -l type $types[$idx]
|
||||||
|
set -l hint $hints[$idx]
|
||||||
|
|
||||||
|
# Badge (7 visible cols) + value field
|
||||||
|
set -l badge
|
||||||
|
set -l field
|
||||||
|
if test $type = bool
|
||||||
|
# Booleans store true/false (sponge convention); unset = DEFAULT.
|
||||||
|
set -l val (__config_settings_get_raw $var)
|
||||||
|
switch $val
|
||||||
|
case true
|
||||||
|
set badge "$c_ok"" ON$c_reset"
|
||||||
|
case false
|
||||||
|
set badge "$c_err""OFF $c_reset"
|
||||||
|
case '*'
|
||||||
|
set badge "$c_dim""DEFAULT$c_reset"
|
||||||
|
end
|
||||||
|
set field "default: $hint"
|
||||||
|
else
|
||||||
|
set -l raw (__config_settings_get_raw $var)
|
||||||
|
if test "$raw" = DEFAULT
|
||||||
|
set badge "$c_dim""DEFAULT$c_reset"
|
||||||
|
set field "$hint"
|
||||||
|
else
|
||||||
|
switch $type
|
||||||
|
case path
|
||||||
|
set badge "$c_ok"" PATH $c_reset"
|
||||||
|
case int
|
||||||
|
set badge "$c_ok"" INT $c_reset"
|
||||||
|
case list
|
||||||
|
set badge "$c_ok"" LIST $c_reset"
|
||||||
|
case '*'
|
||||||
|
set badge "$c_ok"" STR $c_reset"
|
||||||
|
end
|
||||||
|
set field "$raw"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Inline edit: render the active row's field as the live buffer with a
|
||||||
|
# block caret, tail-anchored so the caret stays visible as text grows.
|
||||||
|
if test "$edit_mode" = edit -a $i -eq $cur_row
|
||||||
|
set -l fw (math $iw - 33)
|
||||||
|
set -l avail (math $fw - 1)
|
||||||
|
set -l shown "$edit_buf"
|
||||||
|
set -l blen (string length -- "$edit_buf")
|
||||||
|
if test $blen -gt $avail
|
||||||
|
set shown (string sub -s (math $blen - $avail + 1) -- "$edit_buf")
|
||||||
|
end
|
||||||
|
set badge "$c_head"" EDIT $c_reset"
|
||||||
|
set field "$shown"(set_color --reverse)" "(set_color normal)
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l curs " "
|
||||||
|
if test $i -eq $cur_row
|
||||||
|
set curs "$c_sel▶$c_reset "
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l fw (math $iw - 33)
|
||||||
|
set -l lpad (string pad -r -w 12 -- $label)
|
||||||
|
# The edit field is already length-constrained and contains a reverse
|
||||||
|
# caret; running it through `string shorten` miscounts the escapes, so
|
||||||
|
# pad it directly. Non-edit fields still shorten to add an ellipsis.
|
||||||
|
set -l fpad
|
||||||
|
if test "$edit_mode" = edit -a $i -eq $cur_row
|
||||||
|
set fpad (string pad -r -w $fw -- "$field")
|
||||||
|
else
|
||||||
|
set fpad (string pad -r -w $fw -- (string shorten -m $fw -- "$field"))
|
||||||
|
end
|
||||||
|
printf '%s│ %s%s [ %s ] %s │\n' $p $curs $lpad $badge $fpad
|
||||||
|
end
|
||||||
|
|
||||||
|
# ── Pad blank rows so chrome(6) + nrows + blanks = 16 ─────────────────
|
||||||
|
set -l blanks (math 10 - $nrows)
|
||||||
|
for i in (seq 1 $blanks)
|
||||||
|
printf '%s│%s│\n' $p (string repeat -n $iw ' ')
|
||||||
|
end
|
||||||
|
|
||||||
|
# ── Bottom divider ────────────────────────────────────────────────────
|
||||||
|
printf '%s│%s│\n' $p $HBR
|
||||||
|
|
||||||
|
# ── Hint line (changes while editing) ─────────────────────────────────
|
||||||
|
set -l hint_line " ↑↓ move Enter edit ←/h clear Tab page q quit"
|
||||||
|
if test "$edit_mode" = edit
|
||||||
|
set hint_line " type value Enter save Esc cancel ⌫ delete"
|
||||||
|
end
|
||||||
|
printf '%s│%s%s%s│\n' $p $c_dim (string pad -r -w $iw -- $hint_line) $c_reset
|
||||||
|
|
||||||
|
# ── Bottom border ─────────────────────────────────────────────────────
|
||||||
|
printf '%s└%s┘\n' $p $HBR
|
||||||
|
end
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
# __config_settings_get_raw <varname>
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
# Prints the current value of a universal variable for display in the
|
||||||
|
# config-settings value pages. List variables are printed space-joined.
|
||||||
|
# Prints "DEFAULT" when the variable is unset in every scope.
|
||||||
|
#
|
||||||
|
# ARGUMENTS
|
||||||
|
# varname Variable name without the $ prefix
|
||||||
|
#
|
||||||
|
# RETURNS
|
||||||
|
# 0 Always; prints the value or "DEFAULT" to stdout
|
||||||
|
#
|
||||||
|
# EXAMPLE
|
||||||
|
# set v (__config_settings_get_raw sponge_delay) # "2" or "DEFAULT"
|
||||||
|
function __config_settings_get_raw
|
||||||
|
set -l varname $argv[1]
|
||||||
|
if set -q $varname
|
||||||
|
string join ' ' -- $$varname
|
||||||
|
else
|
||||||
|
echo DEFAULT
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
# __config_settings_pagetab <active_idx> <iw>
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
# Renders the four-page tab strip used as the header line of every
|
||||||
|
# config-settings page. Pages: 0 Universal, 1 Session, 2 Sponge, 3 Paths.
|
||||||
|
# The active page is marked with a filled bullet and bold text; the others
|
||||||
|
# with a hollow bullet. The returned string is padded to exactly <iw>
|
||||||
|
# printable columns (the caller adds the │ │ border and center offset).
|
||||||
|
#
|
||||||
|
# ARGUMENTS
|
||||||
|
# active_idx 0–3, the active page index
|
||||||
|
# iw inner width in columns to pad the strip to
|
||||||
|
#
|
||||||
|
# RETURNS
|
||||||
|
# 0 Always; prints the tab strip (no trailing newline beyond printf's)
|
||||||
|
#
|
||||||
|
# EXAMPLE
|
||||||
|
# set strip (__config_settings_pagetab 2 76)
|
||||||
|
function __config_settings_pagetab
|
||||||
|
set -l active $argv[1]
|
||||||
|
set -l iw $argv[2]
|
||||||
|
|
||||||
|
set -l c_hi (set_color --bold white)
|
||||||
|
set -l c_reset (set_color normal)
|
||||||
|
set -l names Universal Session Sponge Paths
|
||||||
|
|
||||||
|
set -l strip ' '
|
||||||
|
for i in (seq 0 3)
|
||||||
|
set -l idx (math $i + 1)
|
||||||
|
if test $i -eq $active
|
||||||
|
set strip "$strip$c_hi●$names[$idx]$c_reset "
|
||||||
|
else
|
||||||
|
set strip "$strip○$names[$idx] "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# string pad is width-aware: color escapes count as 0 columns, the bullets
|
||||||
|
# and letters as their printable width.
|
||||||
|
string pad -r -w $iw -- $strip
|
||||||
|
end
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
# RETURNS
|
# RETURNS
|
||||||
# 0 A key was read; one of these tokens is printed to stdout:
|
# 0 A key was read; one of these tokens is printed to stdout:
|
||||||
# up down left right arrow keys
|
# up down left right arrow keys
|
||||||
# space tab enter escape
|
# space tab backtab enter escape backspace
|
||||||
# quit Ctrl-C (byte 3) in raw mode
|
# quit Ctrl-C (byte 3) in raw mode
|
||||||
# <char> any other single printable character
|
# <char> any other single printable character
|
||||||
# "" nothing decodable was read
|
# "" nothing decodable was read
|
||||||
@@ -64,6 +64,8 @@ function __config_settings_read_key
|
|||||||
echo right
|
echo right
|
||||||
case '27 91 68'
|
case '27 91 68'
|
||||||
echo left
|
echo left
|
||||||
|
case '27 91 90'
|
||||||
|
echo backtab
|
||||||
case 27
|
case 27
|
||||||
echo escape
|
echo escape
|
||||||
case 9
|
case 9
|
||||||
@@ -72,6 +74,8 @@ function __config_settings_read_key
|
|||||||
echo space
|
echo space
|
||||||
case 10 13
|
case 10 13
|
||||||
echo enter
|
echo enter
|
||||||
|
case 8 127
|
||||||
|
echo backspace
|
||||||
case 3
|
case 3
|
||||||
echo quit
|
echo quit
|
||||||
case ''
|
case ''
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
# __config_settings_set_value <varname> <type> <value>
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
# Sets a universal config variable from a config-settings value page,
|
||||||
|
# immediately and persistently. An empty <value> erases the variable so the
|
||||||
|
# built-in default takes over. List types split <value> on whitespace; all
|
||||||
|
# other types store it as a single value. When <varname> is a scrollback
|
||||||
|
# variable, the exported SCROLLBACK_HISTORY_* mirror is re-derived so the
|
||||||
|
# POSIX wrappers in the live session see the change without a re-login.
|
||||||
|
#
|
||||||
|
# ARGUMENTS
|
||||||
|
# varname Variable name without the $ prefix
|
||||||
|
# type "list" (whitespace-split) or any other tag (single value)
|
||||||
|
# value The new value; empty string erases (reset to default)
|
||||||
|
#
|
||||||
|
# RETURNS
|
||||||
|
# 0 Always
|
||||||
|
#
|
||||||
|
# EXAMPLE
|
||||||
|
# __config_settings_set_value sponge_delay int 5
|
||||||
|
# __config_settings_set_value sponge_successful_exit_codes list "0 1 130"
|
||||||
|
# __config_settings_set_value __fish_scrollback_history_dir path ~/logs
|
||||||
|
# __config_settings_set_value __fish_user_dots_path path '' # reset
|
||||||
|
function __config_settings_set_value
|
||||||
|
set -l varname $argv[1]
|
||||||
|
set -l type $argv[2]
|
||||||
|
set -l value $argv[3]
|
||||||
|
|
||||||
|
# stderr suppressed: editing a universal while a global of the same name
|
||||||
|
# shadows it makes interactive fish emit a shadow warning that would
|
||||||
|
# corrupt the in-place panel redraw (see __config_settings_apply).
|
||||||
|
if test -z "$value"
|
||||||
|
set -Ue $varname 2>/dev/null
|
||||||
|
else
|
||||||
|
switch $type
|
||||||
|
case list
|
||||||
|
# Accept commas and/or whitespace as separators: collapse any run
|
||||||
|
# of them to a single space, then split (dropping empties). So
|
||||||
|
# "A,B", "A, B", "A B" and "A B" all yield the same two tokens.
|
||||||
|
set -U -- $varname \
|
||||||
|
(string split -n ' ' -- (string replace -ra '[,\s]+' ' ' -- $value)) 2>/dev/null
|
||||||
|
case '*'
|
||||||
|
# -- (before the name) guards typed input that begins with a dash
|
||||||
|
set -U -- $varname $value 2>/dev/null
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Scrollback export mirror — POSIX wrappers read these from the env.
|
||||||
|
switch $varname
|
||||||
|
case __fish_scrollback_history_dir
|
||||||
|
if set -q __fish_scrollback_history_dir
|
||||||
|
set -gx SCROLLBACK_HISTORY_DIR $__fish_scrollback_history_dir
|
||||||
|
else
|
||||||
|
set -gx SCROLLBACK_HISTORY_DIR "$HOME/.terminal_history"
|
||||||
|
end
|
||||||
|
case __fish_scrollback_history_max_files
|
||||||
|
if set -q __fish_scrollback_history_max_files
|
||||||
|
set -gx SCROLLBACK_HISTORY_MAX_FILES $__fish_scrollback_history_max_files
|
||||||
|
else
|
||||||
|
set -gx SCROLLBACK_HISTORY_MAX_FILES 100
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+182
-85
@@ -5,17 +5,19 @@
|
|||||||
# config-settings [-h | --help]
|
# config-settings [-h | --help]
|
||||||
#
|
#
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
# Opens an interactive full-screen TUI for managing fish config settings,
|
# Opens an interactive full-screen TUI for managing fish config settings
|
||||||
# including the six opinionated component categories (C1–C6) and the master
|
# across four pages:
|
||||||
# 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)
|
# Universal — opinionated-category toggles, persistent (set -U / set -Ue)
|
||||||
# Session — active for the current shell only (set -g / set -eg)
|
# Session — opinionated-category toggles, this shell only (set -g / set -eg)
|
||||||
|
# Sponge — sponge history-scrubbing settings (delay, codes, secrets …)
|
||||||
|
# Paths — scrollback log dir, log max, and user-dots path
|
||||||
#
|
#
|
||||||
# Values are changed directionally with the arrow keys (or vim-style h/l)
|
# Toggle rows use ← / → (or h / l) to step OFF ← DEFAULT → ON.
|
||||||
# along an OFF ← DEFAULT → ON scale, and apply immediately — no confirm
|
# Value rows (Sponge, Paths) use Enter to edit inline; ← / h clears to default.
|
||||||
# step. Always available regardless of __fish_config_opinionated state.
|
# Tab / Shift-Tab cycle forward / backward through pages.
|
||||||
|
# Changes apply immediately — no confirm step. Always available regardless of
|
||||||
|
# __fish_config_opinionated state.
|
||||||
#
|
#
|
||||||
# ARGUMENTS
|
# ARGUMENTS
|
||||||
# -h, --help Print usage and exit
|
# -h, --help Print usage and exit
|
||||||
@@ -45,14 +47,17 @@ function config-settings --description 'Interactive TUI for managing fish config
|
|||||||
echo
|
echo
|
||||||
echo "$c_head""Navigation:$c_reset"
|
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""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← →$c_reset or $c_flag""h l$c_reset Toggle pages: OFF ← DEFAULT → ON"
|
||||||
echo " $c_flag""Tab$c_reset Switch scope (Universal ↔ Session)"
|
echo " $c_flag""Enter$c_reset Edit value (Sponge / Paths pages)"
|
||||||
echo " $c_flag""Enter$c_reset Edit path (on Dots Path row)"
|
echo " $c_flag← / h$c_reset Clear value to default (value rows)"
|
||||||
|
echo " $c_flag""Tab / S-Tab$c_reset Next / previous page"
|
||||||
echo " $c_flag""q$c_reset / $c_flag""Esc$c_reset Exit"
|
echo " $c_flag""q$c_reset / $c_flag""Esc$c_reset Exit"
|
||||||
echo
|
echo
|
||||||
echo "$c_head""Scopes:$c_reset"
|
echo "$c_head""Pages:$c_reset"
|
||||||
echo " $c_flag""Universal$c_reset Persistent across all sessions ($c_dim""set -U$c_reset)"
|
echo " $c_flag""Universal$c_reset Toggles, persistent ($c_dim""set -U$c_reset)"
|
||||||
echo " $c_flag""Session$c_reset Current session only ($c_dim""set -g$c_reset)"
|
echo " $c_flag""Session$c_reset Toggles, this shell ($c_dim""set -g$c_reset)"
|
||||||
|
echo " $c_flag""Sponge$c_reset sponge history-scrubbing settings"
|
||||||
|
echo " $c_flag""Paths$c_reset scrollback & user-dots paths"
|
||||||
return 0
|
return 0
|
||||||
case '*'
|
case '*'
|
||||||
echo "$c_err""Unknown option: $arg$c_reset" >&2
|
echo "$c_err""Unknown option: $arg$c_reset" >&2
|
||||||
@@ -61,28 +66,59 @@ function config-settings --description 'Interactive TUI for managing fish config
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# ── Variable list (matches Panel Layout Reference) ────
|
# ── Toggle-page variables (rows 0–6: 6 categories + master) ───────────
|
||||||
set -l vars \
|
set -l toggle_vars \
|
||||||
__fish_config_op_aliases \
|
__fish_config_op_aliases \
|
||||||
__fish_config_op_autoexec \
|
__fish_config_op_autoexec \
|
||||||
__fish_config_op_overrides \
|
__fish_config_op_overrides \
|
||||||
__fish_config_op_integrations \
|
__fish_config_op_integrations \
|
||||||
__fish_config_op_logging \
|
__fish_config_op_logging \
|
||||||
__fish_config_op_greeting \
|
__fish_config_op_greeting \
|
||||||
__fish_config_opinionated \
|
__fish_config_opinionated
|
||||||
__fish_user_dots_path
|
|
||||||
|
|
||||||
set -l cur_row 0 # 0–7
|
# ── Value-page row metadata (parallel: var / type) ────────────────────
|
||||||
set -l cur_scope universal # or "session"
|
set -l sponge_vars sponge_delay sponge_purge_only_on_exit sponge_allow_previously_successful sponge_successful_exit_codes __fish_sponge_extra_sensitive
|
||||||
set -l panel_h 16 # total panel lines (all width tiers are 16 lines)
|
set -l sponge_types int bool bool list list
|
||||||
set -l last_cols $COLUMNS # COLUMNS at the time of the last draw
|
set -l sponge_labels Delay "Purge@exit" "Allow prev" "OK codes" "Extra secret"
|
||||||
|
set -l paths_vars __fish_scrollback_history_dir __fish_scrollback_history_max_files __fish_user_dots_path
|
||||||
|
set -l paths_types path int path
|
||||||
|
set -l paths_labels "Log dir" "Log max" "Dots path"
|
||||||
|
|
||||||
|
# Reset/blank-edit target for each value row. A non-empty entry is written
|
||||||
|
# verbatim (sponge reads sponge_delay / sponge_successful_exit_codes with no
|
||||||
|
# fallback, so they must never be left unset); an empty entry erases the var
|
||||||
|
# so its own built-in default applies (scrollback/dots paths and the
|
||||||
|
# extra-sensitive list all tolerate being unset). Bool rows are not reset
|
||||||
|
# through this path — they are a 2-state true/false with no unset state.
|
||||||
|
set -l sponge_defaults 2 '' '' 0 ''
|
||||||
|
set -l paths_defaults '' '' ''
|
||||||
|
|
||||||
|
# Rows per page index 0..3
|
||||||
|
set -l page_rows 7 7 5 3
|
||||||
|
|
||||||
|
set -l cur_page 0 # 0=Universal 1=Session 2=Sponge 3=Paths
|
||||||
|
set -l cur_row 0
|
||||||
|
set -l panel_h 16
|
||||||
|
set -l last_cols $COLUMNS
|
||||||
|
|
||||||
# ── Terminal setup ────────────────────────────────────
|
# ── Terminal setup ────────────────────────────────────
|
||||||
printf '\e[?25l' # hide cursor
|
printf '\e[?25l' # hide cursor
|
||||||
trap 'printf "\e[?25h"; set -g __config_settings_exit 1' INT
|
trap 'printf "\e[?25h"; set -g __config_settings_exit 1' INT
|
||||||
|
|
||||||
# ── Initial draw ──────────────────────────────────────
|
# ── Draw dispatch (page 0/1 = toggle table; 2/3 = value page) ─────────
|
||||||
__config_settings_draw $cur_row $cur_scope $vars
|
function __cs_dispatch_draw --no-scope-shadowing
|
||||||
|
switch $cur_page
|
||||||
|
case 0
|
||||||
|
__config_settings_draw $cur_row universal $toggle_vars
|
||||||
|
case 1
|
||||||
|
__config_settings_draw $cur_row session $toggle_vars
|
||||||
|
case 2
|
||||||
|
__config_settings_draw_value $cur_row sponge
|
||||||
|
case 3
|
||||||
|
__config_settings_draw_value $cur_row paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
__cs_dispatch_draw
|
||||||
|
|
||||||
# ── Event loop ────────────────────────────────────────
|
# ── Event loop ────────────────────────────────────────
|
||||||
# __config_settings_read_key reads a single keypress from /dev/tty in raw
|
# __config_settings_read_key reads a single keypress from /dev/tty in raw
|
||||||
@@ -106,71 +142,131 @@ function config-settings --description 'Interactive TUI for managing fish config
|
|||||||
case up k
|
case up k
|
||||||
set cur_row (math "max(0, $cur_row - 1)")
|
set cur_row (math "max(0, $cur_row - 1)")
|
||||||
case down j
|
case down j
|
||||||
set cur_row (math "min(7, $cur_row + 1)")
|
# Hoist the page index: fish cannot expand a command-substitution
|
||||||
case tab # Tab — switch scope
|
# index inside a quoted math string.
|
||||||
if test $cur_scope = universal
|
set -l pidx (math $cur_page + 1)
|
||||||
set cur_scope session
|
set cur_row (math "min($page_rows[$pidx] - 1, $cur_row + 1)")
|
||||||
|
case tab
|
||||||
|
set cur_page (math "($cur_page + 1) % 4")
|
||||||
|
set cur_row 0
|
||||||
|
case backtab
|
||||||
|
set cur_page (math "($cur_page + 3) % 4")
|
||||||
|
set cur_row 0
|
||||||
|
case right l
|
||||||
|
if test $cur_page -le 1
|
||||||
|
# Toggle page: step toward ON
|
||||||
|
set -l scope universal
|
||||||
|
test $cur_page -eq 1; and set scope session
|
||||||
|
set -l varname $toggle_vars[(math $cur_row + 1)]
|
||||||
|
set -l cur_val (__config_settings_get_val $varname $scope)
|
||||||
|
set -l next_val on
|
||||||
|
test "$cur_val" = off; and set next_val DEFAULT
|
||||||
|
__config_settings_apply $varname $scope $next_val
|
||||||
|
else if test $cur_page -eq 2
|
||||||
|
# Sponge bool rows are 2-state (true/false) with no unset
|
||||||
|
# state — sponge reads them with no fallback. → sets true.
|
||||||
|
set -l ridx (math $cur_row + 1)
|
||||||
|
if test "$sponge_types[$ridx]" = bool
|
||||||
|
set -U $sponge_vars[$ridx] true 2>/dev/null
|
||||||
|
end
|
||||||
|
end
|
||||||
|
case left h
|
||||||
|
if test $cur_page -le 1
|
||||||
|
set -l scope universal
|
||||||
|
test $cur_page -eq 1; and set scope session
|
||||||
|
set -l varname $toggle_vars[(math $cur_row + 1)]
|
||||||
|
set -l cur_val (__config_settings_get_val $varname $scope)
|
||||||
|
set -l next_val off
|
||||||
|
test "$cur_val" = on; and set next_val DEFAULT
|
||||||
|
__config_settings_apply $varname $scope $next_val
|
||||||
else
|
else
|
||||||
set cur_scope universal
|
# Value pages: bool rows set false; other value rows reset to
|
||||||
|
# their default (a literal value, or erase when the var
|
||||||
|
# tolerates being unset — see sponge_defaults/paths_defaults).
|
||||||
|
set -l v_vars $sponge_vars
|
||||||
|
set -l v_types $sponge_types
|
||||||
|
set -l v_defaults $sponge_defaults
|
||||||
|
if test $cur_page -eq 3
|
||||||
|
set v_vars $paths_vars
|
||||||
|
set v_types $paths_types
|
||||||
|
set v_defaults $paths_defaults
|
||||||
|
end
|
||||||
|
set -l ridx (math $cur_row + 1)
|
||||||
|
set -l varname $v_vars[$ridx]
|
||||||
|
set -l vtype $v_types[$ridx]
|
||||||
|
if test "$vtype" = bool
|
||||||
|
set -U $varname false 2>/dev/null
|
||||||
|
else
|
||||||
|
__config_settings_set_value $varname $vtype "$v_defaults[$ridx]"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
case enter
|
case enter
|
||||||
if test $cur_row -eq 7
|
if test $cur_page -ge 2
|
||||||
# Erase panel (wrap-aware, same formula as cleanup)
|
set -l v_vars $sponge_vars
|
||||||
set -l prev_max_lw (math --scale=0 "($last_cols + 78) / 2")
|
set -l v_types $sponge_types
|
||||||
set -l erase_h (math --scale=0 "$panel_h * max(1, ceil($prev_max_lw / $COLUMNS))")
|
set -l v_defaults $sponge_defaults
|
||||||
printf '\e[%dA\e[J' $erase_h
|
if test $cur_page -eq 3
|
||||||
printf '\e[?25h' # restore cursor
|
set v_vars $paths_vars
|
||||||
|
set v_types $paths_types
|
||||||
printf 'User Dots Path (leave blank to reset to default): '
|
set v_defaults $paths_defaults
|
||||||
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
|
end
|
||||||
|
set -l ridx (math $cur_row + 1)
|
||||||
|
set -l varname $v_vars[$ridx]
|
||||||
|
set -l vtype $v_types[$ridx]
|
||||||
|
# Only path/int/list rows are editable; bool rows toggle with ←/→.
|
||||||
|
if test "$vtype" != toggle -a "$vtype" != bool
|
||||||
|
# Inline editor: edit in-place in the row's value field
|
||||||
|
# using the raw key reader — no fish `read` / `read>`
|
||||||
|
# prompt, and the panel cleans itself up on exit. The
|
||||||
|
# buffer is pre-filled with the current value; clearing it
|
||||||
|
# and pressing Enter reverts to the row's default.
|
||||||
|
set -l page sponge
|
||||||
|
test $cur_page -eq 3; and set page paths
|
||||||
|
set -l buf (__config_settings_get_raw $varname)
|
||||||
|
test "$buf" = DEFAULT; and set buf ""
|
||||||
|
set -l committed 0
|
||||||
|
while true
|
||||||
|
set -l pml (math --scale=0 "($last_cols + 78) / 2")
|
||||||
|
set -l eh (math --scale=0 "$panel_h * max(1, ceil($pml / $COLUMNS))")
|
||||||
|
printf '\e[%dA\e[J' $eh
|
||||||
|
set last_cols $COLUMNS
|
||||||
|
__config_settings_draw_value $cur_row $page edit "$buf"
|
||||||
|
|
||||||
printf '\e[?25l' # hide cursor
|
set -l ek (__config_settings_read_key)
|
||||||
set last_cols $COLUMNS
|
or break
|
||||||
__config_settings_draw $cur_row $cur_scope $vars
|
switch $ek
|
||||||
set did_redraw 1
|
case enter
|
||||||
end
|
set committed 1
|
||||||
case right l # → / l — step toward ON (clamped, no wrap)
|
break
|
||||||
if test $cur_row -eq 7
|
case escape
|
||||||
# no-op for path var; use Enter to set
|
break
|
||||||
else
|
case backspace
|
||||||
set -l varname $vars[(math $cur_row + 1)]
|
set buf (string sub -s 1 -e -1 -- "$buf")
|
||||||
set -l cur_val (__config_settings_get_val $varname $cur_scope)
|
case space
|
||||||
|
set buf "$buf "
|
||||||
set -l next_val on
|
case up down left right tab backtab quit ''
|
||||||
switch $cur_val
|
# ignored while editing
|
||||||
case off
|
case '*'
|
||||||
set next_val DEFAULT
|
set buf "$buf$ek"
|
||||||
case on
|
end
|
||||||
set next_val on
|
end
|
||||||
case '*'
|
if test $committed -eq 1
|
||||||
set next_val on
|
# Empty buffer reverts to the row default (a value, or
|
||||||
|
# erase when the var tolerates being unset).
|
||||||
|
if test -n "$buf"
|
||||||
|
__config_settings_set_value $varname $vtype "$buf"
|
||||||
|
else
|
||||||
|
__config_settings_set_value $varname $vtype "$v_defaults[$ridx]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Redraw the normal panel in place of the editor.
|
||||||
|
set -l pml (math --scale=0 "($last_cols + 78) / 2")
|
||||||
|
set -l eh (math --scale=0 "$panel_h * max(1, ceil($pml / $COLUMNS))")
|
||||||
|
printf '\e[%dA\e[J' $eh
|
||||||
|
set last_cols $COLUMNS
|
||||||
|
__cs_dispatch_draw
|
||||||
|
set did_redraw 1
|
||||||
end
|
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
|
end
|
||||||
case q Q quit escape
|
case q Q quit escape
|
||||||
break
|
break
|
||||||
@@ -194,7 +290,7 @@ function config-settings --description 'Interactive TUI for managing fish config
|
|||||||
set -l erase_h (math --scale=0 "$panel_h * max(1, ceil($prev_max_lw / $COLUMNS))")
|
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[%dA\e[J' $erase_h
|
||||||
set last_cols $COLUMNS
|
set last_cols $COLUMNS
|
||||||
__config_settings_draw $cur_row $cur_scope $vars
|
__cs_dispatch_draw
|
||||||
end
|
end
|
||||||
|
|
||||||
# ── Cleanup ───────────────────────────────────────────
|
# ── Cleanup ───────────────────────────────────────────
|
||||||
@@ -203,4 +299,5 @@ function config-settings --description 'Interactive TUI for managing fish config
|
|||||||
set -l erase_h (math --scale=0 "$panel_h * max(1, ceil($prev_max_lw / $COLUMNS))")
|
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[%dA\e[J' $erase_h # erase the panel (wrap-aware)
|
||||||
printf '\e[?25h' # restore cursor
|
printf '\e[?25h' # restore cursor
|
||||||
|
functions --erase __cs_dispatch_draw
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user