diff --git a/bin/miaou-bash b/bin/miaou-bash index 7233a0b..1bbc137 100755 --- a/bin/miaou-bash +++ b/bin/miaou-bash @@ -8,15 +8,11 @@ readonly MIAOU_BASH_ERROR MIAOU_BASH_DEBUG # FUNCTIONS -function on_return { - # regex does not work here unfortunately! - if [[ "${BASH_COMMAND}" == 'return '* ]]; then - code=$(echo "${BASH_COMMAND}" | cut -d' ' -f2) - if [[ -n "$code" ]] && [[ "$code" -ne 0 ]]; then - trap - DEBUG - >&2 echo "${BASH_SOURCE[2]}: line ${BASH_LINENO[0]}: return $code from ${FUNCNAME[1]}" - fi - fi +# overridden function which permits backtracing of original `return` statement +function false { + >&2 echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]} false" + debug "overridden false" + builtin false } # overridden function which permits backtracing of original `exit` statement @@ -28,6 +24,17 @@ function exit { builtin exit "$code" } +function on_return { + # regex does not work here unfortunately! + if [[ "${BASH_COMMAND}" == 'return '* ]]; then + code=$(echo "${BASH_COMMAND}" | cut -d' ' -f2) + if [[ -n "$code" ]] && [[ "$code" -ne 0 ]]; then + trap - DEBUG + >&2 echo "${BASH_SOURCE[2]}: line ${BASH_LINENO[0]}: return $code from ${FUNCNAME[1]}" + fi + fi +} + function on_exit { code=${1:-0} @@ -48,8 +55,8 @@ function on_exit { unset 'stack_sources[0]' unset 'stack_sources[-1]' - if [[ "${#stack_functions[@]}" -gt 1 && "${stack_functions[1]}" == exit && "${stack_sources[1]}" == "${BASH_SOURCE[0]}" ]]; then - # the exit case scenario + if [[ "${#stack_functions[@]}" -gt 1 && "${stack_functions[1]}" =~ exit|false && "${stack_sources[1]}" == "${BASH_SOURCE[0]}" ]]; then + # the exit or false case scenario unset 'stack_functions[1]' unset 'stack_sources[1]' unset 'stack_lines[0]' @@ -70,6 +77,7 @@ function on_exit { last_source=${last_source//./"\."} # replace '.' with '\.' regex1="^$last_source: line ([0-9]+): (.*)\$" regex2="^$last_source:([0-9]+) (.*)\$" + # debug "last_error=[$last_error] <=> ${last_source}" if [[ "$last_error" =~ $regex1 || "$last_error" =~ $regex2 ]]; then line=${BASH_REMATCH[1]} message=${BASH_REMATCH[2]} @@ -80,53 +88,56 @@ function on_exit { failure_payload="${BASH_REMATCH[1]}" stack_lines[0]=$line else - - regex="^return ([0-9]*) from (.*)\$" - if [[ "$message" =~ $regex ]]; then - # return_code="${BASH_REMATCH[1]}" - funcname="${BASH_REMATCH[2]}" - # >&4 echo "RETURN DETECTED line ${stack_sources[0]} $line $funcname" - stack_sources=("${stack_sources[0]}" "${stack_sources[@]}") - stack_lines=("$line" "${stack_lines[@]}") - stack_functions=("$funcname" "${stack_functions[@]}") - - failure_type='RETURN' + if [[ "$message" == 'false' ]]; then + failure_type='FALSE' else - regex='^(.*): command not found$' + regex="^return ([0-9]*) from (.*)\$" if [[ "$message" =~ $regex ]]; then - failure_type='COMMAND NOT FOUND' - failure_payload="${BASH_REMATCH[1]}" + # return_code="${BASH_REMATCH[1]}" + funcname="${BASH_REMATCH[2]}" + # >&4 echo "RETURN DETECTED line ${stack_sources[0]} $line $funcname" + stack_sources=("${stack_sources[0]}" "${stack_sources[@]}") + stack_lines=("$line" "${stack_lines[@]}") + stack_functions=("$funcname" "${stack_functions[@]}") + + failure_type='RETURN' else - regex='^exit' + regex='^(.*): command not found$' if [[ "$message" =~ $regex ]]; then - failure_type='EXIT' + failure_type='COMMAND NOT FOUND' + failure_payload="${BASH_REMATCH[1]}" else - regex='^(.*): No such file or directory$' + regex='^exit' if [[ "$message" =~ $regex ]]; then - failure_payload="${BASH_REMATCH[1]}" - if [[ $code == 1 ]]; then - failure_type='SOURCE NOT FOUND' - stack_lines[0]=$line - code=128 # change code to 128 to remember this embedded 'source not found' issue! - else - if [[ $code == 127 ]]; then - failure_type='FILE NOT FOUND' - regex='\.sh$|\.bash$' - if [[ "$failure_payload" =~ $regex ]]; then - stack_functions[0]="${stack_functions[0]} (hint: prefer source than subshell:1)" - code=129 # change code to 128 to remember this embedded 'source not found' issue! - # >&2 echo "${last_error}" + failure_type='EXIT' + else + regex='^(.*): No such file or directory$' + if [[ "$message" =~ $regex ]]; then + failure_payload="${BASH_REMATCH[1]}" + if [[ $code == 1 ]]; then + failure_type='SOURCE NOT FOUND' + stack_lines[0]=$line + code=128 # change code to 128 to remember this embedded 'source not found' issue! + else + if [[ $code == 127 ]]; then + failure_type='FILE NOT FOUND' + regex='\.sh$|\.bash$' + if [[ "$failure_payload" =~ $regex ]]; then + stack_functions[0]="${stack_functions[0]} (hint: prefer source than subshell:1)" + code=129 # change code to 128 to remember this embedded 'source not found' issue! + # >&2 echo "${last_error}" + else + : + # >&2 echo "${last_error}" + fi else - : - # >&2 echo "${last_error}" + failure_type='UNKNOWN NOT FOUND' fi - else - failure_type='UNKNOWN NOT FOUND' fi + else + failure_type='UNKNOWN' + failure_payload="${message}" fi - else - failure_type='UNKNOWN' - failure_payload="${message}" fi fi fi @@ -167,8 +178,8 @@ function on_exit { } function debug { - $MIAOU_BASH_DEBUG && >/dev/tty echo "*********** DEBUG: $*" - true + [[ "${MIAOU_BASH_DEBUG}" == true ]] && >/dev/tty echo "*********** DEBUG: $*" || + true } function dump_failure { @@ -227,7 +238,7 @@ BASH_ARGV0="$1" && shift # to pretend script runs by itself # magic FD + delayed tee => /dev/fd/3 means delayed stderr, /dev/fd/4 remains original stderr exec 3> >(tee "$MIAOU_BASH_ERROR" >/dev/null) 4>/dev/stderr -$MIAOU_BASH_DEBUG && >/dev/tty echo '---stdout---' +debug '---stdout---' # shellcheck source=/dev/null source "$BASH_ARGV0" 2>&3 dump_success diff --git a/lib/ansi.bash b/lib/ansi.bash index 0bee431..b28a3fa 100644 --- a/lib/ansi.bash +++ b/lib/ansi.bash @@ -25,7 +25,7 @@ BG_COLORS["BLUE"]='\e[44m' BG_COLORS["PURPLE"]='\e[45m' BG_COLORS["CYAN"]='\e[46m' BG_COLORS["WHITE"]='\e[47m' -BG_COLORS["GRAY"]='\e[90m' +# BG_COLORS["GRAY"]='\e[90m' # BG_COLORS["MAGENTA"]='\e[95m' # FUNCTIONS @@ -55,7 +55,11 @@ function _style_fg { } function _style_bg { - [[ -n $1 ]] && echo "${BG_COLORS[$1]}" || true + if [[ -n "$1" ]]; then + [[ -v BG_COLORS[$1] ]] && echo "${BG_COLORS[$1]}" && return + >&2 echo "unknown BG value: $1" + false + fi } function style_ansi { diff --git a/test/stub/scenario.bash b/test/stub/scenario.bash index 1b600ae..4117235 100755 --- a/test/stub/scenario.bash +++ b/test/stub/scenario.bash @@ -7,6 +7,19 @@ readonly BASEDIR # SCENARII +function do_pipe_error { + declare -A associative + associative['A']='Abc' + [[ -v associative['A'] ]] && echo "${associative['A']}" + true +} + +function do_false { + echo before false + false + echo after false +} + function do_success { echo -n 'SUCCESS args=[' ( @@ -17,8 +30,8 @@ function do_success { source "${MIAOU_BASH_DIR}/lib/ansi.bash" local content content=$(PADDING_LEFT=2 PADDING_RIGHT=6 style_padding 'this is success') - content=$(FG=PURPLE style_ansi "$content") - BG=RED PADDING=8 style_block "$content" + content=$(FG=PURPLE BG=GRAY style_ansi "$content") + FG=BLACK BG=RED PADDING=8 style_block "$content" } function do_unbound_variable {