config-settings is now a launcher for scripts/config-settings-tui.py, drawn with Python's stdlib curses. The seven fish files that hand-rolled the ANSI renderer are gone, along with the golden harness that had to pin their byte-exact output. The TUI is a child process, so it can neither read the session's global variables nor write them. State goes in as a dump from the new __config_settings_state; the edits come back as a fish script that config-settings sources, which is what lets the Session page's `set -g` land in the caller's shell instead of in a child that is about to exit. Every edit is emitted as a call to __config_settings_apply or __config_settings_set_value, so list splitting, the SCROLLBACK_HISTORY_* export mirror and the shadow-warning suppression all stay in the fish layer that already owned them. The consequence, and the one behaviour change: edits are applied in one batch on exit rather than on each keypress. The status bar shows a pending count. New: `/` filters the current page, and on the Universal and Session pages it reaches into every category's sub-categories, listing hits as "Category › Sub" so a sub-category can be toggled without drilling into its parent first. Also a `?` help overlay, mouse selection, and a drill-down page that leads with the category's own toggle. Gone with the renderer: the four width tiers, the wrap-aware erase arithmetic, the stty/dd/od raw key reader, the panel-height bookkeeping and the hand-written redraw differ. curses owns all of it, and the alt screen plus absolute addressing makes the desync class behind608b022,4210f3b,93fc5e0and3c4f720unreachable. The sub-category taxonomy is NOT duplicated in Python: it travels in the state dump, still sourced from __config_settings_subcats. The category, Sponge and Paths row tables move into Python, consolidating the two copies the fish renderers kept. Dependency: python3 with curses. Stdlib on Arch, Fedora and a full Debian/Ubuntu python3; python3-minimal alone lacks _curses. The launcher checks for both and names what is missing. Called out in the README. Verified: 416/416 assertions, plus a live end-to-end in a sandbox HOME confirming the Universal page writes universal scope only (U1/G0) and the Session page global scope only (U0/G1).
77 lines
3.4 KiB
Fish
77 lines
3.4 KiB
Fish
# Copyright (C) 2026 Rootiest
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
# DEPENDENCIES
|
|
# __config_settings_get_val, __config_settings_get_raw,
|
|
# __config_settings_subcats
|
|
#
|
|
# SYNOPSIS
|
|
# __config_settings_state
|
|
#
|
|
# DESCRIPTION
|
|
# Dumps everything scripts/config-settings-tui.py needs to render the
|
|
# settings TUI: the current value of every opinionated-component,
|
|
# sponge, scrollback and user-dots variable, plus the sub-category
|
|
# taxonomy from __config_settings_subcats.
|
|
#
|
|
# Two record types, separated by RS (0x1e), fields separated by US
|
|
# (0x1f). Both are ASCII control characters, so no value these variables
|
|
# can hold needs escaping on the way through:
|
|
#
|
|
# var<US><scope><US><name><US><value>
|
|
# sub<US><category_var><US><slug><US><label><US><description>
|
|
#
|
|
# Only variables that are actually set are emitted; the TUI renders an
|
|
# absent variable as DEFAULT. That is what keeps the variable list out of
|
|
# this function -- names are discovered with `set --names` and filtered by
|
|
# prefix, so a new sub-category needs no edit here, only in
|
|
# __config_settings_subcats.
|
|
#
|
|
# Toggle variables are dumped once per scope (universal and session), since
|
|
# the TUI edits those scopes independently. Sponge and Paths variables are
|
|
# universal-only and dumped as the value the running shell resolves,
|
|
# space-joined for list variables.
|
|
#
|
|
# EXIT STATUS
|
|
# 0 Always
|
|
#
|
|
# RETURNS
|
|
# The RS/US-separated state dump, printed to stdout
|
|
#
|
|
# EXAMPLE
|
|
# __config_settings_state | string split \x1e
|
|
function __config_settings_state --description 'Dump config-settings state for the curses TUI'
|
|
# ── Variable values ───────────────────────────────────────────────────
|
|
for name in (set --names)
|
|
switch $name
|
|
case '__fish_config_op_registry_*'
|
|
# conf.d data table, not a setting -- shares the op_ prefix.
|
|
continue
|
|
case '__fish_config_op_*' __fish_config_opinionated
|
|
# Toggles: both scopes, independently editable.
|
|
for scope in universal session
|
|
set -l val (__config_settings_get_val $name $scope)
|
|
test "$val" = DEFAULT; and continue
|
|
printf '%s\x1f%s\x1f%s\x1f%s\x1e' var $scope $name $val
|
|
end
|
|
case 'sponge_*' __fish_sponge_extra_sensitive \
|
|
'__fish_scrollback_history_*' __fish_user_dots_path \
|
|
__fish_user_dots_symlink
|
|
# Value rows: universal-only, list variables space-joined.
|
|
set -l val (__config_settings_get_raw $name)
|
|
test "$val" = DEFAULT; and continue
|
|
printf '%s\x1f%s\x1f%s\x1f%s\x1e' var universal $name $val
|
|
end
|
|
end
|
|
|
|
# ── Sub-category taxonomy ─────────────────────────────────────────────
|
|
for cvar in __fish_config_op_aliases __fish_config_op_autoexec \
|
|
__fish_config_op_overrides __fish_config_op_integrations \
|
|
__fish_config_op_logging __fish_config_op_greeting
|
|
for row in (__config_settings_subcats $cvar)
|
|
set -l f (string split -- \t $row)
|
|
printf '%s\x1f%s\x1f%s\x1f%s\x1f%s\x1e' sub $cvar $f[1] $f[2] $f[3]
|
|
end
|
|
end
|
|
end
|