Files
fish-config/conf.d/paru-wrapper.fish
T
rootiest 477a4ab265 fix(logging): render AUR progress animations to clean logs via terminal emulator
pacman/paru download progress is a multi-line terminal animation: it
repaints lines in place using ANSI cursor-movement (ESC[<n>A) and
erase-line (ESC[K) sequences, not just carriage returns. The previous
line-wise regex approaches could not reconstruct this — frames either
concatenated into one giant line (CR removed) or collapsed to blanks
(CR kept), discarding the final 100% frame.

Add scripts/clean_progress_log.py, a small dependency-free terminal
screen-buffer emulator that replays the cursor movements against an
in-memory grid and dumps the final static frame, preserving SGR color
so logs still render with color in ov/bat/less -R. It also drops the
script(1) header/footer.

Both wrappers now pipe the raw PTY capture through this cleaner (bumped
to version 5), falling back to stripping only the script(1) header when
python3 is unavailable. Document the scripts/ dir and mechanism in
AGENTS.md and docs/fish-config.md.
2026-06-11 22:48:02 -04:00

81 lines
3.3 KiB
Fish

# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Generates ~/.local/bin/paru on first run (and on version bump) when
# /usr/bin/paru is installed. The wrapper runs paru in a PTY so progress
# bars are preserved, renders the captured animation to a clean static log
# (via scripts/clean_progress_log.py), and prunes old 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
# 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 5
# Skip entirely if the real paru binary isn't present
test -x $_paru_real; or return
# Check if wrapper already exists at the expected version
if test -f $_paru_wrapper
and grep -q "# paru-wrapper-version: $_paru_wrapper_version" $_paru_wrapper 2>/dev/null
set --erase _paru_real _paru_wrapper _paru_wrapper_version
return
end
mkdir -p (dirname $_paru_wrapper)
printf '%s\n' \
'#!/usr/bin/env bash' \
"# paru-wrapper-version: $_paru_wrapper_version" \
'# Auto-generated by conf.d/paru-wrapper.fish — do not edit by hand.' \
'# Runs paru in a PTY via script(1) so progress bars are preserved on screen,' \
'# then renders the captured terminal animation to a clean static log.' \
'' \
'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"' \
'' \
'# Build a safely-quoted command string for script(1).' \
'# script(1) allocates a PTY so paru detects a real terminal and shows progress.' \
'cmd_str="/usr/bin/paru"' \
'for arg in "$@"; do' \
' cmd_str+=" $(printf '"'"'%q'"'"' "$arg")"' \
'done' \
'script -q -e -c "$cmd_str" "$log_file"' \
'exit_code=$?' \
'' \
'# Render the captured terminal animation (progress bars repaint in place via' \
'# cursor moves) down to its final static frame, preserving ANSI color. Falls' \
'# back to dropping only the script(1) header/footer when python3 is missing.' \
'cleaner="${XDG_CONFIG_HOME:-$HOME/.config}/fish/scripts/clean_progress_log.py"' \
'if command -v python3 >/dev/null 2>&1 && [[ -f "$cleaner" ]]; then' \
' python3 "$cleaner" < "$log_file" > "${log_file}.tmp" 2>/dev/null && mv "${log_file}.tmp" "$log_file" || rm -f "${log_file}.tmp"' \
'else' \
' sed -i "/^Script \(started\|done\) on /d" "$log_file" 2>/dev/null || true' \
'fi' \
'' \
'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' \
'' \
'exit $exit_code' \
> $_paru_wrapper
chmod +x $_paru_wrapper
set --erase _paru_real _paru_wrapper _paru_wrapper_version