Merge pull request 'feat(config): add sub-category granularity to opinionated components' (#107) from worktree-opinionated-subcategories into main
Generate documentation / build-docs (push) Failing after 43s

This commit was merged in pull request #107.
This commit is contained in:
2026-08-19 01:42:25 +00:00
73 changed files with 1574 additions and 134 deletions
+4 -2
View File
@@ -11,6 +11,8 @@ on:
- "docs/verify-manual.py"
- "docs/site/**"
- "functions/**"
- "conf.d/**"
- "config.fish"
workflow_dispatch:
jobs:
@@ -76,7 +78,7 @@ jobs:
run: |
git config user.name "Gitea Actions"
git config user.email "actions@gitea"
git add docs/fish-config.md docs/fish-config.1
git add docs/fish-config.md docs/fish-config.1 conf.d/__fish_config_op_registry.fish
git diff --cached --quiet && echo "No changes to commit" && exit 0
git commit -m "chore(docs): regenerate manual and man page"
git commit -m "chore(docs): regenerate manual, man page, and component registry"
git push
+8
View File
@@ -320,6 +320,14 @@ set -Ue __fish_config_op_greeting
Command shadows react immediately; bindings, prompt, and abbreviations take effect in new shells. With aliases disabled, `rm` deletes permanently again instead of trashing. See `help config opinionated` for the full component list.
Each category further sub-divides into two to six sub-categories with
their own `__fish_config_op_<category>_<subcategory>` toggles (e.g.
`__fish_config_op_aliases_filesystem`), following the exact same
truthy/falsy/unset cascade one level deeper. Run `config-settings` and
press Enter on a category row to browse and toggle its sub-categories, or
see the [Components Reference](https://fish.rootiest.fyi/08-components-reference/)
for the full sub-category list per category.
---
## Attribution
+146
View File
@@ -0,0 +1,146 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# GENERATED FILE --- do not edit by hand.
# Regenerate with __fish_config_op_registry_rebuild after editing a
# # COMPONENT header, or automatically via docs/build-manual.py.
# Source: docs/generate_component_registry.py
#
# This file must be sourced before any other conf.d/*.fish file that
# calls the opinionated guard. That currently holds only because fish's
# glob-based conf.d loading happens to sort this filename first
# alphabetically among the guard-calling files -- do not rename it
# without preserving that ordering.
set -g __fish_config_op_registry_keys \
"__auto_source_fallback_venv:" \
"__fish_config_sync_logging:" \
"__fish_user_dots_link:" \
"_zellij_dump_log:" \
"abbr:abbr-integrations" \
"abbr:abbr-overrides" \
"agy:" \
"auto-pull:" \
"autopair:" \
"bash:" \
"bash_expands:" \
"cat:" \
"claude:" \
"config:cachyos-strip-aliases" \
"config:cachyos-strip-overrides" \
"config:cachyos-tricks" \
"config:cdpath" \
"config:exit-wiring" \
"config:greeting-stamp" \
"config:pager-editor-gpg" \
"config:path-setup" \
"config:vi-mode" \
"done:" \
"du:" \
"edit:" \
"first_run:first-run-bootstrap" \
"first_run:first-run-greeting" \
"fish_right_prompt:" \
"help:" \
"hist:" \
"key_bindings:" \
"kitty-logging:" \
"kitty-watcher-reminder:" \
"less:" \
"logs:" \
"ls:" \
"mkdir:" \
"mv:" \
"paru-wrapper:paru-autoexec" \
"paru-wrapper:paru-logging" \
"ping:" \
"puffer:" \
"rg:" \
"rm:" \
"smart_exit:exit-plain" \
"smart_exit:logging-guard" \
"split:" \
"spwin:" \
"ssh:" \
"starship:" \
"tab:" \
"theme:" \
"tmux-logging:" \
"top:" \
"tricks:aliases-tricks" \
"tricks:tricks-bang" \
"tricks:tricks-manpager" \
"upgrade:" \
"wakatime:wakatime-autoexec" \
"wakatime:wakatime-hook" \
"yay-wrapper:yay-autoexec" \
"yay-wrapper:yay-logging" \
"yt-dlp:" \
"zoxide:"
set -g __fish_config_op_registry_values \
"autoexec/venv" \
"logging/terminal-capture" \
"autoexec/sync" \
"logging/multiplexer-capture" \
"integrations/terminal-abbrs" \
"overrides/key-bindings" \
"aliases/dev-tools" \
"autoexec/sync" \
"overrides/key-bindings" \
"aliases/shell-tools" \
"overrides/key-bindings" \
"aliases/filesystem" \
"aliases/dev-tools" \
"aliases/filesystem" \
"overrides/key-bindings" \
"overrides/environment" \
"overrides/environment" \
"overrides/key-bindings" \
"greeting/greeting-message" \
"overrides/environment" \
"overrides/environment" \
"overrides/key-bindings" \
"integrations/notifications" \
"aliases/filesystem" \
"aliases/dev-tools" \
"autoexec/plugin-management" \
"greeting/first-run" \
"overrides/prompt" \
"aliases/shell-tools" \
"integrations/history-logs" \
"overrides/key-bindings" \
"logging/terminal-capture" \
"logging/terminal-capture" \
"aliases/shell-tools" \
"integrations/history-logs" \
"aliases/filesystem" \
"aliases/filesystem" \
"aliases/filesystem" \
"autoexec/pkg-wrappers" \
"logging/pkg-logs" \
"aliases/network" \
"overrides/key-bindings" \
"aliases/search" \
"aliases/filesystem" \
"overrides/key-bindings" \
"logging/terminal-capture" \
"integrations/window-mgmt" \
"integrations/window-mgmt" \
"aliases/network" \
"overrides/prompt" \
"integrations/window-mgmt" \
"overrides/prompt" \
"logging/multiplexer-capture" \
"aliases/monitor" \
"aliases/filesystem" \
"overrides/key-bindings" \
"overrides/environment" \
"integrations/pkg-upgrade" \
"autoexec/telemetry" \
"integrations/notifications" \
"autoexec/pkg-wrappers" \
"logging/pkg-logs" \
"aliases/network" \
"aliases/filesystem"
+7 -3
View File
@@ -8,6 +8,10 @@
# This file contains all the abbreviations for the terminal.
# It is sourced by Fish on startup.
# COMPONENT
# site abbr-integrations: integrations/terminal-abbrs
# site abbr-overrides: overrides/key-bindings
# Neovim
# @category Editors
# @desc nvim
@@ -155,7 +159,7 @@ abbr -a ag. agy .
# @desc exit
abbr -a /exit exit
# Window-management abbreviations are opinionated (C4 integrations)
if __fish_config_op_enabled __fish_config_op_integrations
if __fish_config_op_enabled (status basename) abbr-integrations
if test "$TERM" = xterm-kitty
# @category Terminal Windows, Tabs, and Panes
# @desc Close current pane/window
@@ -208,7 +212,7 @@ abbr -a speedtest-fast fast-cli
# Kitty/WezTerm window-management abbreviations are opinionated (C4
# integrations): they assume an active Kitty or WezTerm session.
if __fish_config_op_enabled __fish_config_op_integrations
if __fish_config_op_enabled (status basename) abbr-integrations
# Window Creation (OS Windows)
if test "$TERM" = xterm-kitty
# @category Terminal Windows, Tabs, and Panes
@@ -666,7 +670,7 @@ abbr -a url-open open-url
### History Expansions and Substitutions ###
# Bash-style history expansion is opinionated (C3 overrides), gated atomically
# with conf.d/tricks.fish, conf.d/puffer.fish, and functions/expand_*.fish.
if __fish_config_op_enabled __fish_config_op_overrides
if __fish_config_op_enabled (status basename) abbr-overrides
# @category History Expansion
# @name !^
# @desc Expand to the first argument of the previous command
+4 -1
View File
@@ -14,8 +14,11 @@
# Manage the registry with: auto-pull add / remove / list / status
# C2 guard: when auto-execution is disabled, do not register the handler.
__fish_config_op_enabled __fish_config_op_autoexec; or exit
__fish_config_op_enabled (status basename); or exit
# COMPONENT
# autoexec/sync
#
# SYNOPSIS
# __auto_pull_on_pwd (event handler, --on-variable PWD)
#
+4 -1
View File
@@ -1,8 +1,11 @@
status is-interactive || exit
# COMPONENT
# overrides/key-bindings
# Local modification: opinionated guard (AGENTS.md Task #3). Bracket
# auto-pairing intercepts single-character input, classified as C3 overrides.
__fish_config_op_enabled __fish_config_op_overrides || exit
__fish_config_op_enabled (status basename) || exit
set --global autopair_left "(" "[" "{" '"' "'"
set --global autopair_right ")" "]" "}" '"' "'"
+9 -6
View File
@@ -1,13 +1,16 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# COMPONENT
# overrides/key-bindings
# Provides bash-style history expansion functions for abbreviations.
# These functions are gated by the C3 overrides switch.
# Execute expand_bang_all
function expand_bang_all --description 'Execute expand_bang_all'
# Opinionated guard (C3): no expansion when overrides are disabled.
__fish_config_op_enabled __fish_config_op_overrides; or return 1
__fish_config_op_enabled (status basename); or return 1
set -l token $argv[1]
if test -z "$token"; set token (commandline -t); end
@@ -23,7 +26,7 @@ end
# Execute expand_bang_caret
function expand_bang_caret --description 'Execute expand_bang_caret'
# Opinionated guard (C3): no expansion when overrides are disabled.
__fish_config_op_enabled __fish_config_op_overrides; or return 1
__fish_config_op_enabled (status basename); or return 1
# Split the last history item into a list
set -l tokens (string split -n ' ' -- $history[1])
@@ -36,7 +39,7 @@ end
# Execute expand_bang_minus_n
function expand_bang_minus_n --description 'Execute expand_bang_minus_n'
# Opinionated guard (C3): no expansion when overrides are disabled.
__fish_config_op_enabled __fish_config_op_overrides; or return 1
__fish_config_op_enabled (status basename); or return 1
set -l token $argv[1]
if test -z "$token"; set token (commandline -t); end
@@ -58,7 +61,7 @@ end
# Execute expand_bang_search
function expand_bang_search --description 'Execute expand_bang_search'
# Opinionated guard (C3): no expansion when overrides are disabled.
__fish_config_op_enabled __fish_config_op_overrides; or return 1
__fish_config_op_enabled (status basename); or return 1
set -l token $argv[1]
if test -z "$token"
@@ -84,7 +87,7 @@ end
# Execute expand_bang_string
function expand_bang_string --description 'Execute expand_bang_string'
# Opinionated guard (C3): no expansion when overrides are disabled.
__fish_config_op_enabled __fish_config_op_overrides; or return 1
__fish_config_op_enabled (status basename); or return 1
# Fish 4.x passes the matched token as argv[1]
set -l token $argv[1]
@@ -112,7 +115,7 @@ end
# Execute expand_typo_sub
function expand_typo_sub --description 'Execute expand_typo_sub'
# Opinionated guard (C3): no expansion when overrides are disabled.
__fish_config_op_enabled __fish_config_op_overrides; or return 1
__fish_config_op_enabled (status basename); or return 1
# In newer Fish, the matched token is often passed as $argv[1]
# if the abbr is set up correctly. We'll fallback to commandline just in case.
+4 -1
View File
@@ -19,6 +19,9 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# COMPONENT
# integrations/notifications
if not status is-interactive
exit
@@ -26,7 +29,7 @@ end
# Local modification: opinionated guard (AGENTS.md Task #3). Desktop
# notifications assume a graphical session, classified as C4 integrations.
__fish_config_op_enabled __fish_config_op_integrations; or exit
__fish_config_op_enabled (status basename); or exit
set -g __done_version 1.19.1
+6 -2
View File
@@ -7,6 +7,10 @@
#
# Runs exactly once on the first interactive fish session after install.
# To reset for testing, run: set -Ue __fish_config_first_run_complete
#
# COMPONENT
# site first-run-greeting: greeting/first-run
# site first-run-bootstrap: autoexec/plugin-management
# Exit early in non-interactive shells (scripts, completions, subshells)
if not status is-interactive
@@ -36,7 +40,7 @@ end
# Printing a first-run welcome banner is opinionated (C6 greeting). The
# first-run state variable is already set unconditionally above, so
# disabling the greeting never re-triggers this file.
if __fish_config_op_enabled __fish_config_op_greeting
if __fish_config_op_enabled (status basename) first-run-greeting
echo ""
echo " Welcome to your fish shell configuration!"
echo " Run 'help config' for offline documentation."
@@ -48,7 +52,7 @@ end
# Startup side-effects below (Fisher curl, fisher update, theme apply) are
# opinionated (C2 auto-execution). The first-run state variable is already
# set above either way, so disabling auto-exec never re-triggers this file.
if not __fish_config_op_enabled __fish_config_op_autoexec
if not __fish_config_op_enabled (status basename) first-run-bootstrap
return
end
+4 -1
View File
@@ -5,6 +5,9 @@
# │ help config wrapper │
# ╰──────────────────────────────────────────────────────────╯
#
# COMPONENT
# aliases/shell-tools
#
# SYNOPSIS
# help [topic] [sub-topic...]
# help config [section] [-w|--html] [-m|--man] [-h|--help]
@@ -50,7 +53,7 @@ end
# --- Wrapper Definition ---
function help --wraps help --description "Custom wrapper to intercept 'help config'"
# Opinionated guard (C1): fall back to the native fish help when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
__original_help $argv
return $status
end
+8 -1
View File
@@ -8,6 +8,9 @@
# This file defines custom key bindings for the Fish shell.
# It is sourced by Fish on startup.
# COMPONENT
# overrides/key-bindings
# ────────────────── Bind Prewious Path Head to Ctrl+G ─────────────────
# Bindings to insert the previous path head into the command line
# Behaves like `!$:h` does in bash
@@ -48,7 +51,11 @@ function fish_user_key_bindings
# Custom key chords are opinionated (C3 overrides); skip them entirely
# when overrides are disabled so stock bindings remain untouched.
__fish_config_op_enabled __fish_config_op_overrides; or return
# NOTE: (status basename), not (status current-function) -- this guard
# lives inside fish's own reserved fish_user_key_bindings function, whose
# name is not this file's identity; the registry key is this file's
# bare basename, key_bindings.
__fish_config_op_enabled (status basename); or return
# ───────────────────────────── Set Bindings ─────────────────────────────
#
+5 -1
View File
@@ -1,5 +1,9 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# COMPONENT
# logging/terminal-capture
#
# C5 — Logging & Capture: a non-blocking, per-session reminder shown inside Kitty
# when the fish-config scrollback watcher is not yet set up. It never blocks the
@@ -10,7 +14,7 @@
status is-interactive; or exit
type -q kitty; or exit
set -q KITTY_WINDOW_ID; or exit
__fish_config_op_enabled __fish_config_op_logging; or exit
__fish_config_op_enabled (status basename); or exit
__fish_variable_check __fish_config_kitty_watcher_dismissed; and exit
__kitty_logging_has_watcher; and exit
+6 -2
View File
@@ -6,12 +6,16 @@
# bars are preserved, renders the captured animation to a clean static log
# (via scripts/clean_progress_log.py), and prunes old logs.
# COMPONENT
# site paru-autoexec: autoexec/pkg-wrappers
# site paru-logging: logging/pkg-logs
# Auto-generating a wrapper in ~/.local/bin is opinionated (C2 auto-exec).
# Wrapper generation is also gated by C5 (Logging & Capture).
__fish_config_op_enabled __fish_config_op_autoexec; or return
__fish_config_op_enabled (status basename) paru-autoexec; or return
# C5 — Logging & Capture: remove generated wrapper and skip when logging is off
if not __fish_config_op_enabled __fish_config_op_logging
if not __fish_config_op_enabled (status basename) paru-logging
if test -f "$HOME/.local/bin/paru"
and grep -q "# paru-wrapper-version:" "$HOME/.local/bin/paru" 2>/dev/null
rm -f "$HOME/.local/bin/paru"
+4 -1
View File
@@ -1,9 +1,12 @@
status is-interactive || exit
# COMPONENT
# overrides/key-bindings
# Local modification: opinionated guard (AGENTS.md Task #3). Puffer's key
# intercepts are part of the bang-bang system, gated atomically under C3
# overrides with conf.d/tricks.fish, conf.d/abbr.fish, and expand_*.fish.
__fish_config_op_enabled __fish_config_op_overrides || exit
__fish_config_op_enabled (status basename) || exit
function _puffer_fish_key_bindings --on-variable fish_key_bindings
set -l modes
+5 -1
View File
@@ -1,12 +1,16 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# COMPONENT
# overrides/prompt
#
# Defines fish_prompt only when starship is installed.
# Without starship, fish's built-in prompt already emits OSC 133;A
# on the prompt line itself, so no wrapper is needed.
# Replacing the prompt is opinionated (C3 overrides)
__fish_config_op_enabled __fish_config_op_overrides; or return
__fish_config_op_enabled (status basename); or return
type -q starship; or return
+5 -1
View File
@@ -1,5 +1,9 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# COMPONENT
# overrides/prompt
#
# ╭──────────────────────────────────────────────────────────╮
# │ Fish Theme │
@@ -9,7 +13,7 @@
# Forcing theme colors and $FZF_DEFAULT_OPTS is opinionated (C3 overrides).
# The FZF variable is universal, so clean up our Catppuccin value if it
# lingers from a session where overrides were still enabled.
if not __fish_config_op_enabled __fish_config_op_overrides
if not __fish_config_op_enabled (status basename)
if set -q FZF_DEFAULT_OPTS; and string match -q '*#1E1E2E*' -- "$FZF_DEFAULT_OPTS"
set --erase FZF_DEFAULT_OPTS
end
+5 -1
View File
@@ -1,12 +1,16 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# COMPONENT
# logging/multiplexer-capture
#
# C5 — Logging & Capture: starts a pipe-pane log for the current tmux pane
# when fish launches inside a tmux session. Each fish shell gets its own
# timestamped log file in SCROLLBACK_HISTORY_DIR (default: ~/.terminal_history).
# Naming: tmux_<session>-w<window>-p<pane>_YYYY-MM-DD_HH-MM-SS.log
__fish_config_op_enabled __fish_config_op_logging; or exit
__fish_config_op_enabled (status basename); or exit
status is-interactive; or exit
type -q tmux; or exit
set -q TMUX; or exit
+9 -4
View File
@@ -7,6 +7,11 @@
# │ system aliases, and history/backup utilities │
# ╰──────────────────────────────────────────────────────────╯
# COMPONENT
# site aliases-tricks: aliases/filesystem
# site tricks-manpager: overrides/environment
# site tricks-bang: overrides/key-bindings
## Environment setup
# Apply .profile: use this to put fish compatible .profile stuff in
if test -f ~/.fish_profile
@@ -24,7 +29,7 @@ end
# Format man pages using bat (only if bat is installed)
# Overriding $MANPAGER is opinionated (C3 overrides)
if type -q bat; and __fish_config_op_enabled __fish_config_op_overrides
if type -q bat; and __fish_config_op_enabled (status basename) tricks-manpager
set -gx MANROFFOPT -c
set -gx MANPAGER "sh -c 'col -bx | bat -l man -p'"
end
@@ -37,7 +42,7 @@ set -gx __done_notification_urgency_level low
# Functions needed for !! and !$ https://github.com/oh-my-fish/plugin-bang-bang
# The bang-bang system is opinionated (C3 overrides) and is gated atomically
# here, in conf.d/abbr.fish, conf.d/puffer.fish, and functions/expand_*.fish.
if __fish_config_op_enabled __fish_config_op_overrides
if __fish_config_op_enabled (status basename) tricks-bang
function __history_previous_command
switch (commandline -t)
case "!"
@@ -83,7 +88,7 @@ end
# Fish command history override to show timestamps
# Shadowing the history command is opinionated (C1 aliasing); when disabled,
# the function is never defined and fish's stock history behavior applies.
if __fish_config_op_enabled __fish_config_op_aliases
if __fish_config_op_enabled (status basename) aliases-tricks
function history
builtin history --show-time='%F %T '
end
@@ -123,7 +128,7 @@ alias .....='cd ../../../..'
alias ......='cd ../../../../..'
# Silent flag injection into POSIX tools is opinionated (C1 aliasing)
if __fish_config_op_enabled __fish_config_op_aliases
if __fish_config_op_enabled (status basename) aliases-tricks
# Tools & Core command color overrides
# @category Shell Aliases
# @desc dir --color=auto
+6 -2
View File
@@ -5,11 +5,15 @@
# see: https://github.com/ik11235/wakatime.fish
###
# COMPONENT
# site wakatime-autoexec: autoexec/telemetry
# site wakatime-hook: integrations/notifications
# Local modification: opinionated guard (AGENTS.md Task #3). WakaTime
# reporting is classified under both C2 auto-execution and C4 integrations;
# disabling either category skips registering the hook.
__fish_config_op_enabled __fish_config_op_autoexec; or exit
__fish_config_op_enabled __fish_config_op_integrations; or exit
__fish_config_op_enabled (status basename) wakatime-autoexec; or exit
__fish_config_op_enabled (status basename) wakatime-hook; or exit
function __register_wakatime_fish_before_exec -e fish_postexec
if set -q FISH_WAKATIME_DISABLED
+6 -2
View File
@@ -6,12 +6,16 @@
# bars are preserved, renders the captured animation to a clean static log
# (via scripts/clean_progress_log.py), and prunes old logs.
# COMPONENT
# site yay-autoexec: autoexec/pkg-wrappers
# site yay-logging: logging/pkg-logs
# Auto-generating a wrapper in ~/.local/bin is opinionated (C2 auto-exec).
# Wrapper generation is also gated by C5 (Logging & Capture).
__fish_config_op_enabled __fish_config_op_autoexec; or return
__fish_config_op_enabled (status basename) yay-autoexec; or return
# C5 — Logging & Capture: remove generated wrapper and skip when logging is off
if not __fish_config_op_enabled __fish_config_op_logging
if not __fish_config_op_enabled (status basename) yay-logging
if test -f "$HOME/.local/bin/yay"
and grep -q "# yay-wrapper-version:" "$HOME/.local/bin/yay" 2>/dev/null
rm -f "$HOME/.local/bin/yay"
+4 -1
View File
@@ -3,6 +3,9 @@
# Adapted from icezyclon/zoxide.fish (MIT)
# Heavily customized for Fish 4.x compatibility and performance
# COMPONENT
# aliases/filesystem
if status is-interactive
if type -q zoxide
@@ -65,7 +68,7 @@ if status is-interactive
# Shadowing cd with zoxide is opinionated (C1 aliasing); z and zi
# remain available either way.
if __fish_config_op_enabled __fish_config_op_aliases
if __fish_config_op_enabled (status basename)
alias cd=z
end
+21 -10
View File
@@ -7,7 +7,7 @@
# ───────────────────── Opinionated component guards ─────────────────────
# Opinionated components (AGENTS.md Task #3) are wrapped in
# __fish_config_op_enabled <category> guards throughout this file and conf.d/.
# __fish_config_op_enabled <identity> [<site>] guards throughout this file and conf.d/.
# The helper always evaluates the master switch __fish_config_opinionated
# first (falsy disables everything), then the per-category opt-out variable:
# __fish_config_op_aliases C1 — command shadows / flag injection
@@ -21,12 +21,23 @@
# C5 is the one exception: it defaults to disabled and needs an explicit
# truthy value — set -U __fish_config_op_logging on
# COMPONENT
# site cachyos-tricks: overrides/environment
# site cachyos-strip-aliases: aliases/filesystem
# site cachyos-strip-overrides: overrides/key-bindings
# site pager-editor-gpg: overrides/environment
# site exit-wiring: overrides/key-bindings
# site path-setup: overrides/environment
# site cdpath: overrides/environment
# site vi-mode: overrides/key-bindings
# site greeting-stamp: greeting/greeting-message
# ──────────────────────── Source CachyOS configs ────────────────────────
if test -f /usr/share/cachyos-fish-config/cachyos-config.fish
source /usr/share/cachyos-fish-config/cachyos-config.fish
# Surgically overriding the distro config is opinionated (C3 overrides):
# skip it entirely when overrides are disabled, keeping CachyOS defaults.
if __fish_config_op_enabled __fish_config_op_overrides
if __fish_config_op_enabled (status basename) cachyos-tricks
# Source our tricks over the cachyOS config
test -f "$__fish_config_dir/conf.d/tricks.fish"
and source "$__fish_config_dir/conf.d/tricks.fish"
@@ -41,7 +52,7 @@ if test -f /usr/share/cachyos-fish-config/cachyos-config.fish
# The distro config ships opinionated pieces of its own (it is the origin
# of tricks.fish); strip them when the matching category is disabled so
# the guards hold on CachyOS systems too.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status basename) cachyos-strip-aliases
for _fname in grep fgrep egrep dir vdir wget
functions -q $_fname; and functions --erase $_fname
end
@@ -53,7 +64,7 @@ if test -f /usr/share/cachyos-fish-config/cachyos-config.fish
and source $__fish_data_dir/functions/$_fname.fish
end
end
if not __fish_config_op_enabled __fish_config_op_overrides
if not __fish_config_op_enabled (status basename) cachyos-strip-overrides
for _fname in __history_previous_command __history_previous_command_arguments
functions -q $_fname; and functions --erase $_fname
end
@@ -95,7 +106,7 @@ set -q WORDLIST; or set -gx WORDLIST "$XDG_CONFIG_HOME/hunspell_en_US"
# ─────────────────────────── Pager variables ────────────────────────────
# Overriding $PAGER, $EDITOR, and $GPG_TTY is opinionated (C3 overrides)
if __fish_config_op_enabled __fish_config_op_overrides
if __fish_config_op_enabled (status basename) pager-editor-gpg
if type -q ov
set -gx PAGER ov
else if type -q less
@@ -136,7 +147,7 @@ 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
# Replacing the exit builtin is opinionated (C3 overrides); smart_exit also
# guards itself so a live toggle takes effect without restarting the shell.
if status is-interactive; and __fish_config_op_enabled __fish_config_op_overrides
if status is-interactive; and __fish_config_op_enabled (status basename) exit-wiring
function exit --description 'Safe interactive exit'
# If the smart_exit file exists in our function path, invoke it explicitly
if functions -q smart_exit
@@ -153,7 +164,7 @@ end
# the cargo bin directory is moved to the end of the PATH, which can help avoid conflicts
# with system-installed Rust tools while still allowing user-installed cargo binaries to be found.
# PATH setup is opinionated (C3 overrides)
if __fish_config_op_enabled __fish_config_op_overrides
if __fish_config_op_enabled (status basename) path-setup
fish_add_path $HOME/.local/bin # Standard user-local executables (XDG spec)
fish_add_path $HOME/.local/share/../bin # Alternative/legacy path for local user binaries
fish_add_path $HOME/Applications # User-installed applications and standalone apps
@@ -176,7 +187,7 @@ end
# so if you have a directory named 'myproject' in the current directory,
# running 'cd myproject' will take you there instead of $HOME/projects/myproject.
# CDPATH injection is opinionated (C3 overrides)
if __fish_config_op_enabled __fish_config_op_overrides
if __fish_config_op_enabled (status basename) cdpath
set -gx CDPATH . $HOME/projects $HOME
end
@@ -191,7 +202,7 @@ if status is-interactive
# This is optional but can improve the user experience for those who prefer Vi-style key bindings.
# Global Vi mode is opinionated (C3 overrides); without it fish keeps its
# default Emacs-style bindings.
if __fish_config_op_enabled __fish_config_op_overrides
if __fish_config_op_enabled (status basename) vi-mode
set -g fish_key_bindings fish_vi_key_bindings
end
@@ -251,7 +262,7 @@ if status is-interactive
# function that distro configs set (e.g., CachyOS defines it as fastfetch).
# This runs last inside the interactive block so our empty definition wins
# over whatever cachyos-config.fish or vendor conf.d installed.
if not __fish_config_op_enabled __fish_config_op_greeting
if not __fish_config_op_enabled (status basename) greeting-stamp
function fish_greeting
end
end
+3
View File
@@ -15,6 +15,7 @@ import sys
from pathlib import Path
import manualtools as mt
import generate_component_registry
DOCS = Path(__file__).parent
MANUAL = DOCS / "manual"
@@ -840,6 +841,8 @@ def main() -> int:
if not (args.concat or args.site):
ap.error("nothing to do: pass --concat and/or --site")
generate_component_registry.main()
if args.site:
src = DOCS / "site" / "src"
out = src / "content" / "docs"
+121
View File
@@ -0,0 +1,121 @@
#!/usr/bin/env python3
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Generate the committed opinionated-component registry.
Walks every `# COMPONENT` header in functions/*.fish, conf.d/*.fish, and
config.fish and writes conf.d/__fish_config_op_registry.fish, the fish
data file __fish_config_op_registry_lookup reads at shell startup.
Run manually (via __fish_config_op_registry_rebuild) after editing a
# COMPONENT header, and automatically as a pre-step in build-manual.py
before the manual is built.
"""
import sys
from pathlib import Path
import manualtools as mt
DOCS = Path(__file__).parent
REPO = DOCS.parent
OUTPUT = REPO / "conf.d" / "__fish_config_op_registry.fish"
def collect_components() -> dict[str, list[str]]:
"""Gather every `# COMPONENT` header across the whole repo.
Concatenates raw component lines when the same identity appears in
more than one source (e.g. functions/auto-pull.fish and
conf.d/auto-pull.fish both self-identify as "auto-pull" at runtime,
since the guard can only ever look up the bare status
current-function/basename string) rather than letting one silently
overwrite the other.
"""
out: dict[str, list[str]] = {}
for source in (
mt.parse_components(REPO / "functions"),
mt.parse_components(REPO / "conf.d"),
mt.parse_component_file(REPO / "config.fish"),
):
for identity, lines in source.items():
out.setdefault(identity, []).extend(lines)
return out
def build_registry(components: dict[str, list[str]]) -> tuple[dict[str, list[str]], list[str]]:
"""Turn {identity: [raw COMPONENT lines]} into ({"identity:site": [tags]}, warnings).
A site with both always/on and always/off tagged is a contradiction:
both are stripped and a warning is emitted, but generation continues
-- any other real tag on that same site survives. A site whose
effective tag set is empty after stripping produces no registry entry
at all, which __fish_config_op_enabled already treats as always/on
(fail-open) at guard time -- see spec §4.5.
"""
registry: dict[str, list[str]] = {}
warnings: list[str] = []
for identity, raw_lines in components.items():
by_site: dict[str, list[str]] = {}
for site, tag in mt.parse_component_lines(raw_lines):
by_site.setdefault(site, []).append(tag)
for site, tags in by_site.items():
if "always/on" in tags and "always/off" in tags:
label = identity if not site else f"{identity}:{site}"
warnings.append(
f"{label}: both always/on and always/off tagged; ignoring both"
)
tags = [t for t in tags if t not in ("always/on", "always/off")]
if tags:
registry[f"{identity}:{site}"] = list(dict.fromkeys(tags))
return registry, warnings
def render(registry: dict[str, list[str]]) -> str:
keys = sorted(registry)
lines = [
"# Copyright (C) 2026 Rootiest",
"# SPDX-License-Identifier: AGPL-3.0-or-later",
"#",
"# GENERATED FILE --- do not edit by hand.",
"# Regenerate with __fish_config_op_registry_rebuild after editing a",
"# # COMPONENT header, or automatically via docs/build-manual.py.",
"# Source: docs/generate_component_registry.py",
"#",
"# This file must be sourced before any other conf.d/*.fish file that",
"# calls the opinionated guard. That currently holds only because fish's",
"# glob-based conf.d loading happens to sort this filename first",
"# alphabetically among the guard-calling files -- do not rename it",
"# without preserving that ordering.",
"",
]
if not keys:
lines.append("set -g __fish_config_op_registry_keys")
lines.append("set -g __fish_config_op_registry_values")
return "\n".join(lines) + "\n"
quoted_keys = [f'"{k}"' for k in keys]
lines.append("set -g __fish_config_op_registry_keys \\")
lines += [f" {k} \\" for k in quoted_keys[:-1]] + [f" {quoted_keys[-1]}"]
lines.append("")
values = ['"' + " ".join(registry[k]) + '"' for k in keys]
lines.append("set -g __fish_config_op_registry_values \\")
lines += [f" {v} \\" for v in values[:-1]] + [f" {values[-1]}"]
lines.append("")
return "\n".join(lines) + "\n"
def main() -> int:
components = collect_components()
registry, warnings = build_registry(components)
for w in warnings:
print(f" WARN {w}", file=sys.stderr)
OUTPUT.write_text(render(registry))
print(f"wrote {OUTPUT} ({len(registry)} entries)", file=sys.stderr)
return 0
if __name__ == "__main__":
sys.path.insert(0, str(Path(__file__).parent))
raise SystemExit(main())
+13
View File
@@ -145,6 +145,19 @@ NOTE:
- Disabled integration commands (spwin, tab, split, hist, logs, upgrade) print an error naming the variable that disabled them.
- On CachyOS, the distro fish config's own aliases, history override, and bang-bang bindings are stripped per category as well.
### Sub-categories
Each of the six categories further sub-divides into two to six
sub-categories, each with its own `__fish_config_op_<category>_<subcategory>`
variable (e.g. `__fish_config_op_aliases_filesystem`). These follow the
exact same truthy/falsy/unset cascade one level deeper: an explicit
sub-category value overrides the master switch and the parent category's
setting, and an unset sub-category inherits from its parent category (which
in turn inherits from `__fish_config_opinionated`). Run config-settings and
press Enter on a category row to browse and toggle its sub-categories
interactively. See [Components Reference](/08-components-reference/) for the
full sub-category breakdown of every category.
## Prompt and Theme
@@ -31,3 +31,35 @@ all of these commands.
When C1 is disabled, `rm` uses bare `command rm` with no wrapper — files
are permanently deleted, not trashed. There is no intermediate safety net.
## Sub-categories
`__fish_config_op_aliases` sub-divides into six sub-categories, each with
its own `__fish_config_op_aliases_<slug>` toggle:
## filesystem
`ls`, `cat`, `cd`, `du`, `mkdir`, `rm`, `mv`, and `cd`/zoxide navigation --
the everyday filesystem-inspection and -modification shadows.
## search
`rg`, with its Kitty hyperlink formatting.
## network
`ping`, `ssh`, and `yt-dlp` -- shadows that talk to the network.
## monitor
`top` -> `btop`.
## shell-tools
`bash` (XDG bashrc + `$SHELL` reset), `less` (`$PAGER` fallback chain),
and the `help config` interception.
## dev-tools
`claude` (AGENTS.md/CLAUDE.md auto-linking) and `edit` (multi-editor
launcher), plus `agy`.
@@ -43,3 +43,28 @@ branches, or repos without a remote. The handler fires once per repo entry
(not on every sub-directory `cd`). The registry is machine-local at
`$__fish_user_dots_path/auto-pull.list` (defaults to `~/.config/.user-dots/fish/auto-pull.list`) and is never committed.
## Sub-categories
`__fish_config_op_autoexec` sub-divides into five sub-categories, each
with its own `__fish_config_op_autoexec_<slug>` toggle:
## plugin-management
Fisher bootstrap on first run.
## pkg-wrappers
`paru`/`yay` wrapper generation.
## venv
Automatic Python virtualenv activation.
## telemetry
The WakaTime hook's startup bootstrap.
## sync
Auto-pull background fast-forward, and the user-dots convenience symlink.
@@ -33,3 +33,23 @@ When C3 is disabled, `exit` falls back to `builtin exit` with no scrollback
capture, no Kitty IPC, and no file I/O on exit. The scrollback capture block
is independently controlled by C5 (see below).
## Sub-categories
`__fish_config_op_overrides` sub-divides into three sub-categories, each
with its own `__fish_config_op_overrides_<slug>` toggle:
## key-bindings
Vi mode, autopair, puffer key intercepts, bang-bang history expansion,
and `smart_exit`'s plain-exit path.
## environment
`$PATH`, `$PAGER`/`$EDITOR`/`$GPG_TTY`, and `$CDPATH`.
## prompt
Starship, the right prompt, Catppuccin syntax/prompt colors, and FZF
theming (`$FZF_DEFAULT_OPTS`) -- all driven by the same guard as a single
unit, not independently toggleable from each other.
@@ -22,3 +22,28 @@ Disabled integration commands (`spwin`, `tab`, `split`, `hist`, `logs`, `upgrade
a colored error to stderr naming the variable that disabled them rather than
silently failing.
## Sub-categories
`__fish_config_op_integrations` sub-divides into five sub-categories,
each with its own `__fish_config_op_integrations_<slug>` toggle:
## terminal-abbrs
The Kitty/WezTerm abbreviation set.
## window-mgmt
`spwin`, `tab`, `split`.
## notifications
`done`'s completion notifications, and the WakaTime activity hook.
## history-logs
`hist`, `logs`.
## pkg-upgrade
`upgrade`.
@@ -112,3 +112,22 @@ Note: C3 and C5 compose independently. C3 controls whether the smart_exit
wrapper is active at all; C5 controls only the scrollback-capture block
inside it. With C3 disabled, exit is plain builtin exit regardless of C5.
## Sub-categories
`__fish_config_op_logging` sub-divides into three sub-categories, each
with its own `__fish_config_op_logging_<slug>` toggle (all still opt-in
by default, inherited from C5's own opt-in behavior -- see §3 of the
design spec):
## terminal-capture
Kitty watcher scrollback capture, and `smart_exit`'s logging-guard path.
## multiplexer-capture
tmux `pipe-pane` and zellij `dump-screen` capture.
## pkg-logs
`paru`/`yay` AUR log wrappers.
@@ -13,3 +13,16 @@ When C6 is disabled, no greeting is printed by this config. Any greeting
set by the distro or other configs runs normally — this config simply does
not override it.
## Sub-categories
`__fish_config_op_greeting` sub-divides into two sub-categories, each
with its own `__fish_config_op_greeting_<slug>` toggle:
## first-run
The first-run welcome banner.
## greeting-message
The per-session `fish_greeting` override.
@@ -18,3 +18,18 @@ category variable.
C4 [Integrations](/08-components-reference/04-c4-terminal-and-tool-integration/) — Kitty/Wezterm integrations, starship hooks, fzf theme
C5 [Logging and Capture](/08-components-reference/05-c5-logging-and-capture/) — Session logs, command duration
C6 [Greeting & First-Run UI](/08-components-reference/06-c6-greeting-and-first-run-ui/) — Custom startup banner
Each category further sub-divides into two to six sub-categories (24 in
total) with their own `__fish_config_op_<category>_<subcategory>` toggles
-- see that category's page for its sub-category list.
## Per-function overrides: `C0`/`always`
Every guarded function or file can also carry a reserved `always/on` or
`always/off` tag in its `# COMPONENT` header, independent of every C1-C6
category and sub-category toggle and invisible to `config-settings`. An
`always/off` tag disables that function unconditionally; an `always/on`
tag enables it unconditionally, ignoring the state of every other tagged
sub-category. This is a per-function escape hatch for cases too granular
or too idiosyncratic to justify a taxonomy entry -- edit the header
directly and run `__fish_config_op_registry_rebuild` to apply the change.
+7
View File
@@ -237,6 +237,13 @@ Re-enable everything:
set -Ue __fish_config_opinionated
Each category also has two to six sub-categories (e.g.
`__fish_config_op_aliases_filesystem`) that can be checked, disabled, or
reset the same way — `set -U __fish_config_op_<category>_<subcategory> off`
and `set -Ue __fish_config_op_<category>_<subcategory>` work identically to
the category-level recipes above, just one level more granular. See
[Components Reference](/08-components-reference/) for the full list.
For an interactive alternative to setting these variables by hand, run `config-settings`.
---
+72 -5
View File
@@ -62,6 +62,7 @@ HEADER_LABEL = re.compile(r"^#\s+([A-Z][A-Z ]*[A-Z])\s*$")
FUNC_DEF = re.compile(r"^\s*function\s+(\S+)")
SECTIONS = (
"CATEGORY",
"COMPONENT",
"DEPENDENCIES",
"SYNOPSIS",
"DESCRIPTION",
@@ -109,6 +110,19 @@ def _trailing_blanks(lines: list[str]) -> int:
return n
def _block_identity(path: Path, lines: list[str], end: int, blocks_count: int) -> str:
"""Resolve a header block's associated name.
A file carrying exactly one header is associated with its own stem, so
a `function` nested inside a `type -q` guard still resolves. A file
with several headers walks forward to the next `function` definition.
"""
if blocks_count == 1:
return path.stem
after = (m.group(1) for ln in lines[end:] if (m := FUNC_DEF.match(ln)))
return next(after, path.stem)
def parse_functions(root: Path) -> dict[str, dict[str, list[str]]]:
"""Parse the comment header above every documented public function.
@@ -128,11 +142,7 @@ def parse_functions(root: Path) -> dict[str, dict[str, list[str]]]:
lines = path.read_text(encoding="utf-8").split("\n")
blocks = _header_blocks(lines)
for end, sections in blocks:
if len(blocks) == 1:
name = path.stem
else:
after = (m.group(1) for ln in lines[end:] if (m := FUNC_DEF.match(ln)))
name = next(after, path.stem)
name = _block_identity(path, lines, end, len(blocks))
if name.startswith("_") or "CATEGORY" not in sections:
continue
out[name] = {
@@ -185,6 +195,63 @@ def parse_abbreviations(root: Path) -> dict[str, list[dict]]:
return out
SITE_LINE_RE = re.compile(r"^site\s+(\S+):\s*(\S+)$")
def parse_component_lines(lines: list[str]) -> list[tuple[str, str]]:
"""Parse raw `# COMPONENT` body lines into (site, tag) pairs.
A line of the form `site <slug>: <tag>` scopes <tag> to that site; a
bare `<tag>` line belongs to the default (unnamed) site, keyed "".
Blank lines are skipped.
"""
out: list[tuple[str, str]] = []
for line in lines:
line = line.strip()
if not line:
continue
m = SITE_LINE_RE.match(line)
if m:
out.append((m.group(1), m.group(2)))
else:
out.append(("", line))
return out
def _parse_component_blocks(path: Path) -> dict[str, list[str]]:
"""Parse every `# COMPONENT` header block in one file.
Unlike parse_functions, there is no `# CATEGORY` gate and no
underscore exclusion: component classification applies to every
function/script, public or private, documented in the manual or not
-- the registry needs to see every guarded identity, not just the
ones that appear in the public function reference.
"""
lines = path.read_text(encoding="utf-8").split("\n")
blocks = _header_blocks(lines)
out: dict[str, list[str]] = {}
for end, sections in blocks:
if "COMPONENT" not in sections:
continue
name = _block_identity(path, lines, end, len(blocks))
body = sections["COMPONENT"]
out[name] = body[: len(body) - _trailing_blanks(body)]
return out
def parse_component_file(path: Path) -> dict[str, list[str]]:
"""Parse `# COMPONENT` header block(s) in one specific file (e.g. config.fish)."""
return _parse_component_blocks(path)
def parse_components(root: Path) -> dict[str, list[str]]:
"""Parse `# COMPONENT` header blocks across every `*.fish` file under root."""
out: dict[str, list[str]] = {}
for path in sorted(root.glob("*.fish")):
out.update(_parse_component_blocks(path))
return out
def _sort_key(entry: Path) -> tuple:
"""Order by sidebar.order when present, else by filename. Stable."""
target = entry / "index.md" if entry.is_dir() else entry
+323
View File
@@ -130,6 +130,38 @@ def _parsed_functions() -> dict[str, dict[str, list[str]]]:
return mt.parse_functions(Path(__file__).parent.parent / "functions")
def _parsed_components() -> dict[str, list[str]]:
import generate_component_registry as gcr
return gcr.collect_components()
_C0_TAGS = {"always/on", "always/off"}
_TAXONOMY_FILES = {
"aliases": "01-c1-command-shadows.md",
"autoexec": "02-c2-startup-side-effects.md",
"overrides": "03-c3-key-and-environment-overrides.md",
"integrations": "04-c4-terminal-and-tool-integration.md",
"logging": "05-c5-logging-and-capture.md",
"greeting": "06-c6-greeting-and-first-run-ui.md",
}
def _load_taxonomy() -> dict[str, set[str]]:
"""{category: {sub-category slugs}}, parsed from `## <slug>` headings
in each category's docs/manual/08-components-reference/ file."""
ref_root = Path(__file__).parent / "manual" / "08-components-reference"
taxonomy: dict[str, set[str]] = {}
for category, filename in _TAXONOMY_FILES.items():
_, body = mt.parse(ref_root / filename)
taxonomy[category] = {
m.group(1)
for ln in body.split("\n")
if (m := re.match(r"^## ([a-z][a-z0-9-]*)$", ln))
}
return taxonomy
def test_every_categorised_function_produces_one_entry():
import build_manual
@@ -184,6 +216,36 @@ def test_dependencies_resolve():
assert not dangling, "unresolvable # DEPENDENCIES:\n " + "\n ".join(dangling)
def test_every_component_resolves_to_a_taxonomy_entry():
"""Every non-C0 # COMPONENT tag must resolve to a documented sub-category."""
taxonomy = _load_taxonomy()
unknown = []
for identity, raw_lines in _parsed_components().items():
for site, tag in mt.parse_component_lines(raw_lines):
if tag in _C0_TAGS:
continue
if "/" not in tag:
unknown.append(f"{identity}: malformed tag {tag!r}")
continue
category, subcat = tag.split("/", 1)
if category not in taxonomy or subcat not in taxonomy[category]:
unknown.append(f"{identity}: {tag}")
assert not unknown, "# COMPONENT tags with no taxonomy entry:\n " + "\n ".join(unknown)
def warn_c0_tags_never_combine_with_contradiction():
"""Warn -- never fail -- on always/on + always/off contradictions this
repo's own generator would warn about -- this is a direct repo-content
check, independent of running the generator, so CI surfaces them even
if someone forgets to regenerate. Warnings are non-fatal (spec §4.5);
this exists to print them prominently in CI output."""
from generate_component_registry import build_registry
_, warnings = build_registry(_parsed_components())
for w in warnings:
print(f" WARN {w}")
def warn_public_functions_without_category():
"""Warn — never fail — on a public function carrying no `# CATEGORY`.
@@ -205,6 +267,63 @@ def warn_public_functions_without_category():
print(" " + ", ".join(orphans))
# The guard's own supporting infrastructure: these files' bodies (function
# signature, SYNOPSIS/EXAMPLE prose) legitimately contain the literal text
# "__fish_config_op_enabled" without being a *caller* of the guard, so they
# are permanently exempt from warn_functions_without_component's substring
# check below.
_GUARD_INFRA_FILES = {
"__fish_config_op_enabled.fish",
"__fish_config_op_cascade.fish",
"__fish_config_op_registry_lookup.fish",
}
def warn_functions_without_component():
"""Warn -- never fail -- on a documented function calling the
opinionated guard but carrying no `# COMPONENT` section.
Mirrors warn_public_functions_without_category: a function that never
opted into the header convention at all (no # SYNOPSIS) is silently
out of scope, matching spec §4.5's fail-open tiering.
"""
repo = Path(__file__).parent.parent
components = _parsed_components()
orphans = []
for p in list((repo / "functions").glob("*.fish")) + list((repo / "conf.d").glob("*.fish")):
if p.name in _GUARD_INFRA_FILES:
continue
text = p.read_text(encoding="utf-8")
if "__fish_config_op_enabled" not in text or "# SYNOPSIS" not in text:
continue
if p.stem not in components:
orphans.append(str(p.relative_to(repo)))
if orphans:
print(f" WARN {len(orphans)} function(s) call the opinionated guard but lack # COMPONENT:")
print(" " + ", ".join(sorted(orphans)))
def warn_unused_taxonomy_entries():
"""Warn -- never fail -- on a documented sub-category with zero tagged functions."""
taxonomy = _load_taxonomy()
used: dict[str, set[str]] = {c: set() for c in taxonomy}
for raw_lines in _parsed_components().values():
for _site, tag in mt.parse_component_lines(raw_lines):
if tag in _C0_TAGS or "/" not in tag:
continue
category, subcat = tag.split("/", 1)
if category in used:
used[category].add(subcat)
unused = [
f"{category}/{subcat}"
for category, subcats in taxonomy.items()
for subcat in sorted(subcats - used[category])
]
if unused:
print(f" WARN {len(unused)} taxonomy entr{'y has' if len(unused) == 1 else 'ies have'} zero tagged functions:")
print(" " + ", ".join(unused))
def _without_section_5(text: str) -> str:
"""Drop `# 5. FUNCTIONS REFERENCE` through the start of section 6.
@@ -827,6 +946,207 @@ def test_site_avoids_reserved_dir():
)
def test_parse_component_lines_default_and_named_sites():
lines = [
"aliases/filesystem",
"site exit-plain: overrides/key-bindings",
"site logging-guard: logging/terminal-capture",
"",
" ",
]
got = mt.parse_component_lines(lines)
assert got == [
("", "aliases/filesystem"),
("exit-plain", "overrides/key-bindings"),
("logging-guard", "logging/terminal-capture"),
], f"unexpected parse: {got}"
def test_parse_components_includes_underscore_prefixed_and_uncategorised():
"""Unlike parse_functions, parse_components has no # CATEGORY gate and
no underscore exclusion -- every guarded identity must be visible."""
with tempfile.TemporaryDirectory() as d:
root = Path(d)
(root / "__private_helper.fish").write_text(
"# COMPONENT\n"
"# logging/terminal-capture\n"
"function __private_helper\n"
"end\n"
)
(root / "no_category.fish").write_text(
"# COMPONENT\n"
"# aliases/filesystem\n"
"#\n"
"# SYNOPSIS\n"
"# no_category\n"
"function no_category\n"
"end\n"
)
got = mt.parse_components(root)
assert got["__private_helper"] == ["logging/terminal-capture"]
assert got["no_category"] == ["aliases/filesystem"]
def test_parse_components_resolves_multi_header_file_to_function_name():
with tempfile.TemporaryDirectory() as d:
root = Path(d)
(root / "multi.fish").write_text(
"# COMPONENT\n"
"# aliases/filesystem\n"
"function first_fn\n"
"end\n"
"\n"
"# COMPONENT\n"
"# aliases/network\n"
"function second_fn\n"
"end\n"
)
got = mt.parse_components(root)
assert got == {
"first_fn": ["aliases/filesystem"],
"second_fn": ["aliases/network"],
}, f"unexpected resolution: {got}"
def test_parse_component_file_single_file():
with tempfile.TemporaryDirectory() as d:
path = Path(d) / "config.fish"
path.write_text(
"# COMPONENT\n"
"# site greeting-block: greeting/greeting-message\n"
)
got = mt.parse_component_file(path)
assert got == {"config": ["site greeting-block: greeting/greeting-message"]}
def test_build_registry_strips_on_off_contradiction_with_warning():
import generate_component_registry as gcr
components = {"contradictory_fn": ["always/on", "always/off", "aliases/filesystem"]}
registry, warnings = gcr.build_registry(components)
assert registry["contradictory_fn:"] == ["aliases/filesystem"], (
f"the non-contradictory tag should survive: {registry}"
)
assert len(warnings) == 1 and "contradictory_fn" in warnings[0]
def test_build_registry_drops_empty_effective_tag_sets():
import generate_component_registry as gcr
components = {"only_contradictory": ["always/on", "always/off"]}
registry, warnings = gcr.build_registry(components)
assert "only_contradictory:" not in registry, (
"a site stripped down to nothing must produce no registry entry "
"(fail-open: absence of an entry already means always/on at guard time)"
)
assert len(warnings) == 1
def test_build_registry_keeps_sites_independent():
import generate_component_registry as gcr
components = {
"smart_exit": [
"site exit-plain: overrides/key-bindings",
"site logging-guard: logging/terminal-capture",
]
}
registry, warnings = gcr.build_registry(components)
assert registry["smart_exit:exit-plain"] == ["overrides/key-bindings"]
assert registry["smart_exit:logging-guard"] == ["logging/terminal-capture"]
assert not warnings
def test_collect_components_merges_identity_collisions_across_sources():
"""functions/auto-pull.fish and conf.d/auto-pull.fish both self-identify
as "auto-pull" at runtime -- the guard only ever has the bare
status current-function/basename string to look up with -- so
collect_components must concatenate their raw COMPONENT lines
rather than letting conf.d's entry silently overwrite functions'."""
import generate_component_registry as gcr
with tempfile.TemporaryDirectory() as d:
root = Path(d)
(root / "functions").mkdir()
(root / "conf.d").mkdir()
(root / "functions" / "auto-pull.fish").write_text(
"# COMPONENT\n"
"# autoexec/sync\n"
"function auto-pull\n"
"end\n"
)
(root / "conf.d" / "auto-pull.fish").write_text(
"# COMPONENT\n"
"# autoexec/sync\n"
)
(root / "config.fish").write_text("")
orig_repo = gcr.REPO
try:
gcr.REPO = root
got = gcr.collect_components()
finally:
gcr.REPO = orig_repo
assert got["auto-pull"] == ["autoexec/sync", "autoexec/sync"], (
f"both sources' tags should survive the merge, not overwrite: {got}"
)
def test_render_registry_is_valid_fish_and_round_trips():
"""Sourcing render()'s output must leave the two arrays in the exact
shape __fish_config_op_registry_lookup expects -- checked via the real
lookup helper (functions/__fish_config_op_registry_lookup.fish, Task
2) rather than re-parsing the generated text by hand."""
import subprocess
import generate_component_registry as gcr
registry = {
"rm:": ["aliases/filesystem"],
"smart_exit:exit-plain": ["overrides/key-bindings"],
}
text = gcr.render(registry)
repo = Path(__file__).parent.parent
proc = subprocess.run(
[
"fish", "-c",
f"source {repo}/functions/__fish_config_op_registry_lookup.fish; "
"source /dev/stdin; "
"__fish_config_op_registry_lookup rm ''; echo status=$status",
],
input=text,
capture_output=True,
text=True,
)
assert "aliases/filesystem" in proc.stdout, f"unexpected output: {proc.stdout!r} {proc.stderr!r}"
assert "status=0" in proc.stdout, f"lookup did not report found: {proc.stdout!r}"
def test_build_manual_regenerates_registry_before_building():
"""docs/build-manual.py must regenerate the registry as a pre-step."""
import build_manual
assert hasattr(build_manual, "generate_component_registry"), (
"build-manual.py must import generate_component_registry so its "
"main() can be called as a pre-step before --site/--concat run"
)
def test_committed_registry_matches_headers():
"""The committed conf.d/__fish_config_op_registry.fish must match what
generate_component_registry.py would produce right now from the current
`# COMPONENT` headers -- otherwise CI has nothing catching drift."""
import generate_component_registry as gcr
registry, _ = gcr.build_registry(gcr.collect_components())
assert gcr.render(registry) == gcr.OUTPUT.read_text(), (
"conf.d/__fish_config_op_registry.fish is stale — run "
"__fish_config_op_registry_rebuild"
)
TESTS = [v for k, v in sorted(globals().items()) if k.startswith("test_")]
@@ -840,6 +1160,9 @@ def main() -> int:
print(f" FAIL {t.__name__}: {e}", file=sys.stderr)
failed += 1
warn_public_functions_without_category()
warn_functions_without_component()
warn_unused_taxonomy_entries()
warn_c0_tags_never_combine_with_contradiction()
print(f"\n{len(TESTS) - failed}/{len(TESTS)} passed")
return 1 if failed else 0
+4 -1
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# COMPONENT
# autoexec/venv
#
# SYNOPSIS
# __auto_source_fallback_venv
#
@@ -16,7 +19,7 @@ function __auto_source_fallback_venv --on-variable PWD
status --is-command-substitution; and return
# Opinionated guard (C2): no automatic venv activation when disabled.
__fish_config_op_enabled __fish_config_op_autoexec; or return
__fish_config_op_enabled (status current-function); or return
# 1. Skip if direnv is already managing this directory
if set -q DIRENV_DIR; or test -e ".envrc"
+1 -1
View File
@@ -182,7 +182,7 @@ function __config_settings_draw
# ── Keybind hint ──────────────────────────────────────────────────────
# string pad is width-aware (arrows count as 1 column)
set -l hint " ↑↓/kj move ←→/hl set Tab page q quit"
set -l hint " ↑↓/kj move ←→/hl set Enter sub-cats Tab pg q quit"
printf '%s│%s%s%s│\n' $p $c_dim (string pad -r -w $iw -- $hint) $c_reset
# ── Bottom border ─────────────────────────────────────────────────────
@@ -0,0 +1,151 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __config_settings_draw_subcat <cur_row> <cur_scope> <category_var>
#
# DESCRIPTION
# Renders the sub-category drill-down page for one C1-C6 category:
# the category's own toggle at the top (still meaningful as the cascade
# default for its sub-categories), then one row per sub-category from
# __config_settings_subcats, sized dynamically instead of the fixed
# 6-row layout __config_settings_draw uses for the category list.
# Follows the same width-tier and center-padding conventions as
# __config_settings_draw so the panel doesn't visibly jump between the
# two pages.
#
# Label and description fields are defensively truncated to their field
# width before padding (string pad only ever grows a string, never
# shrinks it) -- sub-category labels/descriptions are static data from
# __config_settings_subcats, not authored per width-tier the way
# __config_settings_draw's own category descriptions are, so a couple of
# them are longer than the narrower tiers' fields (e.g. "Notifications"
# is 13 chars against a 12-char label field; several descriptions run
# well past the 17-char field at the narrowest tier). Truncating keeps
# the box perfectly rectangular in every case instead of only in the
# cases the static text happens to fit.
#
# ARGUMENTS
# cur_row 0-based highlighted row (0 = the category's own toggle;
# 1..N = sub-category rows)
# cur_scope "universal" or "session"
# category_var One of the six __fish_config_op_<category> names
#
# EXIT STATUS
# 0 Always
#
# EXAMPLE
# __config_settings_draw_subcat 1 universal __fish_config_op_aliases
function __config_settings_draw_subcat
set -l cur_row $argv[1]
set -l cur_scope $argv[2]
set -l category_var $argv[3]
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)
set -l rows (__config_settings_subcats $category_var)
set -l n (count $rows)
# ── Width tier: matches __config_settings_draw's 6-col-per-side steps ──
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)") ' ')
# Label field is 13 wide (one wider than __config_settings_draw's 12) --
# the longest real sub-category label ("Notifications") is 13 chars.
# Description field absorbs the difference so every row still totals
# iw+2, matching the surrounding box lines exactly.
set -l label_w 13
set -l desc_w (math $iw - 34)
set -l cat_label (string replace -r '^__fish_config_op_' '' -- $category_var)
# Scope indicator: toggling a row on this page writes -U (Universal,
# persistent) or -g (Session, this-shell-only) -- the title must say
# which, since it isn't otherwise visible anywhere on the page.
set -l scope_label Universal
test "$cur_scope" = session; and set scope_label Session
# Title layout is "┌─ Sub-categories: <label> (<scope>) ───┐"; the
# dash count must absorb every visible char added around cat_label so
# the line still totals iw+2, matching the surrounding box exactly --
# see the DESCRIPTION doc comment above for why this is hand-verified,
# not eyeballed.
set -l title_dashes (math $iw - (string length -- $cat_label) - (string length -- $scope_label) - 22)
printf '%s┌─%s Sub-categories: %s (%s)%s %s┐\n' \
$p $c_head "$cat_label" $scope_label "$c_reset" (string repeat -n (math "max(0, $title_dashes)") '─')
printf '%s│%s│\n' $p $HBR
# Row 0: the category's own toggle, still meaningful as the cascade
# default any DEFAULT-valued sub-category below falls back to.
set -l cat_val (__config_settings_get_val $category_var $cur_scope)
set -l cat_badge
switch $cat_val
case on
set cat_badge "$c_ok"" ON$c_reset"
case off
set cat_badge "$c_err""OFF $c_reset"
case '*'
set cat_badge "$c_dim""DEFAULT$c_reset"
end
set -l cat_curs " "
if test $cur_row -eq 0
set cat_curs "$c_sel$c_reset "
end
set -l cat_desc "cascade default"
if test $iw -ge 68
set cat_desc "default for all sub-cats below"
end
if test $iw -ge 72
set cat_desc "default for all sub-categories below"
end
printf '%s│ %s%s [ %s ] %s │\n' $p $cat_curs \
(string pad -r -w $label_w -- "(category)") $cat_badge \
(string pad -r -w $desc_w -- (string sub -l $desc_w -- $cat_desc))
printf '%s│ %s │\n' $p (string repeat -n (math $iw - 6) '─')
for i in (seq 1 $n)
set -l fields (string split -- \t $rows[$i])
set -l slug $fields[1]
set -l label $fields[2]
set -l desc $fields[3]
set -l subcat_var "$category_var"_(string replace -a -- '-' '_' $slug)
set -l val (__config_settings_get_val $subcat_var $cur_scope)
set -l badge
switch $val
case on
set badge "$c_ok"" ON$c_reset"
case off
set badge "$c_err""OFF $c_reset"
case '*'
set badge "$c_dim""DEFAULT$c_reset"
end
set -l curs " "
if test $i -eq $cur_row
set curs "$c_sel$c_reset "
end
set -l lpad (string pad -r -w $label_w -- (string sub -l $label_w -- $label))
set -l dpad (string pad -r -w $desc_w -- (string sub -l $desc_w -- $desc))
printf '%s│ %s%s [ %s ] %s │\n' $p $curs $lpad $badge $dpad
end
printf '%s│%s│\n' $p $HBR
set -l hint " ↑↓/kj move ←→/hl set Esc back q quit"
printf '%s│%s%s%s│\n' $p $c_dim (string pad -r -w $iw -- $hint) $c_reset
printf '%s└%s┘\n' $p $HBR
end
+65
View File
@@ -0,0 +1,65 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __config_settings_subcats <category_variable>
#
# DESCRIPTION
# Prints the sub-category rows for one C1-C6 category, one per line as
# "<slug>\t<label>\t<description>". This is a fish-native copy of the
# taxonomy authored in docs/manual/08-components-reference/*.md (Task 9)
# -- kept here as a static table rather than parsed from markdown at
# draw time, since config-settings redraws on every keypress and every
# terminal resize.
#
# ARGUMENTS
# category_variable One of the six __fish_config_op_<category> names
#
# EXIT STATUS
# 0 Always
#
# RETURNS
# Tab-separated "<slug>\t<label>\t<description>" rows, one per line
#
# EXAMPLE
# __config_settings_subcats __fish_config_op_aliases
function __config_settings_subcats --description 'List the sub-categories for one opinionated-component category'
switch $argv[1]
case __fish_config_op_aliases
printf '%s\t%s\t%s\n' \
filesystem Filesystem "ls, cat, cd, du, mkdir, rm, mv, zoxide" \
search Search "rg" \
network Network "ping, ssh, yt-dlp" \
monitor Monitor "top" \
shell-tools Shell-tools "bash, less, help" \
dev-tools Dev-tools "claude, edit, agy"
case __fish_config_op_autoexec
printf '%s\t%s\t%s\n' \
plugin-management Plugins "Fisher bootstrap" \
pkg-wrappers Pkg-wrappers "paru/yay wrapper generation" \
venv Venv "Python auto-activation" \
telemetry Telemetry "WakaTime hook bootstrap" \
sync Sync "auto-pull, user-dots symlink"
case __fish_config_op_overrides
printf '%s\t%s\t%s\n' \
key-bindings Key-bindings "vi-mode, autopair, puffer, bang-bang" \
environment Environment "PATH, PAGER, EDITOR, CDPATH" \
prompt Prompt "Starship, right prompt, theme + FZF colors"
case __fish_config_op_integrations
printf '%s\t%s\t%s\n' \
terminal-abbrs Term-abbrs "Kitty/WezTerm abbreviations" \
window-mgmt Window-mgmt "spwin, tab, split" \
notifications Notifications "done, WakaTime hook" \
history-logs History-logs "hist, logs" \
pkg-upgrade Pkg-upgrade "upgrade"
case __fish_config_op_logging
printf '%s\t%s\t%s\n' \
terminal-capture Term-capture "Kitty watcher, smart_exit scrollback" \
multiplexer-capture Multiplexer "tmux, zellij" \
pkg-logs Pkg-logs "paru/yay AUR log wrappers"
case __fish_config_op_greeting
printf '%s\t%s\t%s\n' \
first-run First-run "welcome banner" \
greeting-message Greeting "fish_greeting override"
end
end
+63
View File
@@ -0,0 +1,63 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __fish_config_op_cascade <category_variable> [<subcategory_variable>]
#
# DESCRIPTION
# Evaluates the opt-out cascade for one C1-C6 classification: an
# explicit truthy/falsy sub-category variable wins outright; otherwise
# falls back to the category variable; otherwise falls back to the
# master switch __fish_config_opinionated. A category in the opt-in
# list (currently just __fish_config_op_logging, C5) defaults to
# disabled when nothing in the chain is explicit, and the master switch
# cannot enable it -- this is data-driven here instead of a hardcoded
# string comparison, so any sub-category nested under an opt-in
# category inherits "off unless explicit" for free through the cascade,
# with no per-sub-category special-casing.
#
# ARGUMENTS
# category_variable Name (without $) of a C1-C6 category variable
# subcategory_variable Optional name (without $) of a sub-category
# variable nested under that category
#
# EXIT STATUS
# 0 Enabled
# 1 Disabled
#
# EXAMPLE
# __fish_config_op_cascade __fish_config_op_aliases
# __fish_config_op_cascade __fish_config_op_aliases __fish_config_op_aliases_filesystem
function __fish_config_op_cascade --description 'Evaluate the sub-category -> category -> master opt-out cascade'
set -l opt_in_categories __fish_config_op_logging
set -l chain $argv[1]
if test (count $argv) -ge 2 -a -n "$argv[2]"
set chain $argv[2] $argv[1]
end
for var_name in $chain
__fish_variable_check $var_name
set -l s $status
if test $s -eq 0
return 0
end
if test $s -eq 1
return 1
end
end
# Every variable in the chain was unset/unrecognized. chain[-1] is
# always the category variable (present whether or not a
# sub-category was given) -- opt-in categories default to disabled
# and the master switch cannot override that.
if contains -- $chain[-1] $opt_in_categories
return 1
end
__fish_variable_check __fish_config_opinionated
if test $status -eq 1
return 1
end
return 0
end
+43 -38
View File
@@ -2,63 +2,68 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __fish_config_op_enabled <category_variable>
# __fish_config_op_enabled <identity> [<site>]
#
# DESCRIPTION
# Guard predicate for opinionated components (AGENTS.md Task #3).
# The category variable is evaluated first via __fish_variable_check:
# an explicit truthy value (1/true/yes/on/y) enables the component
# regardless of the master switch; an explicit falsy value
# (0/false/no/off/n) disables it regardless of the master switch.
# Only when the category variable is unset or unrecognized (status 2
# or 3) does the master switch __fish_config_opinionated apply: a
# falsy master disables every unset-category component at once.
# Unset master with unset category → enabled (active by default).
# Guard predicate for an opinionated component. <identity> is computed
# by the caller, never hand-typed as a category name: (status
# current-function) inside a function body, (status basename) at
# top-level conf.d/*.fish or config.fish code (fish has no API for a
# callee to introspect its own caller, so the caller must compute and
# pass its own identity -- see the spec's "A note on self-identifying").
# A trailing .fish is stripped so a status-basename identity and a
# status-current-function identity land in the same key space.
#
# One exception: __fish_config_op_logging (C5) is opt-in, because it
# writes terminal output to disk. Unset or unrecognized means disabled,
# and the master switch cannot enable it — only an explicit truthy
# value turns logging on.
# Looks up "<identity>:<site>" (site defaults to the empty/unnamed site)
# in the generated component registry. No registry entry (unclassified,
# or a doc header with no # COMPONENT section) resolves to enabled --
# the same fail-open default as an explicit `always/on` tag, so
# user-authored and third-party functions that never call this guard in
# the first place are unaffected, and one that somehow does is never
# silently broken by a missing header. A found `always/off` tag
# disables unconditionally; a found `always/on` tag enables
# unconditionally, short-circuiting before any other tagged
# sub-category is evaluated. Otherwise every tagged sub-category must
# pass the cascade (AND semantics).
#
# ARGUMENTS
# category_variable Name (without $) of the category opt-out variable:
# __fish_config_op_aliases, __fish_config_op_autoexec,
# __fish_config_op_overrides,
# __fish_config_op_integrations,
# __fish_config_op_logging, or
# __fish_config_op_greeting
# identity (status current-function) or (status basename)
# site Optional site slug (see # COMPONENT header grammar);
# omitted for the default/unnamed site
#
# EXIT STATUS
# 0 Component enabled (category explicitly truthy; or category unset and master not falsy — except C5 logging, which requires an explicit truthy value)
# 1 Component disabled (category explicitly falsy; or category unset and master falsy; or C5 logging unset; or no argument with falsy master)
# 0 Component enabled
# 1 Component disabled
#
# EXAMPLE
# if __fish_config_op_enabled __fish_config_op_aliases
# if not __fish_config_op_enabled (status current-function)
# alias grep='grep --color=auto'
# end
function __fish_config_op_enabled --description 'Check whether an opinionated component category is enabled'
__fish_variable_check $argv[1]
set -l cat_status $status
# if not __fish_config_op_enabled (status current-function) exit-plain
# builtin exit
# end
function __fish_config_op_enabled --description 'Guard for an opinionated component, identified by its own caller'
set -l identity (string replace -r '\.fish$' '' -- $argv[1])
set -l site $argv[2]
if test $cat_status -eq 0
set -l tags (__fish_config_op_registry_lookup $identity $site)
if test $status -ne 0
return 0
end
if test $cat_status -eq 1
if contains -- always/off $tags
return 1
end
# C5 logging is opt-in: it writes terminal output to disk, so an unset or
# unrecognized value means off — the master switch cannot enable it.
if test "$argv[1]" = __fish_config_op_logging
return 1
if contains -- always/on $tags
return 0
end
# Status 3 (garbage) defers to master — an unrecognized value is not an opt-out.
__fish_variable_check __fish_config_opinionated
if test $status -eq 1
return 1
for tag in $tags
set -l parts (string split -m 1 -- / $tag)
set -l category_var "__fish_config_op_$parts[1]"
set -l subcat_var "__fish_config_op_$parts[1]_"(string replace -a -- '-' '_' $parts[2])
__fish_config_op_cascade $category_var $subcat_var
or return 1
end
return 0
end
@@ -0,0 +1,38 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __fish_config_op_registry_lookup <identity> <site>
#
# DESCRIPTION
# Looks up the "<identity>:<site>" key in the generated component
# registry ($__fish_config_op_registry_keys /
# $__fish_config_op_registry_values, sourced from
# conf.d/__fish_config_op_registry.fish at shell startup) and prints its
# tags, one per line. <site> is empty string for the default/unnamed
# site.
#
# ARGUMENTS
# identity Function name (status current-function) or file basename
# with any trailing .fish stripped (status basename)
# site Site slug, or empty string for the default site
#
# EXIT STATUS
# 0 Found: tags printed to stdout
# 1 Not found: nothing printed
#
# RETURNS
# Matching tags, one per line, printed to stdout
#
# EXAMPLE
# set -l tags (__fish_config_op_registry_lookup rm "")
# or return 0 # unclassified: caller treats this as always-on
function __fish_config_op_registry_lookup --description 'Look up the COMPONENT tags for an identity:site pair'
set -l key "$argv[1]:$argv[2]"
set -l idx (contains -i -- $key $__fish_config_op_registry_keys)
if test -z "$idx"
return 1
end
string split ' ' -- $__fish_config_op_registry_values[$idx]
return 0
end
@@ -0,0 +1,30 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __fish_config_op_registry_rebuild
#
# DESCRIPTION
# Regenerates conf.d/__fish_config_op_registry.fish from every
# # COMPONENT header in functions/*.fish, conf.d/*.fish, and
# config.fish, then re-sources it into the current session so the
# change takes effect immediately. Run manually after editing a
# # COMPONENT header; never run automatically at shell startup --
# parsing every header on every new shell would be wasted work on
# every session that isn't actively editing a header.
#
# EXIT STATUS
# 0 Registry regenerated
# 1 python3 is not available, or generation failed
#
# EXAMPLE
# __fish_config_op_registry_rebuild
function __fish_config_op_registry_rebuild --description 'Regenerate the opinionated-component registry from # COMPONENT headers'
if not type -q python3
echo "__fish_config_op_registry_rebuild: python3 not found" >&2
return 1
end
python3 "$__fish_config_dir/docs/generate_component_registry.py"
or return 1
source "$__fish_config_dir/conf.d/__fish_config_op_registry.fish"
end
+4 -1
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# COMPONENT
# logging/terminal-capture
#
# SYNOPSIS
# __fish_config_sync_logging
#
@@ -29,7 +32,7 @@ function __fish_config_sync_logging --description 'Sync C5 logging state: sentin
set -l yay_wrapper "$HOME/.local/bin/yay"
set -l wrapper_version 1
if __fish_config_op_enabled __fish_config_op_logging
if __fish_config_op_enabled (status current-function)
# Logging enabled: remove sentinel and regenerate wrappers if binaries exist
rm -f $sentinel
+4 -1
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# COMPONENT
# autoexec/sync
#
# SYNOPSIS
# __fish_user_dots_link
#
@@ -41,7 +44,7 @@ function __fish_user_dots_link --description 'Manage the user-dots convenience s
end
# Enabled: creation is a C2 startup side-effect.
__fish_config_op_enabled __fish_config_op_autoexec; or return 0
__fish_config_op_enabled (status current-function); or return 0
test -d "$__fish_user_dots_path"; or return 0
if test -L "$link"
+4 -1
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# COMPONENT
# logging/multiplexer-capture
#
# SYNOPSIS
# _zellij_dump_log
#
@@ -23,7 +26,7 @@
# EXAMPLE
# _zellij_dump_log
function _zellij_dump_log --description 'Dump the current Zellij pane scrollback to a log file, with pruning'
__fish_config_op_enabled __fish_config_op_logging; or return 0
__fish_config_op_enabled (status current-function); or return 0
set -q ZELLIJ; or return 0
type -q zellij; or return 0
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 12-ai-and-developer-tools
#
# COMPONENT
# aliases/dev-tools
#
# DEPENDENCIES
# agents-init
#
@@ -35,7 +38,7 @@
# agy -i "initial prompt"
# agy models
function agy --wraps=agy --description 'agy wrapper: auto-initializes AGENTS/ sub-repo before launch'
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command agy $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 04-git-and-version-control
#
# COMPONENT
# autoexec/sync
#
# SYNOPSIS
# auto-pull [list]
# auto-pull add [PATH]
@@ -136,7 +139,7 @@ function auto-pull --description 'Manage the auto-pull repository registry'
return 0
case status
if __fish_config_op_enabled __fish_config_op_autoexec
if __fish_config_op_enabled (status current-function)
echo "$c_ok""auto-pull: ENABLED$c_reset $c_dim(C2 auto-execution on)$c_reset"
else
echo "$c_warn""auto-pull: DISABLED$c_reset $c_dim(via __fish_config_op_autoexec)$c_reset"
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 14-miscellaneous
#
# COMPONENT
# aliases/shell-tools
#
# SYNOPSIS
# bash [args...]
#
@@ -18,7 +21,7 @@
# bash
function bash --wraps='bash' --description 'bash switches to bash shell'
# Opinionated guard (C1): fall back to bare command bash when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command bash $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 01-file-and-directory
#
# COMPONENT
# aliases/filesystem
#
# SYNOPSIS
# cat [args...]
#
@@ -21,7 +24,7 @@
# cat ~/projects/myapp
function cat --wraps='bat' --description 'Use bat for files, ls for directories, and raw cat for ANSI logs'
# Opinionated guard (C1): fall back to bare command cat when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command cat $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 12-ai-and-developer-tools
#
# COMPONENT
# aliases/dev-tools
#
# DEPENDENCIES
# agents-init
#
@@ -33,7 +36,7 @@
# claude --resume
# claude "Explain the recent changes"
function claude --wraps=claude --description 'claude wrapper: auto-links AGENTS.md as CLAUDE.md'
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command claude $argv
return $status
end
+92 -14
View File
@@ -20,7 +20,10 @@
# path, and the user-dots convenience symlink toggle (Dots link)
#
# Toggle rows use ← / → (or h / l) to step OFF ← DEFAULT → ON; DEFAULT erases
# the variable so the master switch / built-in default applies. Value rows
# the variable so the master switch / built-in default applies. On the
# Universal/Session pages, Enter on a category row (C1C6) opens that
# category's sub-category drill-down page for finer-grained toggles;
# Escape backs out to the category list. Value rows
# (Sponge, Paths) use Enter to edit inline; ← / h clears to 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.
@@ -49,7 +52,10 @@
# ↑ ↓ / k j Move cursor
# ← → / h l Toggle rows: OFF ← DEFAULT → ON
# ← / h Value rows: clear to default
# Enter Value rows: edit inline (Sponge / Paths pages)
# Enter Category rows (Universal/Session): open sub-category
# drill-down page. Value rows: edit inline (Sponge /
# Paths pages)
# Escape Sub-category page: back out to the category list
# Tab / S-Tab Next / previous page
# q / Escape Exit
#
@@ -82,7 +88,8 @@ function config-settings --description 'Interactive TUI for managing fish config
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 Toggle pages: OFF ← DEFAULT → ON"
echo " $c_flag""Enter$c_reset Edit value (Sponge / Paths pages)"
echo " $c_flag""Enter$c_reset Open sub-category page (Universal / Session);"
echo " edit value (Sponge / Paths pages)"
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"
@@ -110,6 +117,12 @@ function config-settings --description 'Interactive TUI for managing fish config
__fish_config_op_greeting \
__fish_config_opinionated
# ── Drill-down navigation state (Universal/Session pages only) ────────
# in_subcat: 1 while viewing a category's sub-category page (Enter to
# open, Escape to back out). subcat_row: cursor row within that page.
set -l in_subcat 0
set -l subcat_row 0
# ── Value-page row metadata (parallel: var / type) ────────────────────
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 sponge_types int bool bool list list
@@ -140,16 +153,34 @@ function config-settings --description 'Interactive TUI for managing fish config
trap 'printf "\e[?25h"; set -g __config_settings_exit 1' INT
# ── Draw dispatch (page 0/1 = toggle table; 2/3 = value page) ─────────
# Records the actual line count of whatever it just drew into panel_h,
# so every erase (redraw loop, inline editor, final cleanup) matches
# reality -- the sub-category page is n+7 lines (2-6 sub-categories:
# 9-13 lines), never the category list's fixed 16.
function __cs_dispatch_draw --no-scope-shadowing
switch $cur_page
case 0
__config_settings_draw $cur_row universal $toggle_vars
if test $in_subcat -eq 1
__config_settings_draw_subcat $subcat_row universal $toggle_vars[(math $cur_row + 1)]
set panel_h (math 7 + (count (__config_settings_subcats $toggle_vars[(math $cur_row + 1)])))
else
__config_settings_draw $cur_row universal $toggle_vars
set panel_h 16
end
case 1
__config_settings_draw $cur_row session $toggle_vars
if test $in_subcat -eq 1
__config_settings_draw_subcat $subcat_row session $toggle_vars[(math $cur_row + 1)]
set panel_h (math 7 + (count (__config_settings_subcats $toggle_vars[(math $cur_row + 1)])))
else
__config_settings_draw $cur_row session $toggle_vars
set panel_h 16
end
case 2
__config_settings_draw_value $cur_row sponge
set panel_h 16
case 3
__config_settings_draw_value $cur_row paths
set panel_h 16
end
end
__cs_dispatch_draw
@@ -174,24 +205,50 @@ function config-settings --description 'Interactive TUI for managing fish config
switch $key
case up k
set cur_row (math "max(0, $cur_row - 1)")
if test $in_subcat -eq 1
set subcat_row (math "max(0, $subcat_row - 1)")
else
set cur_row (math "max(0, $cur_row - 1)")
end
case down j
# Hoist the page index: fish cannot expand a command-substitution
# index inside a quoted math string.
set -l pidx (math $cur_page + 1)
set cur_row (math "min($page_rows[$pidx] - 1, $cur_row + 1)")
if test $in_subcat -eq 1
set -l n (count (__config_settings_subcats $toggle_vars[(math $cur_row + 1)]))
set subcat_row (math "min($n, $subcat_row + 1)")
else
# Hoist the page index: fish cannot expand a command-substitution
# index inside a quoted math string.
set -l pidx (math $cur_page + 1)
set cur_row (math "min($page_rows[$pidx] - 1, $cur_row + 1)")
end
case tab
set cur_page (math "($cur_page + 1) % 4")
set cur_row 0
set in_subcat 0
case backtab
set cur_page (math "($cur_page + 3) % 4")
set cur_row 0
set in_subcat 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)]
# Default: the category variable itself -- correct both
# when not in a sub-category page at all, and when in
# one but sitting on its row 0 (the category's own
# toggle). Only row >= 1 of a sub-category page
# resolves to a different, sub-category variable.
# Hoist the category variable into a plain local first --
# fish cannot expand a command-substitution index
# ("$toggle_vars[(math ...)]") inside a quoted string
# (same reason the down/j case above hoists $pidx).
set -l cvar $toggle_vars[(math $cur_row + 1)]
set -l varname $cvar
if test $in_subcat -eq 1 -a $subcat_row -ne 0
set -l rows (__config_settings_subcats $cvar)
set -l fields (string split -- \t $rows[$subcat_row])
set varname "$cvar"_(string replace -a -- '-' '_' $fields[1])
end
set -l cur_val (__config_settings_get_val $varname $scope)
set -l next_val on
test "$cur_val" = off; and set next_val DEFAULT
@@ -217,7 +274,17 @@ function config-settings --description 'Interactive TUI for managing fish config
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)]
# Same varname resolution as the right/l case above
# (hoisted local -- see the comment there for why the
# command-substitution index can't be inlined into the
# quoted string directly).
set -l cvar $toggle_vars[(math $cur_row + 1)]
set -l varname $cvar
if test $in_subcat -eq 1 -a $subcat_row -ne 0
set -l rows (__config_settings_subcats $cvar)
set -l fields (string split -- \t $rows[$subcat_row])
set varname "$cvar"_(string replace -a -- '-' '_' $fields[1])
end
set -l cur_val (__config_settings_get_val $varname $scope)
set -l next_val off
test "$cur_val" = on; and set next_val DEFAULT
@@ -246,7 +313,12 @@ function config-settings --description 'Interactive TUI for managing fish config
end
end
case enter
if test $cur_page -ge 2
if test $cur_page -le 1
if test $in_subcat -eq 0 -a $cur_row -le 5
set in_subcat 1
set subcat_row 0
end
else if test $cur_page -ge 2
set -l v_vars $sponge_vars
set -l v_types $sponge_types
set -l v_defaults $sponge_defaults
@@ -313,8 +385,14 @@ function config-settings --description 'Interactive TUI for managing fish config
set did_redraw 1
end
end
case q Q quit escape
case q Q quit
break
case escape
if test $in_subcat -eq 1
set in_subcat 0
else
break
end
end
# Skip redraw entirely when the key reader timed out with no resize
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 01-file-and-directory
#
# COMPONENT
# aliases/filesystem
#
# SYNOPSIS
# du [--disk|--dir|--dua] [args...]
#
@@ -23,7 +26,7 @@
# du --disk
function du --description 'Execute du'
# Opinionated guard (C1): fall back to bare command du when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command du $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 03-editors-and-viewers
#
# COMPONENT
# aliases/dev-tools
#
# SYNOPSIS
# edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...]
#
@@ -50,7 +53,7 @@ function edit --description 'Open files in a terminal or GUI editor with fallbac
set -l c_reset (set_color normal)
# Opinionated guard (C1): fall back to the legacy bare-editor behavior.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
if set -q EDITOR; and test -n "$EDITOR"
$EDITOR $argv
else if type -q nvim
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 08-terminal-management
#
# COMPONENT
# overrides/prompt
#
# SYNOPSIS
# fish_right_prompt
#
@@ -31,7 +34,7 @@ function fish_right_prompt
# Docker context — only relevant alongside the starship prompt, and only
# when docker is actually installed (guarded like every other optional
# integration in this config).
if type -q docker; and type -q starship; and __fish_config_op_enabled __fish_config_op_overrides
if type -q docker; and type -q starship; and __fish_config_op_enabled (status current-function)
set -l docker_ctx (docker context show 2>/dev/null)
if test -n "$docker_ctx"; and test "$docker_ctx" != default
set_color blue
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 04-git-and-version-control
#
# COMPONENT
# integrations/history-logs
#
# SYNOPSIS
# hist
#
@@ -15,7 +18,7 @@
# hist
function hist --description 'Search fish history and put it in the prompt'
# Opinionated guard (C4): integrations disabled
if not __fish_config_op_enabled __fish_config_op_integrations
if not __fish_config_op_enabled (status current-function)
set -l c_err (set_color red)
set -l c_reset (set_color normal)
echo "$c_err"'hist: disabled by __fish_config_op_integrations'"$c_reset" >&2
+5 -2
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 14-miscellaneous
#
# COMPONENT
# logging/terminal-capture
#
# SYNOPSIS
# kitty-logging [install | uninstall | status | dismiss] [-h]
#
@@ -97,7 +100,7 @@ function kitty-logging --description 'Install/manage the fish-config Kitty scrol
else
echo " Watcher file: $c_warn""not installed$c_reset"
end
if __fish_config_op_enabled __fish_config_op_logging
if __fish_config_op_enabled (status current-function)
echo " C5 logging: $c_ok""enabled$c_reset"
else
echo " C5 logging: $c_warn""disabled$c_reset (capture is currently inert)"
@@ -143,7 +146,7 @@ function kitty-logging --description 'Install/manage the fish-config Kitty scrol
end
echo "$c_ok""→ Installed.$c_reset Watcher wired into $conf"
echo " $c_dim""Restart Kitty (new windows) for it to take effect.$c_reset"
if not __fish_config_op_enabled __fish_config_op_logging
if not __fish_config_op_enabled (status current-function)
echo " $c_warn""Note: C5 logging is disabled, so capture is currently inert.$c_reset"
end
return 0
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 03-editors-and-viewers
#
# COMPONENT
# aliases/shell-tools
#
# SYNOPSIS
# less [args...]
#
@@ -18,7 +21,7 @@
# less /var/log/syslog
function less --wraps='ov' --description 'Pager wrapper: $PAGER → ov → less → more → cat'
# Opinionated guard (C1): fall back to bare command less when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command less $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 11-pager-and-logging
#
# COMPONENT
# integrations/history-logs
#
# SYNOPSIS
# logs [-h] [-c <category>]
#
@@ -35,7 +38,7 @@
# logs -c scrollback
function logs --description 'Browse terminal log files interactively with fzf'
# Opinionated guard (C4): integrations disabled
if not __fish_config_op_enabled __fish_config_op_integrations
if not __fish_config_op_enabled (status current-function)
set -l c_err (set_color red)
set -l c_reset (set_color normal)
echo "$c_err"'logs: disabled by __fish_config_op_integrations'"$c_reset" >&2
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 01-file-and-directory
#
# COMPONENT
# aliases/filesystem
#
# SYNOPSIS
# ls [args...]
#
@@ -20,7 +23,7 @@
# ls -a ~/projects
function ls --description 'List all files'
# Opinionated guard (C1): fall back to bare command ls when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command ls $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 01-file-and-directory
#
# COMPONENT
# aliases/filesystem
#
# SYNOPSIS
# mkdir [args...]
#
@@ -20,7 +23,7 @@
# mkdir ~/projects/myapp/src
function mkdir --description 'Execute mkdir'
# Opinionated guard (C1): fall back to bare command mkdir when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command mkdir $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 01-file-and-directory
#
# COMPONENT
# aliases/filesystem
#
# SYNOPSIS
# mv [args...]
#
@@ -27,7 +30,7 @@
# mv ~/.config/btop/themes/themes ~/.config/btop/themes
function mv --wraps='mv' --description 'Move files with auto-collapse for nested directories'
# Opinionated guard (C1): fall back to bare command mv when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command mv $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 10-network
#
# COMPONENT
# aliases/network
#
# SYNOPSIS
# ping [args...]
#
@@ -21,7 +24,7 @@
# ping --legend google.com
function ping --description 'prettyping with default nolegend'
# Opinionated guard (C1): fall back to bare command ping when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command ping $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 01-file-and-directory
#
# COMPONENT
# aliases/search
#
# SYNOPSIS
# rg [args...]
#
@@ -21,7 +24,7 @@
# rg -l "TODO" ~/projects/myapp
function rg --description 'alias rg=rg --hyperlink-format=kitty'
# Opinionated guard (C1): fall back to bare command rg when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command rg $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 01-file-and-directory
#
# COMPONENT
# aliases/filesystem
#
# SYNOPSIS
# rm [-e [options] | -S | args...]
#
@@ -38,7 +41,7 @@
# Falls back to /usr/bin/rm when trash is unavailable.
function rm --description 'Ultimate rm: trash, list, empty, and secure-erase'
# Opinionated guard (C1): fall back to bare command rm when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command rm $argv
return $status
end
+6 -2
View File
@@ -4,6 +4,10 @@
# CATEGORY
# 11-pager-and-logging
#
# COMPONENT
# site exit-plain: overrides/key-bindings
# site logging-guard: logging/terminal-capture
#
# SYNOPSIS
# smart_exit [-h] [-n]
#
@@ -32,7 +36,7 @@ function smart_exit --description 'Capture colorized scrollback before exiting,
# Opinionated guard (C3): exit plainly when overrides are disabled.
# This composes with Task #4's __fish_config_enable_logging, which will
# gate only the scrollback capture while leaving the exit wrapper active.
if not __fish_config_op_enabled __fish_config_op_overrides
if not __fish_config_op_enabled (status current-function) exit-plain
builtin exit $argv
end
@@ -60,7 +64,7 @@ function smart_exit --description 'Capture colorized scrollback before exiting,
# C5 — Logging & Capture: skip all capture when logging is disabled.
# When disabled, tell Kitty the window is handled so its watcher doesn't
# capture either — belt-and-suspenders alongside the sentinel file.
if not __fish_config_op_enabled __fish_config_op_logging
if not __fish_config_op_enabled (status current-function) logging-guard
if test -n "$KITTY_WINDOW_ID"
kitty @ set-user-vars "logged_by_shell=true" 2>/dev/null
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 08-terminal-management
#
# COMPONENT
# integrations/window-mgmt
#
# SYNOPSIS
# split [-h | -v] [command...]
#
@@ -27,7 +30,7 @@
# split -v nvim README.md
function split --description 'Run a command in a new terminal split'
# Opinionated guard (C4): integrations disabled
if not __fish_config_op_enabled __fish_config_op_integrations
if not __fish_config_op_enabled (status current-function)
set -l c_err (set_color red)
set -l c_reset (set_color normal)
echo "$c_err"'split: disabled by __fish_config_op_integrations'"$c_reset" >&2
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 08-terminal-management
#
# COMPONENT
# integrations/window-mgmt
#
# SYNOPSIS
# spwin [args...]
#
@@ -22,7 +25,7 @@
# spwin
function spwin --wraps='~/.config/kitty/spawn-window.sh' --description 'spawn window in kitty or wezterm'
# Opinionated guard (C4): integrations disabled
if not __fish_config_op_enabled __fish_config_op_integrations
if not __fish_config_op_enabled (status current-function)
set -l c_err (set_color red)
set -l c_reset (set_color normal)
echo "$c_err"'spwin: disabled by __fish_config_op_integrations'"$c_reset" >&2
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 08-terminal-management
#
# COMPONENT
# aliases/network
#
# SYNOPSIS
# ssh [args...]
#
@@ -20,7 +23,7 @@
# ssh user@host
function ssh --description 'Alias ssh to kitten ssh when using Kitty terminal'
# Opinionated guard (C1): fall back to bare command ssh when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command ssh $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 08-terminal-management
#
# COMPONENT
# integrations/window-mgmt
#
# SYNOPSIS
# tab [args...]
#
@@ -23,7 +26,7 @@
# tab
function tab --description 'Spawn a new tab in the current terminal'
# Opinionated guard (C4): integrations disabled
if not __fish_config_op_enabled __fish_config_op_integrations
if not __fish_config_op_enabled (status current-function)
set -l c_err (set_color red)
set -l c_reset (set_color normal)
echo "$c_err"'tab: disabled by __fish_config_op_integrations'"$c_reset" >&2
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 07-system-and-monitoring
#
# COMPONENT
# aliases/monitor
#
# SYNOPSIS
# top [args...]
#
@@ -18,7 +21,7 @@
# top
function top --wraps='btop' --description 'Use btop as a modern replacement for top'
# Opinionated guard (C1): fall back to bare command top when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command top $argv
return $status
end
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 05-package-management
#
# COMPONENT
# integrations/pkg-upgrade
#
# SYNOPSIS
# upgrade
#
@@ -19,7 +22,7 @@
# upgrade
function upgrade --description 'Full system upgrade via paru or yay'
# Opinionated guard (C4): integrations disabled
if not __fish_config_op_enabled __fish_config_op_integrations
if not __fish_config_op_enabled (status current-function)
set -l c_err (set_color red)
set -l c_reset (set_color normal)
echo "$c_err"'upgrade: disabled by __fish_config_op_integrations'"$c_reset" >&2
+4 -1
View File
@@ -4,6 +4,9 @@
# CATEGORY
# 13-media-and-utilities
#
# COMPONENT
# aliases/network
#
# SYNOPSIS
# yt-dlp [args...] URL [URL...]
#
@@ -29,7 +32,7 @@
# yt-dlp --no-embed-thumbnail dQw4w9WgXcQ # drops our thumbnail default
function yt-dlp --description 'yt-dlp with embedding + SponsorBlock defaults'
# Opinionated guard (C1): fall back to bare command yt-dlp when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases
if not __fish_config_op_enabled (status current-function)
command yt-dlp $argv
return $status
end