# this is sourced from a startup file, and you use a login shell to
# run a command. Avoid doing that if you want function arguments in
# your trace.
- if [[ $- != *c* ]] && ! shopt login_shell >/dev/null; then
+ if [[ $- != *c* ]] || ! shopt login_shell >/dev/null; then
shopt -s extdebug
fi
_err-trap() {
}
+#######################################
+# Internal function for err-catch-interactive.
+# Prints stack trace from interactive shell trap.
+# Usage: see err-catch-interactive
+#######################################
+
+_err-bash-trace-interactive() {
+ local ret bash_command argc pattern i
+ # We have these passed to us because they are lost inside the
+ # function.
+ ret=$1
+ bash_command="$2"
+ argc=$(( $3 - 1 ))
+ shift 3
+ argv=("$@")
+ for pattern in "${err_catch_ignore[@]}"; do
+ # shellcheck disable=SC2053
+ if [[ ${BASH_SOURCE[0]} == $pattern ]]; then
+ return 0
+ fi
+ done
+ if (( ${#FUNCNAME[@]} > _err_func_last )); then
+ echo ERR: \`$bash_command\' returned $ret
+ fi
+ _err_func_last=${#FUNCNAME[@]}
+ if (( _err_func_last > 1 )); then
+ printf " from \`%s" "${FUNCNAME[1]}"
+ if shopt extdebug >/dev/null; then
+ for ((i=argc; i >= 0; i--)); do
+ printf " %s" "${argv[i]}"
+ done
+ fi
+ printf "\' defined at %s:%s\n" "${BASH_SOURCE[1]}" "$(declare -F "${FUNCNAME[1]}"|awk "{print \$2}")"
+ return $ret
+ fi
+}
+
#######################################
# For interactive shells: on error, print stack trace and return
#
+# Note: calling line number is not available, so we print function
+# definition lines.
+#
# Globals:
# err_catch_ignore Array containing glob patterns to test against filenames to ignore
# errors from. Initialized to ignore bash-completion scripts on debian
# based systems.
-# _err_func_last Used internally.
-# _err_catch_err Used internally.
-# _err_catch_i Used internally.
-# _err_catch_ignore Used internally.
+# _err_func_last Used internally in err-bash-trace-interactive
#
-# misc: All shellcheck disables for this function are false positives.
#######################################
-# shellcheck disable=SC2120
err-catch-interactive() {
- err_catch_ignore=(
- '/etc/bash_completion.d/*'
- )
- # shellcheck disable=SC2034
+ if ! test ${err_catch_ignore+defined}; then
+ err_catch_ignore=(
+ '/etc/bash_completion.d/*'
+ '*/bash-completion/*'
+ )
+ fi
declare -i _err_func_last=0
set -E; shopt -s extdebug
# shellcheck disable=SC2154
- trap '_err_catch_err=$? _trap_bc="$BASH_COMMAND"
- _err_catch_ignore=false
- for _err_catch_i in "${err_catch_ignore[@]}"; do
- if [[ ${BASH_SOURCE[0]} == $_err_catch_i ]]; then
- _err_catch_ignore=true
- break
- fi
- done
- if ! $_err_catch_ignore; then
- if (( ${#FUNCNAME[@]} > _err_func_last )); then
- echo ERR: \`$_trap_bc'"\'"' returned $_err_catch_err
- fi
- _err_func_last=${#FUNCNAME[@]}
- if (( _err_func_last )); then
- printf " from %s:%s:in \`%s" "${BASH_SOURCE[0]}" "$(declare -F "${FUNCNAME[0]}"|awk "{print \$2}")" "${FUNCNAME[0]}"
- if shopt extdebug >/dev/null; then
- for ((_err_catch_i=${BASH_ARGC[0]}-1; _err_catch_i >= 0; _err_catch_i--)); do
- printf " %s" "${BASH_ARGV[_err_catch_i]}"
- done
- fi
- echo '"\'"'
- return $_err_catch_err
- fi
- fi' ERR
+ trap '_err-bash-trace-interactive $? "$BASH_COMMAND" ${BASH_ARGC[0]} "${BASH_ARGV[@]}"' ERR
set -o pipefail
}