diff --git a/poc b/poc
index 428ecdb..a817402 100755
--- a/poc
+++ b/poc
@@ -49,20 +49,23 @@ function is_true {
# example: alias toto="bash -c \"[[ \\\$MIAOU_DEBUG == 'true' ]] && echo yes \\\$* || echo nope\""
function miaou_debug {
if is_true "${MIAOU_DEBUG}"; then
+ local i message="$*" padding=''
local compute_hierarchy=true
[[ ! -v miaou_debug_hierarchy ]] && miaou_debug_hierarchy=0
- local i message="$*" padding=''
+
regex='^' # starts with
[[ $miaou_debug_hierarchy -gt 0 ]] &&
[[ "${message}" =~ $regex ]] &&
- ((--miaou_debug_hierarchy)) &&
+ miaou_debug_hierarchy=$((miaou_debug_hierarchy - 1)) &&
compute_hierarchy=false
+
for ((i = 0; i < miaou_debug_hierarchy; i++)); do padding+=' '; done
>&4 builtin echo -e "\e[90m <== DEBUG ==> ${padding}\e[33m${message}\e[0m"
+
regex='[^/]>$' # does NOT end with />
is_true $compute_hierarchy &&
[[ "${message}" =~ $regex ]] &&
- ((++miaou_debug_hierarchy)) ||
+ miaou_debug_hierarchy=$((miaou_debug_hierarchy + 1)) ||
true
fi
}
@@ -117,7 +120,15 @@ function print_miaou_error {
local message
message="${source}: line ${line}: miaou_error: ${type} ${code}"
[[ -n "$payload" ]] && message+=" payload: ${payload}"
- [[ -v tmp_error ]] && miaou_debug "tmp_error=${#tmp_error[@]}" && tmp_error+=("$message") || >&2 echo "$message"
+ >&2 echo "$message"
+}
+
+function add_miaou_error {
+ local source="$1" line="$2" code="$3" type="$4" payload="${5:-}"
+ local message
+ message="${source}: line ${line}: miaou_error: ${type} ${code}"
+ [[ -n "$payload" ]] && message+=" payload: ${payload}"
+ tmp_error+=("$message")
}
function on_error {
@@ -131,11 +142,28 @@ function on_error {
if [[ ! -v failure_type ]]; then
if [[ ${BASH_COMMAND} == 'false' ]]; then
failure_type="FALSE"
+ print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}"
else
failure_type="COMMAND_ERROR"
failure_payload="${BASH_COMMAND}"
+ print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" "${failure_payload}"
+
+ miaou_debug ""
+ load_tmp_error # cannot print_miaou_error after investigation
+
+ if [[ ${#tmp_error[@]} -gt 1 ]]; then
+ local last_error regex
+ last_error="${tmp_error[-2]}" # the second latest cause previous print_miaou_error above
+
+ regex='^(.*): line ([0-9]+): (.*): command not found$'
+ if [[ $failure_code == 127 && "$last_error" =~ $regex ]]; then
+ failure_type='COMMAND_NOT_FOUND'
+ failure_payload="${BASH_REMATCH[3]}"
+ miaou_debug ""
+ fi
+ fi
+ miaou_debug ''
fi
- print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}"
fi
error_source=("${BASH_SOURCE[@]}")
@@ -153,11 +181,10 @@ function on_error {
else
miaou_debug ""
fi
-
builtin exit "$failure_code"
else
- miaou_debug ""
print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" 'SUBSHELL_ERROR' "${BASH_COMMAND}"
+ miaou_debug ""
kill -PIPE $$
fi
}
@@ -174,7 +201,7 @@ function on_pipe {
unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
- miaou_debug '' && mapfile -t tmp_error <"$MIAOU_BASH_ERROR"
+ load_tmp_error
last_error="${tmp_error[-1]}"
regex='^(.*): line ([0-9]+): miaou_error: SUBSHELL_ERROR ([0-9]+) payload: (.*)$'
@@ -247,15 +274,24 @@ function dump_stacktrace {
miaou_debug ''
}
+function load_tmp_error {
+ [[ -v tmp_error ]] && return 0
+
+ mapfile -t tmp_error <"$MIAOU_BASH_ERROR"
+ local count=${#tmp_error[@]}
+ if [[ $count == 0 ]]; then
+ miaou_debug ""
+ else
+ miaou_debug ""
+ fi
+}
+
function on_exit {
trap - RETURN
local code="${1:-0}" last_error regex
-
miaou_debug ""
- [[ ! -v tmp_error ]] &&
- miaou_debug '' &&
- mapfile -t tmp_error <"$MIAOU_BASH_ERROR"
+ load_tmp_error
if [[ -v failure_type && "$failure_type" == 'RETURN' ]]; then
last_error="${tmp_error[-1]}"
@@ -272,7 +308,7 @@ function on_exit {
miaou_debug ""
fi
- else
+ elif [[ ! -v failure_type ]]; then
if [[ $code -gt 0 && ${#tmp_error[@]} -gt 0 ]]; then
last_error="${tmp_error[-1]}"
miaou_debug ""
@@ -298,9 +334,10 @@ function on_exit {
failure_type='UNBOUND_VARIABLE'
failure_payload=$payload
- print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" "${failure_payload}"
- unset 'tmp_error[-2]' # replace previous last_error
+ add_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" "${failure_payload}"
miaou_debug ""
+ else
+ failure_type='UNKNOWN ERROR'
fi
miaou_debug ""
fi
@@ -332,6 +369,8 @@ trap 'on_exit $?' EXIT
trap 'on_pipe' PIPE
trap 'on_return' RETURN
+declare -a tmp_error # to prevent loading multiple times
+
if [[ -e /proc/$$/fd/3 ]]; then exec 4>&3 3>&-; else exec 4>/dev/tty; fi # swap fd 3 4 when fd 3 sent off
exec 3>/dev/stderr 2>"$MIAOU_BASH_ERROR"
diff --git a/test/poc.test.bash b/test/poc.test.bash
index 8be33eb..45b2dc0 100755
--- a/test/poc.test.bash
+++ b/test/poc.test.bash
@@ -24,7 +24,7 @@ function fail_type {
mapfile -t stderr <<<"$(./poc ./test/stub/scenario.bash "$1" 2>&1 >/dev/null 3>/dev/null)"
last_error="${stderr[-1]}"
- regex="^(.*): line ([0-9]+): miaou_error: $2 ([0-9]+) payload: (.*)\$"
+ regex="^(.*): line ([0-9]+): miaou_error: $2 ([0-9]+)"
[[ "${last_error}" =~ $regex ]] && success=true
# if [[ $success == true && -n "${hint_message}" ]]; then
@@ -60,13 +60,13 @@ fail_type command_not_found COMMAND_NOT_FOUND
# fail_type subshell_error COMMAND_NOT_FOUND '(hint: prefer source than subshell)'
# fail_type command_error COMMAND_ERROR
-failed=$((test_count - ${#failures[@]}))
+failed=${#failures[@]}
success=$((test_count - failed))
echo
if [[ $failed -gt 0 ]]; then
ratio=$((100 * success / test_count))
- echo "${ratio}% passed, $success succeeded, $failed failed!"
+ echo "${ratio}% passed, ${test_count} tests, ${failed} failed!"
echo failures:
for failure in "${failures[@]}"; do
echo -e "\t- $failure"