Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
eb1b780a80
|
|||
|
2ce41d0c55
|
|||
|
e30ccbc633
|
|||
|
7e266cb61a
|
|||
|
be3dd7494e
|
|||
|
0382d6ab9c
|
|||
|
f17229d0b8
|
|||
|
621d67e89e
|
@@ -62,6 +62,11 @@
|
||||
opinionated_catalog.md
|
||||
docs/superpowers
|
||||
|
||||
# ──────────────────── Runtime State Files ───────────────────
|
||||
# Sentinel file written/removed at runtime to coordinate logging state
|
||||
# across the fish config and the Kitty Python watcher. Never committed.
|
||||
.logging_disabled
|
||||
|
||||
# ──────────────── Fisher-Managed Plugin Files ───────────────
|
||||
# Fisher writes these into the repo directory on install/update.
|
||||
# They are owned by Fisher — do not commit them.
|
||||
|
||||
@@ -166,7 +166,7 @@ end
|
||||
|
||||
## Minimal Mode
|
||||
|
||||
Everything opinionated in this config — command shadows, startup side-effects, key and environment overrides, and terminal integrations — is active by default but can be switched off with universal variables. Four category toggles and one master switch are available:
|
||||
Everything opinionated in this config — command shadows, startup side-effects, key and environment overrides, terminal integrations, and logging — is active by default but can be switched off with universal variables. Five category toggles and one master switch are available:
|
||||
|
||||
| Variable | Disables |
|
||||
|---|---|
|
||||
@@ -174,7 +174,8 @@ Everything opinionated in this config — command shadows, startup side-effects,
|
||||
| `__fish_config_op_autoexec` | Startup side-effects: Fisher bootstrap, theme apply, `paru`/`yay` wrapper generation, auto venv activation, WakaTime hook |
|
||||
| `__fish_config_op_overrides` | Vi mode, `exit`→`smart_exit`, `$PAGER`/`$MANPAGER`/`$CDPATH`, bang-bang history expansion, autopair, puffer, Starship prompt, theme colors |
|
||||
| `__fish_config_op_integrations` | Kitty/WezTerm window abbreviations, `done` notifications, `spwin`/`tab`/`split`, `hist`, `logs`, `upgrade`, WakaTime |
|
||||
| `__fish_config_opinionated` | Master switch — all four categories at once |
|
||||
| `__fish_config_op_logging` | Scrollback capture on exit, `paru`/`yay` AUR log wrappers, Kitty watcher capture (sentinel-file coordinated) |
|
||||
| `__fish_config_opinionated` | Master switch — all five categories at once |
|
||||
|
||||
Set any of them to a falsy value (`0`, `false`, `no`, `off`, `n`) to disable; erase the variable to re-enable:
|
||||
|
||||
|
||||
@@ -6,9 +6,18 @@
|
||||
# timestamped log file and prunes old logs, mirroring smart_exit behavior.
|
||||
|
||||
# Auto-generating a wrapper in ~/.local/bin is opinionated (C2 auto-exec).
|
||||
# Task #4's __fish_config_enable_logging will additionally gate this wrapper.
|
||||
# Wrapper generation is also gated by C5 (Logging & Capture).
|
||||
__fish_config_op_enabled __fish_config_op_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 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"
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
set -l _paru_real /usr/bin/paru
|
||||
set -l _paru_wrapper "$HOME/.local/bin/paru"
|
||||
set -l _paru_wrapper_version 1
|
||||
|
||||
+10
-1
@@ -6,9 +6,18 @@
|
||||
# timestamped log file and prunes old logs, mirroring smart_exit behavior.
|
||||
|
||||
# Auto-generating a wrapper in ~/.local/bin is opinionated (C2 auto-exec).
|
||||
# Task #4's __fish_config_enable_logging will additionally gate this wrapper.
|
||||
# Wrapper generation is also gated by C5 (Logging & Capture).
|
||||
__fish_config_op_enabled __fish_config_op_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 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"
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
set -l _yay_real /usr/bin/yay
|
||||
set -l _yay_wrapper "$HOME/.local/bin/yay"
|
||||
set -l _yay_wrapper_version 1
|
||||
|
||||
+7
-2
@@ -1382,7 +1382,7 @@ fish_variables.
|
||||
## Opinionated Components (Minimal Mode)
|
||||
|
||||
Every opinionated piece of this config is active by default but can be
|
||||
switched off through four category opt-out variables, each evaluated via
|
||||
switched off through five category opt-out variables, each evaluated via
|
||||
__fish_variable_check. Set a variable to any falsy value (0, false, no,
|
||||
off, n) to disable its category; erase it or set a truthy value (1, true,
|
||||
yes, on, y) to re-enable. Unset means enabled.
|
||||
@@ -1410,13 +1410,18 @@ yes, on, y) to re-enable. Unset means enabled.
|
||||
WezTerm window abbreviations, done
|
||||
notifications, spwin/tab/split,
|
||||
hist, logs, upgrade, WakaTime
|
||||
__fish_config_op_logging Logging & capture: scrollback
|
||||
capture on exit, paru/yay AUR log
|
||||
wrappers, Kitty watcher capture;
|
||||
sentinel file coordinates
|
||||
cross-process state
|
||||
|
||||
Examples:
|
||||
|
||||
# Disable command shadows only (rm becomes plain rm again):
|
||||
set -U __fish_config_op_aliases off
|
||||
|
||||
# Full minimal mode — disable all four categories at once:
|
||||
# Full minimal mode — disable all five categories at once:
|
||||
set -U __fish_config_opinionated 0
|
||||
|
||||
# Re-enable everything:
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# SYNOPSIS
|
||||
# __fish_config_logging_changed
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Event handler that fires in every running shell when
|
||||
# __fish_config_op_logging is set or erased. Delegates to
|
||||
# __fish_config_sync_logging to update the Kitty sentinel file and
|
||||
# paru/yay wrappers immediately without requiring a shell restart.
|
||||
#
|
||||
# RETURNS
|
||||
# 0 Always
|
||||
#
|
||||
# EXAMPLE
|
||||
# set -U __fish_config_op_logging 0 # triggers this automatically
|
||||
function __fish_config_logging_changed --on-variable __fish_config_op_logging \
|
||||
--description 'C5 event handler: sync logging state when __fish_config_op_logging changes'
|
||||
__fish_config_sync_logging
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# SYNOPSIS
|
||||
# __fish_config_opinionated_changed
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Event handler that fires in every running shell when
|
||||
# __fish_config_opinionated (the master opinionated switch) is set or
|
||||
# erased. Delegates to __fish_config_sync_logging to keep C5 logging
|
||||
# state in sync. Logging is the only category with external on-disk
|
||||
# state (sentinel file, wrapper scripts) that requires real-time
|
||||
# synchronisation when the master variable changes; C1-C4 guards
|
||||
# evaluate at call-time and need no event handler.
|
||||
#
|
||||
# RETURNS
|
||||
# 0 Always
|
||||
#
|
||||
# EXAMPLE
|
||||
# set -U __fish_config_opinionated 0 # triggers this automatically
|
||||
function __fish_config_opinionated_changed --on-variable __fish_config_opinionated \
|
||||
--description 'C5 event handler: sync logging state when master opinionated switch changes'
|
||||
__fish_config_sync_logging
|
||||
end
|
||||
@@ -0,0 +1,99 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# SYNOPSIS
|
||||
# __fish_config_sync_logging
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Synchronises C5 logging state: creates or removes the Kitty sentinel
|
||||
# file ($XDG_CONFIG_HOME/fish/.logging_disabled) and generates or removes
|
||||
# the paru/yay AUR-helper log wrappers based on the combined value of
|
||||
# __fish_config_opinionated (master) and __fish_config_op_logging (C5).
|
||||
# Called by --on-variable event handlers whenever either variable changes.
|
||||
# Safe to call at any time; wrapper removal only affects files bearing
|
||||
# the generated version-marker comment.
|
||||
#
|
||||
# RETURNS
|
||||
# 0 Always
|
||||
#
|
||||
# EXAMPLE
|
||||
# __fish_config_sync_logging
|
||||
function __fish_config_sync_logging --description 'Sync C5 logging state: sentinel file and paru/yay wrappers'
|
||||
set -l config_home $XDG_CONFIG_HOME
|
||||
if test -z "$config_home"
|
||||
set config_home "$HOME/.config"
|
||||
end
|
||||
set -l sentinel "$config_home/fish/.logging_disabled"
|
||||
set -l paru_wrapper "$HOME/.local/bin/paru"
|
||||
set -l yay_wrapper "$HOME/.local/bin/yay"
|
||||
set -l wrapper_version 1
|
||||
|
||||
if __fish_config_op_enabled __fish_config_op_logging
|
||||
# Logging enabled: remove sentinel and regenerate wrappers if binaries exist
|
||||
rm -f $sentinel
|
||||
|
||||
if test -x /usr/bin/paru
|
||||
mkdir -p (dirname $paru_wrapper)
|
||||
printf '%s\n' \
|
||||
'#!/usr/bin/env bash' \
|
||||
"# paru-wrapper-version: $wrapper_version" \
|
||||
'# Auto-generated by conf.d/paru-wrapper.fish — do not edit by hand.' \
|
||||
'# Tees paru output to a timestamped log file and prunes old ones.' \
|
||||
'set -o pipefail' \
|
||||
'' \
|
||||
'log_dir="${SCROLLBACK_HISTORY_DIR:-$HOME/.terminal_history}"' \
|
||||
'mkdir -p "$log_dir"' \
|
||||
'log_file="$log_dir/paru_$(date +%Y-%m-%d_%H-%M-%S).log"' \
|
||||
'' \
|
||||
'/usr/bin/paru "$@" 2>&1 | tee "$log_file"' \
|
||||
'' \
|
||||
'max_files="${SCROLLBACK_HISTORY_MAX_FILES:-100}"' \
|
||||
'mapfile -t logs < <(ls -1t "$log_dir"/paru_*.log 2>/dev/null)' \
|
||||
'excess=$(( ${#logs[@]} - max_files ))' \
|
||||
'for (( i = ${#logs[@]} - 1; i >= ${#logs[@]} - excess && i >= 0; i-- )); do' \
|
||||
' rm -f "${logs[$i]}"' \
|
||||
'done' \
|
||||
>$paru_wrapper
|
||||
chmod +x $paru_wrapper
|
||||
end
|
||||
|
||||
if test -x /usr/bin/yay
|
||||
mkdir -p (dirname $yay_wrapper)
|
||||
printf '%s\n' \
|
||||
'#!/usr/bin/env bash' \
|
||||
"# yay-wrapper-version: $wrapper_version" \
|
||||
'# Auto-generated by conf.d/yay-wrapper.fish — do not edit by hand.' \
|
||||
'# Tees yay output to a timestamped log file and prunes old ones.' \
|
||||
'set -o pipefail' \
|
||||
'' \
|
||||
'log_dir="${SCROLLBACK_HISTORY_DIR:-$HOME/.terminal_history}"' \
|
||||
'mkdir -p "$log_dir"' \
|
||||
'log_file="$log_dir/yay_$(date +%Y-%m-%d_%H-%M-%S).log"' \
|
||||
'' \
|
||||
'/usr/bin/yay "$@" 2>&1 | tee "$log_file"' \
|
||||
'' \
|
||||
'max_files="${SCROLLBACK_HISTORY_MAX_FILES:-100}"' \
|
||||
'mapfile -t logs < <(ls -1t "$log_dir"/yay_*.log 2>/dev/null)' \
|
||||
'excess=$(( ${#logs[@]} - max_files ))' \
|
||||
'for (( i = ${#logs[@]} - 1; i >= ${#logs[@]} - excess && i >= 0; i-- )); do' \
|
||||
' rm -f "${logs[$i]}"' \
|
||||
'done' \
|
||||
>$yay_wrapper
|
||||
chmod +x $yay_wrapper
|
||||
end
|
||||
else
|
||||
# Logging disabled: create sentinel and remove any generated wrappers
|
||||
mkdir -p (dirname $sentinel)
|
||||
touch $sentinel
|
||||
|
||||
if test -f $paru_wrapper
|
||||
and grep -q "# paru-wrapper-version:" $paru_wrapper 2>/dev/null
|
||||
rm -f $paru_wrapper
|
||||
end
|
||||
|
||||
if test -f $yay_wrapper
|
||||
and grep -q "# yay-wrapper-version:" $yay_wrapper 2>/dev/null
|
||||
rm -f $yay_wrapper
|
||||
end
|
||||
end
|
||||
end
|
||||
+36
-33
@@ -48,49 +48,52 @@ function smart_exit --description 'Capture colorized scrollback before exiting,
|
||||
return 0
|
||||
end
|
||||
|
||||
set -l snapshot_dir (set -q SCROLLBACK_HISTORY_DIR; and echo $SCROLLBACK_HISTORY_DIR; or echo "$HOME/.terminal_history")
|
||||
set -l max_files (set -q SCROLLBACK_HISTORY_MAX_FILES; and echo $SCROLLBACK_HISTORY_MAX_FILES; or echo 100)
|
||||
# C5 — Logging & Capture: skip all capture when logging is disabled
|
||||
if __fish_config_op_enabled __fish_config_op_logging
|
||||
set -l snapshot_dir (set -q SCROLLBACK_HISTORY_DIR; and echo $SCROLLBACK_HISTORY_DIR; or echo "$HOME/.terminal_history")
|
||||
set -l max_files (set -q SCROLLBACK_HISTORY_MAX_FILES; and echo $SCROLLBACK_HISTORY_MAX_FILES; or echo 100)
|
||||
|
||||
# Handle Scrollback Capture (Skipped if -n/--no-log is used)
|
||||
if not set -q _flag_no_log
|
||||
mkdir -p $snapshot_dir
|
||||
set -l timestamp (date "+%Y-%m-%d_%H-%M-%S")
|
||||
set -l filename "$snapshot_dir/scrollback_$timestamp.log"
|
||||
# Handle Scrollback Capture (Skipped if -n/--no-log is used)
|
||||
if not set -q _flag_no_log
|
||||
mkdir -p $snapshot_dir
|
||||
set -l timestamp (date "+%Y-%m-%d_%H-%M-%S")
|
||||
set -l filename "$snapshot_dir/scrollback_$timestamp.log"
|
||||
|
||||
# Safe child process detection
|
||||
set -l active_tui (ps -o comm= --ppid $fish_pid 2>/dev/null)
|
||||
# Safe child process detection
|
||||
set -l active_tui (ps -o comm= --ppid $fish_pid 2>/dev/null)
|
||||
|
||||
if test -n "$KITTY_WINDOW_ID"
|
||||
# LIVE BUFFER CHECK: Check the active token variable $_
|
||||
# If the user typed exit, $_ will match "exit". If flags were passed,
|
||||
# we check if it contains the phrase "exit" to match 'exit -n' or 'exit --help'.
|
||||
if string match -qr exit "$_"
|
||||
if not string match -qr '^(nvim|vim|vi|nano|emacs|tmux)$' "$active_tui"
|
||||
# Capture the log via the shell
|
||||
kitty @ get-text --match id:$KITTY_WINDOW_ID --extent all --ansi | sed 's/^\[38;2;[0-9;]*m//g' >$filename 2>/dev/null
|
||||
# Broadcast a window variable flag telling Kitty the log is handled
|
||||
kitty @ set-user-vars "logged_by_shell=true" 2>/dev/null
|
||||
if test -n "$KITTY_WINDOW_ID"
|
||||
# LIVE BUFFER CHECK: Check the active token variable $_
|
||||
# If the user typed exit, $_ will match "exit". If flags were passed,
|
||||
# we check if it contains the phrase "exit" to match 'exit -n' or 'exit --help'.
|
||||
if string match -qr exit "$_"
|
||||
if not string match -qr '^(nvim|vim|vi|nano|emacs|tmux)$' "$active_tui"
|
||||
# Capture the log via the shell
|
||||
kitty @ get-text --match id:$KITTY_WINDOW_ID --extent all --ansi | sed 's/^\[38;2;[0-9;]*m//g' >$filename 2>/dev/null
|
||||
# Broadcast a window variable flag telling Kitty the log is handled
|
||||
kitty @ set-user-vars "logged_by_shell=true" 2>/dev/null
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# 4. Prune junk logs before counting toward the max
|
||||
_scrollback_prune_junk $snapshot_dir
|
||||
# 4. Prune junk logs before counting toward the max
|
||||
_scrollback_prune_junk $snapshot_dir
|
||||
|
||||
# 5. Automatic Pruning Logic
|
||||
set -l current_logs $snapshot_dir/scrollback_*.log
|
||||
if test -f "$current_logs[1]"
|
||||
set -l total_files (count $current_logs)
|
||||
if test $total_files -gt $max_files
|
||||
set -l num_to_delete (math $total_files - $max_files)
|
||||
for i in (seq 1 $num_to_delete)
|
||||
rm -f $current_logs[$i]
|
||||
# 5. Automatic Pruning Logic
|
||||
set -l current_logs $snapshot_dir/scrollback_*.log
|
||||
if test -f "$current_logs[1]"
|
||||
set -l total_files (count $current_logs)
|
||||
if test $total_files -gt $max_files
|
||||
set -l num_to_delete (math $total_files - $max_files)
|
||||
for i in (seq 1 $num_to_delete)
|
||||
rm -f $current_logs[$i]
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
echo -e "$c_warn""➔""$c_reset Exiting discreetly; $c_bold""no history logs saved.""$c_reset"
|
||||
sleep 0.4
|
||||
end
|
||||
else
|
||||
echo -e "$c_warn""➔""$c_reset Exiting discreetly; $c_bold""no history logs saved.""$c_reset"
|
||||
sleep 0.4
|
||||
end
|
||||
|
||||
# Call the true system exit directly
|
||||
|
||||
Reference in New Issue
Block a user