2
0

Scripts update to visualize errors better.

This commit is contained in:
Maarten Billemont 2018-06-05 12:49:03 -04:00
parent af4d7c4bc9
commit 788d85178d
3 changed files with 231 additions and 77 deletions

View File

@ -66,12 +66,6 @@
# readwhile command [args] # readwhile command [args]
# Outputs the characters typed by the user into the terminal's input buffer while running the given command. # Outputs the characters typed by the user into the terminal's input buffer while running the given command.
# #
# pushqueue element ...
# Pushes the given arguments as elements onto the queue.
#
# popqueue
# Pops one element off the queue.
#
# log [format] [arguments...] # log [format] [arguments...]
# Log an event at a certain importance level. # Log an event at a certain importance level.
# The event is expressed as a printf(1) format argument. # The event is expressed as a printf(1) format argument.
@ -85,7 +79,7 @@
# reverse [-0|-d delimitor] [elements ...] [<<< elements] # reverse [-0|-d delimitor] [elements ...] [<<< elements]
# Reverse the order of the given elements. # Reverse the order of the given elements.
# #
# order [-0|-d char] [-[cC] isAscending|-n] [-t number] [elements ...] [<<< elements] # order [-0|-d char] [-[cC] comparator|-n] [-t number] [elements ...] [<<< elements]
# Orders the elements in ascending order. # Orders the elements in ascending order.
# #
# mutex file # mutex file
@ -180,6 +174,9 @@ genToc() {
# | .: GLOBAL DECLARATIONS :. | # | .: GLOBAL DECLARATIONS :. |
# |______________________________________________________________________| # |______________________________________________________________________|
# Environment
TMPDIR=${TMPDIR:-/tmp} TMPDIR=${TMPDIR%/}
# Variables for convenience sequences. # Variables for convenience sequences.
bobber=( '.' 'o' 'O' 'o' ) bobber=( '.' 'o' 'O' 'o' )
spinner=( '-' \\ '|' '/' ) spinner=( '-' \\ '|' '/' )
@ -190,8 +187,8 @@ runner=( '> >' \
# Variables for terminal requests. # Variables for terminal requests.
[[ -t 2 && $TERM != dumb ]] && { [[ -t 2 && $TERM != dumb ]] && {
COLUMNS=$( tput cols || tput co ) # Columns in a line COLUMNS=$({ tput cols || tput co;} 2>&3) # Columns in a line
LINES=$( tput lines || tput li ) # Lines on screen LINES=$({ tput lines || tput li;} 2>&3) # Lines on screen
alt=$( tput smcup || tput ti ) # Start alt display alt=$( tput smcup || tput ti ) # Start alt display
ealt=$( tput rmcup || tput te ) # End alt display ealt=$( tput rmcup || tput te ) # End alt display
hide=$( tput civis || tput vi ) # Hide cursor hide=$( tput civis || tput vi ) # Hide cursor
@ -230,7 +227,7 @@ runner=( '> >' \
tput eA; tput as; tput eA; tput as;
tput ac; tput ae; } ) # Drawing characters tput ac; tput ae; } ) # Drawing characters
back=$'\b' back=$'\b'
} ||: } 3>&2 2>/dev/null ||:
@ -264,7 +261,10 @@ chr() {
# Outputs the decimal ASCII value of the given character. # Outputs the decimal ASCII value of the given character.
# #
ord() { ord() {
printf '%d' "'$1" local str=$1 s
for (( s=0; s < ${#str}; ++s )); do
printf '%d' "'${str:s:1}"
done
} # _____________________________________________________________________ } # _____________________________________________________________________
@ -277,7 +277,10 @@ ord() {
# Outputs the hexadecimal ASCII value of the given character. # Outputs the hexadecimal ASCII value of the given character.
# #
hex() { hex() {
printf '%x' "'$1" local str=$1 s
for (( s=0; s < ${#str}; ++s )); do
printf '%02X' "'${str:s:1}"
done
} # _____________________________________________________________________ } # _____________________________________________________________________
@ -290,7 +293,10 @@ hex() {
# Outputs the character that has the given hexadecimal ASCII value. # Outputs the character that has the given hexadecimal ASCII value.
# #
unhex() { unhex() {
printf "\\x$1" local hex=$1 h
for (( h=0; h < ${#hex}; h+=2 )); do
printf "\\x${hex:h:2}"
done
} # _____________________________________________________________________ } # _____________________________________________________________________
@ -329,6 +335,26 @@ min() {
# ______________________________________________________________________
# |__ si ________________________________________________________________|
#
# si number
#
# Output a human-readable version of the number using SI units.
#
si() {
local number=$1
if (( number >= 1000000000000000 )); then printf '%dM' "$((number / 1000000000000000))"
elif (( number >= 1000000000000 )); then printf '%dM' "$((number / 1000000000000))"
elif (( number >= 1000000000 )); then printf '%dM' "$((number / 1000000000))"
elif (( number >= 1000000 )); then printf '%dM' "$((number / 1000000))"
elif (( number >= 1000 )); then printf '%dk' "$((number / 1000))"
else printf '%d' "$number"; fi
} # _____________________________________________________________________
# ______________________________________________________________________ # ______________________________________________________________________
# |__ totime ____________________________________________________________| # |__ totime ____________________________________________________________|
# #
@ -528,6 +554,50 @@ iterate() (
fi fi
) # _____________________________________________________________________ ) # _____________________________________________________________________
# _______________________________________________________________________
# |__ csvline ____________________________________________________________|
#
# csvline [-d delimiter] [-D line-delimiter]
#
# Parse a CSV record from standard input, storing the fields in the CSVLINE array.
#
# By default, a single line of input is read and parsed into comma-delimited fields.
# Fields can optionally contain double-quoted data, including field delimiters.
#
# A different field delimiter can be specified using -d. You can use -D
# to change the definition of a "record" (eg. to support NULL-delimited records).
#
csvline() {
CSVLINE=()
local line field quoted=0 delimiter=, lineDelimiter=$'\n' c
local OPTIND=1 arg
while getopts :d: arg; do
case $arg in
d) delimiter=$OPTARG ;;
esac
done
IFS= read -d "$lineDelimiter" -r line || return
while IFS= read -rn1 c; do
case $c in
\")
(( quoted = !quoted ))
continue ;;
$delimiter)
if (( ! quoted )); then
CSVLINE+=( "$field" ) field=
continue
fi ;;
esac
field+=$c
done <<< "$line"
[[ $field ]] && CSVLINE+=( "$field" ) ||:
} # _____________________________________________________________________
# ______________________________________________________________________ # ______________________________________________________________________
# |__ Logging ___________________________________________________________| # |__ Logging ___________________________________________________________|
# #
@ -551,11 +621,11 @@ iterate() (
# The closing statement also takes a format and arguments, which are displayed in the spinner. # The closing statement also takes a format and arguments, which are displayed in the spinner.
# #
log() { log() {
local exitcode=$? level=${level:-inf} supported=0 end=$'\n' type=msg conMsg= logMsg= format= colorFormat= date= info= arg= args=() colorArgs=() ruler= local exitcode=$? result=0 level=${level:-inf} supported=0 end=$'\n' type=msg conMsg= logMsg= format= colorFormat= date= info= arg= args=() colorArgs=() ruler=
# Handle options. # Handle options.
local OPTIND=1 local OPTIND=1
while getopts :tpuPrR:d:n arg; do while getopts :tpuPrR:d:nx arg; do
case $arg in case $arg in
p) p)
end='.. ' end='.. '
@ -573,13 +643,14 @@ log() {
end=$OPTARG ;; end=$OPTARG ;;
n) n)
end= ;; end= ;;
t) x)
date=$(date +"${_logDate:-%H:%M}") ;; result=$exitcode ;;
esac esac
done done
shift "$((OPTIND-1))" shift "$((OPTIND-1))"
format=$1 args=( "${@:2}" ) format=$1 args=( "${@:2}" )
(( ! ${#args[@]} )) && [[ $format ]] && { args=("$format") format=%s; local bold=; } (( ! ${#args[@]} )) && [[ $format ]] && { args=("$format") format=%s; local bold=; }
date=${_logDate+$(date +"${_logDate:-%H:%M}")}
# Level-specific settings. # Level-specific settings.
local logLevelColor local logLevelColor
@ -600,17 +671,17 @@ log() {
log FTL 'Log level %s does not exist' "$level" log FTL 'Log level %s does not exist' "$level"
exit 1 ;; exit 1 ;;
esac esac
(( ! supported )) && return "$exitcode" (( ! supported )) && return "$result"
local logColor=${_logColor:+$logLevelColor} local logColor=${_logColor:+$logLevelColor}
# Generate the log message. # Generate the log message.
case $type in case $type in
msg|startProgress) msg|startProgress)
printf -v logMsg "[${date:+%s }%-3s] $format$end" ${date:+"$date"} "$level" "${args[@]}" printf -v logMsg "${date:+%s }${_logLevel:+%-3s }$format$end" ${date:+"$date"} ${_logLevel:+"$level"} "${args[@]}"
if (( _logColor )); then if (( _logColor )); then
colorFormat=$(sed ${reset:+-e "s/$(requote "$reset")/$reset$logColor/g"} -e "s/%[^a-z]*[a-z]/$reset$bold$logColor&$reset$logColor/g" <<< "$format") colorFormat=$(sed ${reset:+-e "s/$(requote "$reset")/$reset$_logAttributes$logColor/g"} -e "s/%[^a-z]*[a-z]/$reset$_logAttributes$bold$logColor&$reset$_logAttributes$logColor/g" <<< "$format")
colorArgs=("${args[@]//$reset/$reset$bold$logColor}") colorArgs=("${args[@]//$reset/$reset$_logAttributes$bold$logColor}")
printf -v conMsg "$reset[${date:+%s }$logColor$bold%-3s$reset] $logColor$colorFormat$reset$black\$$reset$end$save" ${date:+"$date"} "$level" "${colorArgs[@]}" printf -v conMsg "$reset$_logAttributes${date:+%s }${_logLevel:+$logColor$bold%-3s$reset $_logAttributes}$logColor$colorFormat$reset$_logAttributes$black\$$reset$end$save" ${date:+"$date"} ${_logLevel:+"$level"} "${colorArgs[@]}"
else else
conMsg=$logMsg conMsg=$logMsg
fi fi
@ -619,15 +690,17 @@ log() {
updateProgress) updateProgress)
printf -v logMsg printf " [$format]" "${args[@]}" printf -v logMsg printf " [$format]" "${args[@]}"
if (( _logColor )); then if (( _logColor )); then
colorFormat=$(sed ${reset:+-e "s/$(requote "$reset")/$reset$logColor/g"} -e "s/%[^a-z]*[a-z]/$reset$bold$logColor&$reset$logColor/g" <<< "$format") colorFormat=$(sed ${reset:+-e "s/$(requote "$reset")/$reset$_logAttributes$logColor/g"} -e "s/%[^a-z]*[a-z]/$reset$_logAttributes$bold$logColor&$reset$_logAttributes$logColor/g" <<< "$format")
colorArgs=("${args[@]//$reset/$reset$bold$logColor}") colorArgs=("${args[@]//$reset/$reset$_logAttributes$bold$logColor}")
printf -v conMsg "$load$eel$blue$bold[$reset$logColor$colorFormat$reset$blue$bold]$reset$end" "${colorArgs[@]}" printf -v conMsg "$load$eel$blue$bold[$reset$_logAttributes$logColor$colorFormat$reset$_logAttributes$blue$bold]$reset$end" "${colorArgs[@]}"
else else
conMsg=$logMsg conMsg=$logMsg
fi fi
;; ;;
stopProgress) stopProgress)
kill -0 "$_logSpinner" 2>/dev/null || return
case $exitcode in case $exitcode in
0) printf -v logMsg "done${format:+ ($format)}.\n" "${args[@]}" 0) printf -v logMsg "done${format:+ ($format)}.\n" "${args[@]}"
if (( _logColor )); then if (( _logColor )); then
@ -653,15 +726,17 @@ log() {
# Create the log file. # Create the log file.
if [[ $_logFile && ! -e $_logFile ]]; then if [[ $_logFile && ! -e $_logFile ]]; then
[[ $_logFile = */* ]] || $_logFile=./$logFile [[ $_logFile = */* ]] || _logFile=./$_logFile
mkdir -p "${_logFile%/*}" && touch "$_logFile" mkdir -p "${_logFile%/*}" && touch "$_logFile"
fi fi
# Stop the spinner. # Stop the spinner.
if [[ $type = stopProgress && $_logSpinner ]]; then if [[ $type = stopProgress && $_logSpinner ]]; then
kill "$_logSpinner" {
wait "$_logSpinner" 2>/dev/null kill "$_logSpinner" ||:
unset _logSpinner wait "$_logSpinner" ||:
unset _logSpinner
} 2>/dev/null
fi fi
# Output the ruler. # Output the ruler.
@ -685,9 +760,10 @@ log() {
while printf >&2 "$eel$blue$bold[$reset%s$reset$blue$bold]$reset\b\b\b" "${spinner[s++ % ${#spinner[@]}]}" && sleep .1 while printf >&2 "$eel$blue$bold[$reset%s$reset$blue$bold]$reset\b\b\b" "${spinner[s++ % ${#spinner[@]}]}" && sleep .1
do :; done do :; done
} & _logSpinner=$! } & _logSpinner=$!
addtrap EXIT 'level=%q _logSpinner=%q golp' "$level" "$_logSpinner"
fi fi
return $exitcode return $result
} }
trc() { level=TRC log "$@"; } trc() { level=TRC log "$@"; }
dbg() { level=DBG log "$@"; } dbg() { level=DBG log "$@"; }
@ -718,6 +794,8 @@ rrep() { level=ERR golp "$@"; }
ltfp() { level=FTL golp "$@"; } ltfp() { level=FTL golp "$@"; }
_logColor=${_logColor:-$([[ -t 2 ]] && echo 1)} _logVerbosity=2 _logColor=${_logColor:-$([[ -t 2 ]] && echo 1)} _logVerbosity=2
_logTrcColor=$grey _logDbgColor=$blue _logInfColor=$white _logWrnColor=$yellow _logErrColor=$red _logFtlColor=$bold$red _logTrcColor=$grey _logDbgColor=$blue _logInfColor=$white _logWrnColor=$yellow _logErrColor=$red _logFtlColor=$bold$red
#_logDate=%H:%M # Set this to enable date output in log messages.
#_logLevel=1 # Set this to enable level output in log messages.
# _______________________________________________________________________ # _______________________________________________________________________
@ -794,10 +872,10 @@ ask() {
printf '%s' "$muteChar" >&$fd printf '%s' "$muteChar" >&$fd
done done
REPLY=$reply REPLY=$reply
[[ $options && $REPLY ]] || (( silent )) && printf '\n' >&$fd
else else
read -u8 -e ${options:+-n1} ${silent:+-s} read -u8 -e ${options:+-n1} ${silent:+-s}
fi fi
[[ $options && $REPLY ]] || (( silent )) && printf '\n' >&$fd
# Evaluate the reply. # Evaluate the reply.
while true; do while true; do
@ -886,7 +964,7 @@ reverse() {
# ______________________________________________________________________ # ______________________________________________________________________
# |__ Order _____________________________________________________________| # |__ Order _____________________________________________________________|
# #
# order [-0|-d char] [-[fF] isDesired] [-[cC] isAscending|-n|-r|-t] [-T number] [-a array|elements ...] [<<< elements] # order [-0|-d char] [-[fF] isDesired] [-[cC] comparator|-n|-R|-t] [-r] [-T number] [-a array|elements ...] [<<< elements]
# #
# Orders the elements in ascending order. # Orders the elements in ascending order.
# Elements are read from command arguments or standard input if no element # Elements are read from command arguments or standard input if no element
@ -895,21 +973,23 @@ reverse() {
# #
# By default, the elements will be ordered using lexicographic comparison. # By default, the elements will be ordered using lexicographic comparison.
# If the -n option is given, the elements will be ordered numerically. # If the -n option is given, the elements will be ordered numerically.
# If the -r option is given, the elements will be ordered randomly. # If the -R option is given, the elements will be ordered randomly.
# If the -t option is given, the elements are ordered by file mtime.
# If the -f option is given, the command name following it will be used # If the -f option is given, the command name following it will be used
# as a filter. # as a filter.
# If the -c option is given, the command name following it will be used # If the -c option is given, the command name following it will be used
# as a comparator. # as a comparator.
# If the -C option is given, the bash code following it will be used # If the -C option is given, the bash code following it will be used
# as a comparator. # as a comparator.
# If the -t option is given, only the first number results are returned. # If the -r option is given, the ordering will be reversed.
# If the -T option is given, only the first number results are returned.
# If the -a option is given, the elements in array are ordered instead and # If the -a option is given, the elements in array are ordered instead and
# array is mutated to contain the result. # array is mutated to contain the result.
# If number is 0, all results are returned. # If number is 0, all results are returned.
# #
# isDesired is a command name which will get one parameter. The parameter # isDesired is a command name which will get one parameter. The parameter
# is an element which will only be included if the command exits successfully. # is an element which will only be included if the command exits successfully.
# isAscending is a command name which will be executed for each element # comparator is a command name which will be executed for each element
# comparison and will be passed two element arguments. The command should # comparison and will be passed two element arguments. The command should
# succeed if the first argument is less than the second argument for the # succeed if the first argument is less than the second argument for the
# purpose of this sort. # purpose of this sort.
@ -924,59 +1004,61 @@ reverse() {
order() { order() {
# Initialize the vars. # Initialize the vars.
local delimitor=$'\n' i isDesired=true isAscending=string_ascends top=0 arrayName= array= local _delimitor=$'\n' _i _j _isDesired=true _comparator=string_ascends _comparator_ascends=1 _top=0 _arrayName= _array=
# Parse the options. # Parse the options.
local OPTIND=1 local OPTIND=1
while getopts :0nrd:f:F:c:C:tT:a: opt; do while getopts :0nrRd:f:F:c:C:tT:a: opt; do
case $opt in case $opt in
0) delimitor=$'\0' ;; 0) _delimitor=$'\0' ;;
d) delimitor=$OPTARG ;; d) _delimitor=$OPTARG ;;
n) isAscending=number_ascends ;; n) _comparator=number_ascends ;;
r) isAscending=random_ascends ;; R) _comparator=random_ascends ;;
t) isAscending=mtime_ascends ;; t) _comparator=mtime_ascends ;;
f) isDesired=$OPTARG ;; f) _isDesired=$OPTARG ;;
F) isDesired=bash_desired bash_desired_code=$OPTARG ;; F) _isDesired=bash_desired _bash_desired_code=$OPTARG ;;
c) isAscending=$OPTARG ;; c) _comparator=$OPTARG ;;
C) isAscending=bash_ascends bash_ascends_code=$OPTARG ;; C) _comparator=bash_ascends _bash_ascends_code=$OPTARG ;;
T) top=$OPTARG ;; r) _comparator_ascends=0 ;;
a) arrayName=$OPTARG array=$arrayName[@] ;; T) _top=$OPTARG ;;
a) _arrayName=$OPTARG _array=$_arrayName[@] ;;
esac esac
done done
shift "$((OPTIND-1))" shift "$((OPTIND-1))"
# Get the elements. # Get the elements.
local elements=() element local _elements=() _element
if [[ $arrayName ]]; then if [[ $_arrayName ]]; then
for element in "${!array}"; do for _element in "${!_array}"; do
"$isDesired" "$element" && elements+=("$element") "$_isDesired" "$_element" && _elements+=("$_element")
done done
elif (( $# )); then elif (( $# )); then
for element; do for _element; do
"$isDesired" "$element" && elements+=("$element") "$_isDesired" "$_element" && _elements+=("$_element")
done done
else else
while IFS= read -r -d "$delimitor" element; do while IFS= read -r -d "$_delimitor" _element; do
"$isDesired" "$element" && elements+=("$element") "$_isDesired" "$_element" && _elements+=("$_element")
done done
fi fi
# Iterate in reverse order. # Iterate in reverse order.
for (( i = 1; i < ${#elements[@]}; ++i )); do for (( _i = 1; _i < ${#_elements[@]}; ++_i )); do
for (( j = i; j > 0; --j )); do for (( _j = _i; _j > 0; --_j )); do
element=${elements[j]} _element=${_elements[_j]}
if "$isAscending" "$element" "${elements[j-1]}"; then if ( (( _comparator_ascends )) && "$_comparator" "$_element" "${_elements[_j-1]}" ) ||
elements[j]=${elements[j-1]} ( (( ! _comparator_ascends )) && ! "$_comparator" "$_element" "${_elements[_j-1]}" ); then
elements[j-1]=$element _elements[_j]=${_elements[_j-1]}
_elements[_j-1]=$_element
fi fi
done done
done done
(( top )) || top=${#elements[@]} (( _top )) || _top=${#_elements[@]}
if [[ $array ]]; then if [[ $_array ]]; then
declare -ga "$array=($(printf '%q ' "${elements[@]:0:top}"))" declare -ga "$_array=($(printf '%q ' "${_elements[@]:0:_top}"))"
else else
printf "%s${delimitor:-\0}" "${elements[@]:0:top}" printf "%s${_delimitor:-\0}" "${_elements[@]:0:_top}"
fi fi
} # _____________________________________________________________________ } # _____________________________________________________________________
string_ascends() { [[ $1 < $2 ]]; } string_ascends() { [[ $1 < $2 ]]; }
@ -987,8 +1069,28 @@ exists_desired() { [[ -e $1 ]]; }
line_desired() { [[ $1 ]]; } line_desired() { [[ $1 ]]; }
code_desired() { line_desired "$1" && ! comment_desired "$1"; } code_desired() { line_desired "$1" && ! comment_desired "$1"; }
comment_desired() { line_desired "$1" && [[ $1 = @(#|//|/\*)* ]]; } comment_desired() { line_desired "$1" && [[ $1 = @(#|//|/\*)* ]]; }
bash_desired() { bash -c "$bash_desired_code" -- "$@"; } bash_desired() { bash -c "$_bash_desired_code" -- "$@"; }
bash_ascends() { bash -c "$bash_ascends_code" -- "$@"; } bash_ascends() { bash -c "$_bash_ascends_code" -- "$@"; }
# ______________________________________________________________________
# |__ AddTrap _____________________________________________________________|
#
# addtrap signal command-format [args...]
#
# Add a command to the current commands executed when a signal is received by the bash process.
#
# The command-format is a printf-style format for the command to execute. The optional
# args are interpolated into the command-format by bash's built-in printf.
#
addtrap() {
local signal=$1 cmd=$2; shift 2
printf -v cmd "$cmd" "$@"
read _ _ oldtrap <<< "$(trap -p "$signal")"
eval "declare oldtrap=${oldtrap% *}"
trap "$oldtrap${oldtrap:+; }$cmd" "$signal"
}
# ______________________________________________________________________ # ______________________________________________________________________
@ -1214,18 +1316,17 @@ showHelp() {
shquote() { shquote() {
# Initialize the defaults. # Initialize the defaults.
local arg escape=0 sq="'\\''" dq='\"' quotedArgs=() type=single always=0 local OPTIND=1 arg escape=0 sq="'\\''" dq='\"' quotedArgs=() type=single always=0
# Parse the options. # Parse the options.
while [[ $1 = -* ]]; do while getopts :eda arg; do
case $1 in case $arg in
-e) type=escape ;; e) type=escape ;;
-d) type=double ;; d) type=double ;;
-a) always=1 ;; a) always=1 ;;
--) shift; break ;;
esac esac
shift
done done
shift "$((OPTIND-1))"
# Print out each argument, quoting it properly. # Print out each argument, quoting it properly.
for arg; do for arg; do
@ -1330,6 +1431,29 @@ shorten() {
# ______________________________________________________________________
# |__ CdSource ________________________________________________________________|
#
# cdsource [file]
#
# Change the current directory into the directory where the file is located, resolving symlinks.
#
cdsource() {
local source=${1:-${BASH_SOURCE[1]}}
while [[ $source ]]; do
[[ $source = */* ]] && cd "${source%/*}"
if [[ -L ${source##*/} ]]; then
source=$(readlink "${source##*/}")
else
source=
fi
done
} # _____________________________________________________________________
# ______________________________________________________________________ # ______________________________________________________________________
# |__ Up ________________________________________________________________| # |__ Up ________________________________________________________________|
# #
@ -1405,7 +1529,34 @@ inArray() {
# Perform the search. # Perform the search.
for element for element
do [[ $element = $search ]] && return 0; done do [[ "$element" = "$search" ]] && return 0; done
return 1
} # _____________________________________________________________________
# ______________________________________________________________________
# |__ IndexOf ___________________________________________________________|
#
# indexOf element array
#
# Outputs the index of the given element in the given array.
#
# element The element to search the array for.
# array This is a list of elements to search through.
#
indexOf() {
# Parse the options.
local element index=0
local search=$1; shift
# Perform the search.
for element
do
[[ $element = $search ]] && echo "$index" && return 0
let ++index
done
return 1 return 1
} # _____________________________________________________________________ } # _____________________________________________________________________

View File

@ -2,6 +2,7 @@
# See https://developer.apple.com/library/ios/qa/qa1686/_index.html # See https://developer.apple.com/library/ios/qa/qa1686/_index.html
cd "${BASH_SOURCE%/*}" cd "${BASH_SOURCE%/*}"
source bashlib source bashlib
trap 'c=$BASH_COMMAND s=$?; (( s )) && echo "ERROR: $s: $c"; exit $s' EXIT
set -e set -e
cd .. cd ..
export PATH+=:/usr/local/bin export PATH+=:/usr/local/bin

View File

@ -1,6 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
cd "${BASH_SOURCE%/*}" cd "${BASH_SOURCE%/*}"
source ./bashlib source ./bashlib
trap 'c=$BASH_COMMAND s=$?; (( s )) && echo "ERROR: $s: $c"; exit $s' EXIT
set -e
cd .. cd ..
export PATH+=:/usr/libexec export PATH+=:/usr/libexec