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).
57 lines
2.8 KiB
Fish
Executable File
57 lines
2.8 KiB
Fish
Executable File
#!/usr/bin/env fish
|
|
# Copyright (C) 2026 Rootiest
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
#
|
|
# Gate for the curses config-settings front-end (scripts/config-settings-tui.py).
|
|
#
|
|
# Runs isolated (no `# MODE:` marker). Three things are checked here:
|
|
#
|
|
# 1. python3 can import `curses`. On Arch, Fedora and a full Debian/Ubuntu
|
|
# python3 this is stdlib and always true, but python3-minimal alone does
|
|
# not carry _curses -- the one portability claim config-settings makes,
|
|
# and the reason the function checks the import rather than just `type -q`.
|
|
# 2. The TUI's own --self-test passes. That covers the state-dump parser,
|
|
# variable-name derivation, toggle cycling, the sub-category-aware filter,
|
|
# fish quoting and command emission, with no TTY.
|
|
# 3. config-settings still degrades cleanly with no terminal, rather than
|
|
# leaving a half-initialised curses screen behind.
|
|
#
|
|
# The drawing code is deliberately NOT golden-tested, and the golden harness
|
|
# the ANSI renderer needed is gone. That is the point of the rewrite: curses
|
|
# owns the cell arithmetic, so there is no hand-tuned width/pad/dash maths left
|
|
# to pin down. The seam that does need pinning -- dump in, fish script out --
|
|
# is covered here and, for session scope, in tests/test-session.fish.
|
|
|
|
source (dirname (status filename))/lib.fish
|
|
|
|
# Isolated suites run under `fish --no-config`, which autoloads nothing from
|
|
# this repo. The launcher cases below call config-settings for real, so put the
|
|
# repo's functions on the autoload path -- and only that, so nothing in conf.d
|
|
# runs and the guard variables stay unset.
|
|
set -p fish_function_path $repo_root/functions
|
|
|
|
set -l tui $repo_root/scripts/config-settings-tui.py
|
|
|
|
section "config-settings-tui: prerequisites"
|
|
check "scripts/config-settings-tui.py is executable" true (test -x $tui; and echo true; or echo false)
|
|
check "python3 is available" true (type -q python3; and echo true; or echo false)
|
|
check "python3 ships the curses module" 0 (python3 -c 'import curses' >/dev/null 2>&1; echo $status)
|
|
|
|
section "config-settings-tui: self-test"
|
|
check "--self-test passes" 0 (python3 $tui --self-test >/dev/null 2>&1; echo $status)
|
|
|
|
section "config-settings: launcher"
|
|
check "--help exits 0" 0 (config-settings --help >/dev/null 2>&1; echo $status)
|
|
check "an unknown flag exits 1" 1 (config-settings --nope >/dev/null 2>&1; echo $status)
|
|
|
|
# stdout is a pipe here, so the isatty guard fires before curses ever starts.
|
|
# Without it the TUI would fail deep inside setupterm and leave the terminal
|
|
# in whatever state it got to.
|
|
function test_no_tty_is_refused_cleanly
|
|
set -l out (config-settings 2>&1 >/dev/null | string collect)
|
|
string match -q '*needs a terminal*' -- $out
|
|
end
|
|
check "no TTY is refused with a message, not a curses crash" true (test_no_tty_is_refused_cleanly; and echo true; or echo false)
|
|
|
|
report
|