fix bugs
This commit is contained in:
@@ -138,7 +138,7 @@ A bar-style prompt showing current time, execution time of the last command
|
||||
| `rmspc` | filefct | Replace spaces in filenames with underscores (or a custom character) |
|
||||
| `setc` | lang | Set locale to standard C (POSIX) |
|
||||
| `setlocale` | lang | Set console locale to any installed locale |
|
||||
| `settrace` | debug | Activate or deactivate ERR trap to display backtrace on script errors |
|
||||
| `settrace` | debug | Activate (`--on`), deactivate (`--off`) or query (`--status`) an ERR trap that prints the exit status and a call stack (on stderr) for each failing command; `--force` replaces/removes an ERR trap set by something else; active at startup when `SETTRACE_DEFAULT_ENABLED=1` |
|
||||
| `showinfo` | info | Display welcome banner and system information (figlet + neofetch/fastfetch) |
|
||||
| `ssr` | ssh | SSH into a server as root, forwarding extra ssh options |
|
||||
| `taz` | compress | Compress files and directories into a chosen archive format |
|
||||
@@ -224,6 +224,12 @@ change the default without having to pass flags every time.
|
||||
| `UTAZ_DEFAULT_DIR_MODE` | `auto` | Host directory policy: `auto` (only when the archive has no single top-level directory), `always` or `never` |
|
||||
| `UTAZ_DEFAULT_IGNORE_CASE` | `0` | Set to `1` to match archive extensions case-insensitively (`.ZIP`, `.Tar.GZ`). Per call: `utaz -i` / `utaz -s` |
|
||||
|
||||
**`[debug]`** — `settrace`
|
||||
|
||||
| Key | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `SETTRACE_DEFAULT_ENABLED` | `0` | Set to `1` to activate the error trace (`settrace --on`) at the startup of every interactive shell |
|
||||
|
||||
**`[filefct]`** — file utilities
|
||||
|
||||
| Key | Default | Description |
|
||||
|
||||
@@ -14,6 +14,8 @@ Versions follow `MAJOR.MINOR.PATCH-REVISION_STAGE_N` (e.g. `3.99.1-4_rc_1`).
|
||||
- `utaz -i` / `--ignore-case` and `-s` / `--case-sensitive` switches to match
|
||||
archive extensions case-insensitively or not; the default is set by the new
|
||||
`UTAZ_DEFAULT_IGNORE_CASE` key of the `[compress]` section (default `0`).
|
||||
- `SETTRACE_DEFAULT_ENABLED` key in the new `[debug]` configuration options
|
||||
(default `0`): activates `settrace --on` at startup of interactive shells.
|
||||
- `utaz` supports bare `.zst` files and `.tzst` archives; `taz -q` is now
|
||||
effective.
|
||||
|
||||
@@ -36,6 +38,14 @@ Versions follow `MAJOR.MINOR.PATCH-REVISION_STAGE_N` (e.g. `3.99.1-4_rc_1`).
|
||||
(it selected `xterm-direct` even inside tmux/screen or VTE terminals);
|
||||
multiplexers (tmux, screen) are now checked before emulator hints, since they
|
||||
inherit the emulator's variables.
|
||||
- `debug.sh`: the trace is now written to stderr (it used to pollute captured
|
||||
`$(...)` output) and includes the exit status; `backtrace` and `error` are
|
||||
exported like `settrace`; `settrace` tells its own trap from a foreign one
|
||||
(`--status`, and `--off` no longer removes a foreign trap without `--force`);
|
||||
`--on` when already active is only a warning; `getopt` errors name the command.
|
||||
- All modules: counters updated with `((x++))`-style commands (which return a
|
||||
non-zero status when the value was 0) now use plain assignments, so they no
|
||||
longer trigger the ERR trace or break `set -e`.
|
||||
- `compress.sh`: option flags and loop variables no longer leak into the
|
||||
interactive shell.
|
||||
|
||||
|
||||
@@ -56,7 +56,11 @@ PAGER=less
|
||||
|
||||
# ==============================================================================
|
||||
[debug]
|
||||
# (no configurable keys yet)
|
||||
# Activate the error trace (settrace --on) at startup of interactive shells:
|
||||
# every failing command then prints its exit status and a call stack to stderr.
|
||||
# Verbose; meant for debugging scripts and the profile itself (0=no, 1=yes).
|
||||
# Can be toggled at any time with settrace --on / --off.
|
||||
#SETTRACE_DEFAULT_ENABLED=0
|
||||
|
||||
# ==============================================================================
|
||||
[disp]
|
||||
|
||||
@@ -42,7 +42,12 @@ TERM=xterm-256color
|
||||
#UTAZ_DEFAULT_IGNORE_CASE=0
|
||||
|
||||
[debug]
|
||||
# Section used by debug.sh (nothing yet)
|
||||
# Section used by debug.sh
|
||||
|
||||
# Activate the error trace (settrace --on) at startup of interactive shells:
|
||||
# every failing command then prints its exit status and a call stack to stderr
|
||||
# (0=no, 1=yes).
|
||||
#SETTRACE_DEFAULT_ENABLED=0
|
||||
|
||||
[disp]
|
||||
# Section used by disp.sh
|
||||
|
||||
+79
-21
@@ -37,48 +37,62 @@
|
||||
load_conf "debug"
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Display a backtrace
|
||||
# Display a backtrace of the current call stack (innermost frame first), one
|
||||
# line per frame: function, file where it is defined, line of the call site.
|
||||
# Usage: backtrace
|
||||
backtrace()
|
||||
{
|
||||
printf "========= Call stack =========\n"
|
||||
local i=1 # We begin at 1 to ignore backtrace itself
|
||||
while [[ $i -lt ${#FUNCNAME[@]} ]]; do
|
||||
# BASH_SOURCE[i] is the file defining FUNCNAME[i], and BASH_LINENO[i-1]
|
||||
# the line of that file from which FUNCNAME[i-1] was called.
|
||||
printf '%15s() %s:%d\n' \
|
||||
"${FUNCNAME[$i]}" "${BASH_SOURCE[$i]}" "${BASH_LINENO[$(( i-1 ))]}"
|
||||
((i++))
|
||||
i=$(( i + 1 ))
|
||||
done
|
||||
unset i
|
||||
printf "==============================\n"
|
||||
}
|
||||
export -f backtrace
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Function to be trapped for errors investigation
|
||||
# Handler installed by settrace as ERR trap: report the failure and the call
|
||||
# stack, then give back the exit status of the failed command so the trap does
|
||||
# not alter the shell behaviour (e.g. under "set -e").
|
||||
# Everything goes to stderr: with errtrace a failure inside $(...) or a pipe
|
||||
# would otherwise inject the trace into the captured output.
|
||||
# Exported because an exported settrace may be used from child bash processes,
|
||||
# where the trap needs this function to exist.
|
||||
error()
|
||||
{
|
||||
local errcode=$?
|
||||
backtrace
|
||||
printf "Command failed with exit status %d\n" "$errcode" >&2
|
||||
backtrace >&2
|
||||
return $errcode
|
||||
}
|
||||
export -f error
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Activate or deactivate error trapping to display backtrace
|
||||
# Usage: settrace <--on|--off|--status>
|
||||
# Usage: settrace <--on|--off|--status> [--force]
|
||||
# Startup behaviour is set by SETTRACE_DEFAULT_ENABLED in the [debug] section.
|
||||
settrace()
|
||||
{
|
||||
local PARSED
|
||||
PARSED=$(getopt -oh --long help,on,off,status,force -- "$@")
|
||||
PARSED=$(getopt -oh --long help,on,off,status,force -n settrace -- "$@")
|
||||
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
||||
if [[ $? -ne 0 ]]; then
|
||||
disp E "Invalid options, use \"settrace --help\" to display usage."
|
||||
return 1
|
||||
fi
|
||||
local -a _pargs=()
|
||||
readarray -td '' _pargs < <(printf '%s' "$PARSED" | xargs printf '%s\0')
|
||||
set -- "${_pargs[@]}"
|
||||
# getopt emits a shell-quoted, normalised argument list ("--" ends options)
|
||||
eval set -- "$PARSED"
|
||||
|
||||
# First pass: gather the requested action and flags. --on, --off and
|
||||
# --status are mutually exclusive; --force only modifies --on.
|
||||
# --status are mutually exclusive; --force only modifies --on and --off.
|
||||
local action="" force=0
|
||||
while true; do
|
||||
case $1 in
|
||||
@@ -86,11 +100,14 @@ settrace()
|
||||
printf "Try to activate backtrace display for script debugging.\n\n"
|
||||
printf "Options:\n"
|
||||
printf "\t--on\t\tActivate backtrace generation\n"
|
||||
printf "\t--force\t\tForce replacement of existing trap (use with --on)\n"
|
||||
printf "\t--force\t\tReplace (with --on) or remove (with --off) an ERR trap\n"
|
||||
printf "\t\t\tnot installed by settrace\n"
|
||||
printf "\t--off\t\tDeactivate backtrace generation\n"
|
||||
printf "\t--status\tDisplay whether the ERR trap is set\n\n"
|
||||
printf "That function active a trap event on error. If the script you want to\n"
|
||||
printf "debug overload the ERR bash trap, it will not work.\n"
|
||||
printf "That function activates a trap event on error. If the script you want to\n"
|
||||
printf "debug overloads the ERR bash trap, it will not work.\n\n"
|
||||
printf "To activate it at every interactive startup, set SETTRACE_DEFAULT_ENABLED=1\n"
|
||||
printf "in the [debug] section of the profile configuration.\n"
|
||||
return 0
|
||||
;;
|
||||
--on|--off|--status)
|
||||
@@ -117,25 +134,48 @@ settrace()
|
||||
done
|
||||
|
||||
# Second pass: evaluate the current trap state, then apply the action.
|
||||
local status="off"
|
||||
[[ -n $(trap -p ERR) ]] && status="on"
|
||||
# "trap -p ERR" prints the exact command line that re-creates the trap, so
|
||||
# comparing it tells our own trap ("on") from one set by someone else
|
||||
# ("foreign"); empty output means no trap at all ("off").
|
||||
# Limitation: bash hides the ERR trap from code running in a function (and
|
||||
# its subshells) unless errtrace is set. Our own trap is always seen since
|
||||
# settrace sets errtrace with it, but a foreign trap set without errtrace is
|
||||
# reported as "off" (and can then be replaced without --force).
|
||||
local status="off" current
|
||||
current=$(trap -p ERR)
|
||||
if [[ -n $current ]]; then
|
||||
status="foreign"
|
||||
[[ $current == "trap -- 'error' ERR" ]] && status="on"
|
||||
fi
|
||||
|
||||
case $action in
|
||||
on)
|
||||
if [[ $status == "on" && $force -eq 0 ]]; then
|
||||
disp E "ERR signal trap is already set. Use --force to replace it."
|
||||
if [[ $status == "on" ]]; then
|
||||
disp W "ERR signal trap is already set."
|
||||
return 0
|
||||
fi
|
||||
if [[ $status == "foreign" && $force -eq 0 ]]; then
|
||||
disp E "Another ERR signal trap is already set. Use --force to replace it."
|
||||
return 1
|
||||
fi
|
||||
# errtrace makes functions and subshells inherit the ERR trap
|
||||
set -o errtrace
|
||||
trap "error" ERR
|
||||
trap 'error' ERR
|
||||
;;
|
||||
off)
|
||||
[[ $status != "on" ]] && disp W "ERR signal trap is already unset!"
|
||||
if [[ $status == "foreign" && $force -eq 0 ]]; then
|
||||
disp E "The ERR signal trap was not set by settrace. Use --force to remove it."
|
||||
return 1
|
||||
fi
|
||||
[[ $status == "off" ]] && disp W "ERR signal trap is already unset!"
|
||||
trap - ERR
|
||||
set +o errtrace
|
||||
;;
|
||||
status)
|
||||
disp I "Trap signal on error is ${status}."
|
||||
case $status in
|
||||
foreign) disp I "Trap signal on error is set, but not by settrace." ;;
|
||||
*) disp I "Trap signal on error is ${status}." ;;
|
||||
esac
|
||||
;;
|
||||
"")
|
||||
disp E "No action specified, use \"settrace --help\" to display usage."
|
||||
@@ -147,4 +187,22 @@ export -f settrace
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Optional trace activation at startup (SETTRACE_DEFAULT_ENABLED, default 0).
|
||||
# Interactive shells only: this file is sourced by non-interactive shells too,
|
||||
# where an ERR trap would add noise to scripts. [[ $- == *i* ]] is used because
|
||||
# profile.sh sets INTERACTIVE only after the modules are loaded.
|
||||
# disp is not defined yet (modules load alphabetically), so the trap is set only
|
||||
# when none exists, a path that never calls disp. An existing trap is left alone.
|
||||
# Written as "if" so the sourcing status stays 0 when nothing is done.
|
||||
case "${SETTRACE_DEFAULT_ENABLED:-0}" in
|
||||
1|[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn])
|
||||
if [[ $- == *i* && -z $(trap -p ERR) ]]; then
|
||||
settrace --on
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# EOF
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@ disp()
|
||||
local _c=${message:_i:1}
|
||||
_i=$(( _i + 1 ))
|
||||
line+=$_c
|
||||
(( line_vis++ ))
|
||||
(( ++line_vis ))
|
||||
[[ $_c == ' ' ]] && last_space=${#line}
|
||||
if (( line_vis > width )); then
|
||||
if (( last_space > 0 )); then
|
||||
|
||||
+2
-2
@@ -234,7 +234,7 @@ pinfo()
|
||||
[[ "$cpu_model" == "unknown" ]] && cpu_model="${_cpu_line#*: }"
|
||||
;;
|
||||
"processor"*)
|
||||
(( cpu_threads++ ))
|
||||
cpu_threads=$(( cpu_threads + 1 ))
|
||||
;;
|
||||
"physical id"*)
|
||||
_cur_phys="${_cpu_line#*: }"
|
||||
@@ -269,7 +269,7 @@ pinfo()
|
||||
# --- Process count (glob over numeric /proc entries) ---
|
||||
local proc_count=0 _pdir
|
||||
for _pdir in /proc/[0-9]*/; do
|
||||
[[ -d "$_pdir" ]] && (( proc_count++ ))
|
||||
[[ -d "$_pdir" ]] && proc_count=$(( proc_count + 1 ))
|
||||
done
|
||||
|
||||
# --- Shell and terminal ---
|
||||
|
||||
+1
-1
@@ -295,7 +295,7 @@ isipv6()
|
||||
IFS=':' read -ra parts <<< "$seg"
|
||||
for part in "${parts[@]}"; do
|
||||
[[ $part =~ ^[0-9a-fA-F]{1,4}$ ]] || { ok=0; break; }
|
||||
(( total++ ))
|
||||
total=$(( total + 1 ))
|
||||
done
|
||||
(( ok )) || break
|
||||
done
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ load_theme()
|
||||
local _lth_line _lth_key _lth_value _lth_varname _lth_lineno=0
|
||||
|
||||
while IFS= read -r _lth_line || [[ -n "$_lth_line" ]]; do
|
||||
((_lth_lineno++))
|
||||
_lth_lineno=$(( _lth_lineno + 1 ))
|
||||
_lth_line="${_lth_line%$'\r'}" # strip CR
|
||||
_lth_line="${_lth_line#"${_lth_line%%[![:space:]]*}"}" # ltrim
|
||||
_lth_line="${_lth_line%"${_lth_line##*[![:space:]]}"}" # rtrim
|
||||
|
||||
+2
-2
@@ -234,7 +234,7 @@ genpwd()
|
||||
break
|
||||
fi
|
||||
|
||||
((attempts++))
|
||||
attempts=$(( attempts + 1 ))
|
||||
done
|
||||
done
|
||||
|
||||
@@ -256,7 +256,7 @@ genpwd()
|
||||
break
|
||||
fi
|
||||
|
||||
((attempts++))
|
||||
attempts=$(( attempts + 1 ))
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
+3
-3
@@ -300,7 +300,7 @@ _rain_engine()
|
||||
if ((100 * RANDOM / 32768 < falling_odd)); then
|
||||
if ((++rains[idx + 1] > term_height)); then
|
||||
rains=("${rains[@]:0:idx}" "${rains[@]:idx+num_rain_metadata:num_rains*num_rain_metadata}")
|
||||
((num_rains--))
|
||||
num_rains=$(( num_rains - 1 ))
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
@@ -359,7 +359,7 @@ _rain_engine()
|
||||
X=$((term_width * RANDOM / 32768 + 1))
|
||||
Y=$((1 - drop_length))
|
||||
rains=("${rains[@]}" "$X" "$Y" "$rain_drop" "$drop_color" "$drop_length")
|
||||
((num_rains++))
|
||||
num_rains=$(( num_rains + 1 ))
|
||||
fi
|
||||
|
||||
do_render
|
||||
@@ -684,7 +684,7 @@ rainbow()
|
||||
for ((col = 0; col < term_width; col++)); do
|
||||
idx=$((col - offset))
|
||||
while ((idx < 0)); do
|
||||
((idx += palette_width))
|
||||
idx=$(( idx + palette_width ))
|
||||
done
|
||||
idx=$((idx % palette_width))
|
||||
row_line+="${RAINBOW_BG_PALETTE[idx]} "
|
||||
|
||||
Reference in New Issue
Block a user