From 5b808d6750dd119180f4bc916d6af05ef691bda1 Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 10:22:35 -0700 Subject: [PATCH 01/11] Document the intent. --- scripts/lib/bashy-core/arg-processor.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/lib/bashy-core/arg-processor.sh b/scripts/lib/bashy-core/arg-processor.sh index 49ecb9b..6b1a9b0 100644 --- a/scripts/lib/bashy-core/arg-processor.sh +++ b/scripts/lib/bashy-core/arg-processor.sh @@ -266,8 +266,10 @@ function post-process-args-call { } # Processes all of the given arguments, according to the configured handlers. -# Returns non-zero if there is trouble parsing options or if any handler returns -# non-zero. +# Returns normally upon successful processing. If there is any trouble parsing +# (including if there were errors during argument/option declaration), this +# prints the short form of the `usage` message (if `usage` is available) and +# then exits the process entirely with a non-zero code. function process-args { local _argproc_error=0 local _argproc_s From 453914405aea75b6941d73a91da4ae0bcdd02917 Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 10:31:45 -0700 Subject: [PATCH 02/11] Make `process-args` actually `exit` if there was trouble. As far as I know, this is what every use site already does, except that it requires extra boilerplate. --- scripts/lib/bashy-core/arg-processor.sh | 32 +++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/scripts/lib/bashy-core/arg-processor.sh b/scripts/lib/bashy-core/arg-processor.sh index 6b1a9b0..cbaa6ba 100644 --- a/scripts/lib/bashy-core/arg-processor.sh +++ b/scripts/lib/bashy-core/arg-processor.sh @@ -275,8 +275,7 @@ function process-args { local _argproc_s if (( _argproc_declarationError )); then - error-msg 'Cannot process arguments, due to declaration errors.' - return 1 + _argproc_error-exit 'Cannot process arguments, due to declaration errors.' fi # Run all the pre-parse statements. @@ -297,7 +296,7 @@ function process-args { # Don't continue if there were problems above, because that will lead to # spurious extra errors (e.g. "missing" a required option that was # present but didn't pass a validity check). - return "${_argproc_error}" + _argproc_error-exit --code="${_argproc_error}" fi # Do any post-parse checks. @@ -305,7 +304,9 @@ function process-args { eval "${_argproc_s}" || _argproc_error="$?" done - return "${_argproc_error}" + if (( _argproc_error )); then + _argproc_error-exit --code="${_argproc_error}" + fi } # Requires that exactly one of the indicated arguments / options is present. @@ -569,6 +570,29 @@ function _argproc_define-value-taking-arg { fi } +# Does an error-exit, printing `usage` if available. +function _argproc_error-exit { + local exitCode=1 + + if [[ $1 =~ ^--code= ]]; then + exitCode="${1#*=}" + shift + fi + + local msg=("$@") + + if (( ${#msg[@]} != 0 )); then + error-msg "${msg[@]}" + fi + + if declare -F usage >/dev/null; then + error-msg '' + usage --short + fi + + exit "${exitCode}" +} + # Produces an argument handler body, from the given components. function _argproc_handler-body { local longName="$1" From 803c8d5f2bb092a00d89822c86dfda0dc14d2aea Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 10:38:58 -0700 Subject: [PATCH 03/11] Better reporting. --- tests/run-all | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/run-all b/tests/run-all index c9eb8c0..62919e7 100755 --- a/tests/run-all +++ b/tests/run-all @@ -38,16 +38,29 @@ if [[ ${allRunScripts[0]} == 'error' ]]; then exit 1 fi -errors=0 +errors=() for run in "${allRunScripts[@]}"; do - "${testsDir}/run-one" "${run%/run}" \ - || (( errors++ )) + testName="${run%/run}" + "${testsDir}/run-one" "${testName}" \ + || errors+=("${testName}") done -if (( errors == 0 )); then +errorCount="${#errors[@]}" + +echo '' + +if (( errorCount == 0 )); then echo 'All passed. Yay!' else - (( errors == 1 )) && noun=error || noun=errors - echo "${errors} ${noun}. Alas." + echo 'Problems with:' + + for e in "${errors[@]}"; do + echo " ${e}" + done + + (( errorCount == 1 )) && noun=error || noun=errors + echo '' + echo "${errorCount} ${noun}. Alas." + exit 1 fi From 6f0c177c03582a133a2c356eda61c6b82c6bb151 Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 10:39:12 -0700 Subject: [PATCH 04/11] Drop the extra line. The effect is now achieved elsewhere. --- scripts/lib/bashy-core/helpy/print-usage | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/lib/bashy-core/helpy/print-usage b/scripts/lib/bashy-core/helpy/print-usage index 98dddde..724a27b 100755 --- a/scripts/lib/bashy-core/helpy/print-usage +++ b/scripts/lib/bashy-core/helpy/print-usage @@ -33,9 +33,9 @@ define-usage --with-help $' --short Prints a short version of the , intended to be the coda on some other error message. This only prints double-newline delimited sections - whose first line starts with the value of `$${name}`. In addition, it - prepends an extra newline at the start. Note: For this to work as intended, - always put a double-newline after each command summary section. + whose first line starts with the value of `$${name}`. Note: For this to + work as intended, always put a double-newline after each command summary + section. ' # Command name. @@ -128,7 +128,6 @@ END { message = vars["message"]; if (short) { - print ""; print shorten(message, vars["name"]); } else { print message; From dd085efce771b3ee821de01a8c37082534bc5472 Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 10:40:42 -0700 Subject: [PATCH 05/11] Update test. --- tests/02-core/02-define-usage/01-usage-call/expect.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/02-core/02-define-usage/01-usage-call/expect.md b/tests/02-core/02-define-usage/01-usage-call/expect.md index c95d6b8..5dd6a87 100644 --- a/tests/02-core/02-define-usage/01-usage-call/expect.md +++ b/tests/02-core/02-define-usage/01-usage-call/expect.md @@ -3,7 +3,6 @@ ### stderr ``` This is not actually an error! (But we can pretend.) - the-cmd -- This is the short help for the command. the-cmd another-option-variant @@ -38,7 +37,6 @@ And more help about that. ### stderr ``` This is an error! - the-cmd -- This is the short help for the command. the-cmd another-option-variant @@ -53,7 +51,6 @@ the-cmd another-option-variant ### stderr ``` This is an error! - the-cmd -- This is the short help for the command. the-cmd another-option-variant From 00d287ac757d16818562d974fabd6bf884ce1603 Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 10:46:52 -0700 Subject: [PATCH 06/11] Fix doc. --- scripts/lib/bashy-core/misc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/lib/bashy-core/misc.sh b/scripts/lib/bashy-core/misc.sh index 245af1b..519f062 100644 --- a/scripts/lib/bashy-core/misc.sh +++ b/scripts/lib/bashy-core/misc.sh @@ -21,7 +21,7 @@ _bashy_usageMessage='' # Defines a standard-form `usage` function, optionally adding standardized help # options. When `usage` is defined with this, any non-zero pending exit code # (`$?`) becomes a process exit, so, for example, it is possible to say -# something like `process-args "$@" || usage --short`, and know that that exit +# something like `do-something || usage --short`, and know that that will exit # the process on error. With option `--with-help`, this defines standard help # options `--help` and short form `-h`, and appends help-for-help to the # description. From f543479b32295eb45aa9fb0fde89d64fcc29361a Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 10:51:50 -0700 Subject: [PATCH 07/11] Boilerplate reduction (approximately). --- scripts/lib/bashy-basics/buildy/clean | 2 +- scripts/lib/bashy-basics/buildy/ls-files | 2 +- scripts/lib/bashy-basics/buildy/make-distro | 2 +- scripts/lib/bashy-basics/buildy/out-dir | 2 +- scripts/lib/bashy-basics/buildy/pull-repo | 2 +- scripts/lib/bashy-basics/jarray | 2 +- scripts/lib/bashy-basics/jget | 2 +- scripts/lib/bashy-basics/jlength | 2 +- scripts/lib/bashy-basics/jstring | 2 +- scripts/lib/bashy-basics/jval | 2 +- scripts/lib/bashy-basics/ls-files | 2 +- scripts/lib/bashy-basics/rsync-local | 2 +- scripts/lib/bashy-basics/tempy/mkdir | 2 +- scripts/lib/bashy-basics/tempy/name | 2 +- scripts/lib/bashy-basics/timey/now-stamp | 2 +- scripts/lib/bashy-basics/timey/print | 2 +- scripts/lib/bashy-basics/timey/secs | 2 +- scripts/lib/bashy-core/_default-run | 2 +- scripts/lib/bashy-core/helpy/print-all-commands | 2 +- scripts/lib/bashy-core/helpy/print-subcommands | 2 +- scripts/lib/bashy-core/helpy/print-usage | 2 +- scripts/lib/bashy-net/cidr-calc | 2 +- scripts/lib/bashy-net/extract-public-key | 2 +- scripts/lib/bashy-net/generate-private-key | 2 +- scripts/lib/bashy-node/node-project/build-main-module | 2 +- scripts/lib/bashy-node/node-project/find-module-dependencies | 2 +- scripts/lib/bashy-node/node-project/fix-package-json | 2 +- scripts/lib/bashy-node/node-project/sort-imports | 2 +- scripts/ubik | 2 +- tests/02-core/02-define-usage/02-with-help/the-cmd | 2 +- tests/02-core/03-arg-processor/01-nothing-defined/the-cmd | 2 +- .../02-core/03-arg-processor/02-one-required-positional/the-cmd | 2 +- .../02-core/03-arg-processor/03-one-optional-positional/the-cmd | 2 +- tests/02-core/03-arg-processor/04-positional-req-opt/the-cmd | 2 +- tests/02-core/03-arg-processor/90-init-cross-checks/the-cmd | 2 +- .../03-arg-processor/91-unknown-declaration-opts/the-cmd | 2 +- tests/02-core/03-arg-processor/92-call-or-var/the-cmd | 2 +- tests/02-core/03-arg-processor/93-spec-arg-problems/the-cmd | 2 +- tests/02-core/03-arg-processor/94-duplicate-argument/the-cmd | 2 +- tests/02-core/03-arg-processor/95-incorrect-required/the-cmd | 2 +- tests/run-all | 2 +- tests/run-one | 2 +- 42 files changed, 42 insertions(+), 42 deletions(-) diff --git a/scripts/lib/bashy-basics/buildy/clean b/scripts/lib/bashy-basics/buildy/clean index 9004db7..20e9da9 100755 --- a/scripts/lib/bashy-basics/buildy/clean +++ b/scripts/lib/bashy-basics/buildy/clean @@ -24,7 +24,7 @@ define-usage --with-help $' # Built output directory. opt-value --var=outDir out -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/buildy/ls-files b/scripts/lib/bashy-basics/buildy/ls-files index e8b6375..6d8daae 100755 --- a/scripts/lib/bashy-basics/buildy/ls-files +++ b/scripts/lib/bashy-basics/buildy/ls-files @@ -78,7 +78,7 @@ function parse-rest { fi } -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/buildy/make-distro b/scripts/lib/bashy-basics/buildy/make-distro index fd4adb6..ee61afa 100755 --- a/scripts/lib/bashy-basics/buildy/make-distro +++ b/scripts/lib/bashy-basics/buildy/make-distro @@ -28,7 +28,7 @@ opt-value --var=outDir out # Directory containing the built project. positional-arg --var=builtDir built-dir -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/buildy/out-dir b/scripts/lib/bashy-basics/buildy/out-dir index df6ebc3..ecdb3fd 100755 --- a/scripts/lib/bashy-basics/buildy/out-dir +++ b/scripts/lib/bashy-basics/buildy/out-dir @@ -43,7 +43,7 @@ opt-toggle --var=doCreate create opt-toggle --var=doPrint print opt-toggle --var=doRemove remove -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/buildy/pull-repo b/scripts/lib/bashy-basics/buildy/pull-repo index ffe0cb8..9916243 100755 --- a/scripts/lib/bashy-basics/buildy/pull-repo +++ b/scripts/lib/bashy-basics/buildy/pull-repo @@ -53,7 +53,7 @@ opt-value --var=tagSpec --filter='/./' tag # Repo URL. positional-arg --var=repoUrl repo-url -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/jarray b/scripts/lib/bashy-basics/jarray index 8b0a372..971b06b 100755 --- a/scripts/lib/bashy-basics/jarray +++ b/scripts/lib/bashy-basics/jarray @@ -33,7 +33,7 @@ opt-value --var=inputStyle --init=json --enum='json strings' input # The array elements. rest-arg --var=values values -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/jget b/scripts/lib/bashy-basics/jget index f477a2d..11bbad5 100755 --- a/scripts/lib/bashy-basics/jget +++ b/scripts/lib/bashy-basics/jget @@ -40,7 +40,7 @@ positional-arg --required --var=value value # Expressions to operate on the value. rest-arg --var=exprArgs jval-exprs -process-args "$@" || usage --short +process-args "$@" || exit "$?" if [[ ${filePath} != '' ]]; then if [[ ${value} != '' ]]; then diff --git a/scripts/lib/bashy-basics/jlength b/scripts/lib/bashy-basics/jlength index 9697e94..19878f8 100755 --- a/scripts/lib/bashy-basics/jlength +++ b/scripts/lib/bashy-basics/jlength @@ -19,7 +19,7 @@ define-usage --with-help $' # JSON value. positional-arg --required --var=value json-value -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/jstring b/scripts/lib/bashy-basics/jstring index 0fb1b5e..e627569 100755 --- a/scripts/lib/bashy-basics/jstring +++ b/scripts/lib/bashy-basics/jstring @@ -20,7 +20,7 @@ define-usage --with-help $' # Strings to convert rest-arg --var=values string -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/jval b/scripts/lib/bashy-basics/jval index 731e0bc..55171ad 100755 --- a/scripts/lib/bashy-basics/jval +++ b/scripts/lib/bashy-basics/jval @@ -122,7 +122,7 @@ function parse-rest { fi } -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/ls-files b/scripts/lib/bashy-basics/ls-files index ec0aebd..e32558d 100755 --- a/scripts/lib/bashy-basics/ls-files +++ b/scripts/lib/bashy-basics/ls-files @@ -113,7 +113,7 @@ function parse-rest { fi } -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/rsync-local b/scripts/lib/bashy-basics/rsync-local index fee10ce..b97e7aa 100755 --- a/scripts/lib/bashy-basics/rsync-local +++ b/scripts/lib/bashy-basics/rsync-local @@ -44,7 +44,7 @@ opt-value --call='{ excludeOpts+=("--exclude=$1") }' exclude # Paths to copy from/to. rest-arg --var=paths paths -process-args "$@" || usage --short +process-args "$@" || exit "$?" if (( ${#paths} < 2 )); then error-msg 'Must specify at least two paths.' diff --git a/scripts/lib/bashy-basics/tempy/mkdir b/scripts/lib/bashy-basics/tempy/mkdir index ba4797c..b6fcd89 100755 --- a/scripts/lib/bashy-basics/tempy/mkdir +++ b/scripts/lib/bashy-basics/tempy/mkdir @@ -24,7 +24,7 @@ define-usage --with-help $' # Prefix. opt-value --var=prefix --init='tmp-' prefix -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/tempy/name b/scripts/lib/bashy-basics/tempy/name index a19fc22..b756903 100755 --- a/scripts/lib/bashy-basics/tempy/name +++ b/scripts/lib/bashy-basics/tempy/name @@ -26,7 +26,7 @@ define-usage --with-help $' # Prefix. opt-value --var=prefix --init='tmp-' prefix -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/timey/now-stamp b/scripts/lib/bashy-basics/timey/now-stamp index 3edb1cf..6b240b9 100755 --- a/scripts/lib/bashy-basics/timey/now-stamp +++ b/scripts/lib/bashy-basics/timey/now-stamp @@ -29,7 +29,7 @@ opt-value --var=prefix prefix # Suffix. opt-value --var=suffix suffix -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/timey/print b/scripts/lib/bashy-basics/timey/print index d1de900..c626ac2 100755 --- a/scripts/lib/bashy-basics/timey/print +++ b/scripts/lib/bashy-basics/timey/print @@ -38,7 +38,7 @@ positional-arg --required --var=time time # Output format. positional-arg --var=format --filter='/^[+]/' format -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-basics/timey/secs b/scripts/lib/bashy-basics/timey/secs index 53be84e..dd5561b 100755 --- a/scripts/lib/bashy-basics/timey/secs +++ b/scripts/lib/bashy-basics/timey/secs @@ -28,7 +28,7 @@ opt-value --var=inputType --init='secs' --enum='secs rfc822' input # Time value to parse. positional-arg --required --var=time time -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-core/_default-run b/scripts/lib/bashy-core/_default-run index d159a81..bb8d573 100755 --- a/scripts/lib/bashy-core/_default-run +++ b/scripts/lib/bashy-core/_default-run @@ -39,7 +39,7 @@ positional-arg --var=command command # The original command arguments, including any subcommands and other arguments. rest-arg --var=origArgs args -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-core/helpy/print-all-commands b/scripts/lib/bashy-core/helpy/print-all-commands index 0d2c9b4..ed7fe2b 100755 --- a/scripts/lib/bashy-core/helpy/print-all-commands +++ b/scripts/lib/bashy-core/helpy/print-all-commands @@ -28,7 +28,7 @@ opt-value --var=unitNames --filter='/^[-_.a-zA-Z0-9 ]+$/' units # Prefix string. opt-value --var=prefix prefix -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-core/helpy/print-subcommands b/scripts/lib/bashy-core/helpy/print-subcommands index 72f712d..adf238c 100755 --- a/scripts/lib/bashy-core/helpy/print-subcommands +++ b/scripts/lib/bashy-core/helpy/print-subcommands @@ -23,7 +23,7 @@ positional-arg --required --var=cmdName --filter='/^[-a-z]/' command # Subcommands if any. rest-arg --var=subWords --filter='/^[-a-z]/' subcommands -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-core/helpy/print-usage b/scripts/lib/bashy-core/helpy/print-usage index 724a27b..40067a1 100755 --- a/scripts/lib/bashy-core/helpy/print-usage +++ b/scripts/lib/bashy-core/helpy/print-usage @@ -47,7 +47,7 @@ opt-toggle --var=short short # Usage message to print. positional-arg --required --var=message message -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-net/cidr-calc b/scripts/lib/bashy-net/cidr-calc index d0095a4..883a517 100755 --- a/scripts/lib/bashy-net/cidr-calc +++ b/scripts/lib/bashy-net/cidr-calc @@ -60,7 +60,7 @@ positional-arg --required --var=command command # Command arguments. rest-arg --var=args args -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-net/extract-public-key b/scripts/lib/bashy-net/extract-public-key index 52cd80b..f56e4a3 100755 --- a/scripts/lib/bashy-net/extract-public-key +++ b/scripts/lib/bashy-net/extract-public-key @@ -37,7 +37,7 @@ opt-value --var=outputStyle --init=public-key \ # File path. positional-arg --init='/dev/stdin' --var=path file-path -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-net/generate-private-key b/scripts/lib/bashy-net/generate-private-key index 72ba0de..10fe409 100755 --- a/scripts/lib/bashy-net/generate-private-key +++ b/scripts/lib/bashy-net/generate-private-key @@ -35,7 +35,7 @@ opt-value --required --var=type \ # Where to output. opt-value --var=out --init='/dev/stdout' out -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-node/node-project/build-main-module b/scripts/lib/bashy-node/node-project/build-main-module index 0f0a04f..330be61 100755 --- a/scripts/lib/bashy-node/node-project/build-main-module +++ b/scripts/lib/bashy-node/node-project/build-main-module @@ -61,7 +61,7 @@ opt-toggle --var=runNpmInstallScripts unsafely-run-npm-install-scripts # Project name. positional-arg --filter='/^[-a-z0-9]+$/' --var=projectName project-name -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-node/node-project/find-module-dependencies b/scripts/lib/bashy-node/node-project/find-module-dependencies index 22215cd..57ea110 100755 --- a/scripts/lib/bashy-node/node-project/find-module-dependencies +++ b/scripts/lib/bashy-node/node-project/find-module-dependencies @@ -48,7 +48,7 @@ require-exactly-one-arg-of modules-dir modules-dirs # The module to start at. positional-arg --required --var=moduleName module-name -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-node/node-project/fix-package-json b/scripts/lib/bashy-node/node-project/fix-package-json index 72ed30e..4bf89b5 100755 --- a/scripts/lib/bashy-node/node-project/fix-package-json +++ b/scripts/lib/bashy-node/node-project/fix-package-json @@ -20,7 +20,7 @@ define-usage --with-help $' # Specific paths to process rest-arg --var=files --filter=/./ file -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/lib/bashy-node/node-project/sort-imports b/scripts/lib/bashy-node/node-project/sort-imports index e10ac6c..4874290 100755 --- a/scripts/lib/bashy-node/node-project/sort-imports +++ b/scripts/lib/bashy-node/node-project/sort-imports @@ -21,7 +21,7 @@ define-usage --with-help $' # Specific paths to process rest-arg --var=files --filter=/./ file -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/scripts/ubik b/scripts/ubik index 63a26a9..be2d81a 100755 --- a/scripts/ubik +++ b/scripts/ubik @@ -27,7 +27,7 @@ positional-arg --var=cmdName command # The actual command arguments. rest-arg --var=args args -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/tests/02-core/02-define-usage/02-with-help/the-cmd b/tests/02-core/02-define-usage/02-with-help/the-cmd index 9b722c5..93ebbfd 100755 --- a/tests/02-core/02-define-usage/02-with-help/the-cmd +++ b/tests/02-core/02-define-usage/02-with-help/the-cmd @@ -16,6 +16,6 @@ define-usage --with-help $' This is the longer help. ' -process-args "$@" || usage --short +process-args "$@" || exit "$?" echo 'Finished.' diff --git a/tests/02-core/03-arg-processor/01-nothing-defined/the-cmd b/tests/02-core/03-arg-processor/01-nothing-defined/the-cmd index 8b35cc3..e2ff95b 100755 --- a/tests/02-core/03-arg-processor/01-nothing-defined/the-cmd +++ b/tests/02-core/03-arg-processor/01-nothing-defined/the-cmd @@ -15,6 +15,6 @@ define-usage $' This is a test command. ' -process-args "$@" || usage --short +process-args "$@" || exit "$?" echo 'Success!' diff --git a/tests/02-core/03-arg-processor/02-one-required-positional/the-cmd b/tests/02-core/03-arg-processor/02-one-required-positional/the-cmd index 2482a69..8d7d536 100755 --- a/tests/02-core/03-arg-processor/02-one-required-positional/the-cmd +++ b/tests/02-core/03-arg-processor/02-one-required-positional/the-cmd @@ -17,6 +17,6 @@ define-usage $' positional-arg --required --var=theName zongo -process-args "$@" || usage --short +process-args "$@" || exit "$?" printf 'Value: %q\n' "${theName}" diff --git a/tests/02-core/03-arg-processor/03-one-optional-positional/the-cmd b/tests/02-core/03-arg-processor/03-one-optional-positional/the-cmd index 76d5cd0..85f725d 100755 --- a/tests/02-core/03-arg-processor/03-one-optional-positional/the-cmd +++ b/tests/02-core/03-arg-processor/03-one-optional-positional/the-cmd @@ -17,6 +17,6 @@ define-usage $' positional-arg --var=theName --init=zorch zongo -process-args "$@" || usage --short +process-args "$@" || exit "$?" printf 'Value: %q\n' "${theName}" diff --git a/tests/02-core/03-arg-processor/04-positional-req-opt/the-cmd b/tests/02-core/03-arg-processor/04-positional-req-opt/the-cmd index e7f568b..79699f3 100755 --- a/tests/02-core/03-arg-processor/04-positional-req-opt/the-cmd +++ b/tests/02-core/03-arg-processor/04-positional-req-opt/the-cmd @@ -19,7 +19,7 @@ positional-arg --required --var=yesArg avec-yes positional-arg --var=someValue some-value -process-args "$@" || usage --short +process-args "$@" || exit "$?" printf 'avec-yes: %q\n' "${yesArg}" printf 'some-value: %q\n' "${someValue}" diff --git a/tests/02-core/03-arg-processor/90-init-cross-checks/the-cmd b/tests/02-core/03-arg-processor/90-init-cross-checks/the-cmd index 8de6d48..0441c40 100755 --- a/tests/02-core/03-arg-processor/90-init-cross-checks/the-cmd +++ b/tests/02-core/03-arg-processor/90-init-cross-checks/the-cmd @@ -25,6 +25,6 @@ opt-value --init=x --call=func1 beep opt-choice --init=x --call=func2 bomp blump positional-arg --init=x --call=func3 plomp -process-args "$@" || usage --short +process-args "$@" || exit "$?" echo 'Nopers.' diff --git a/tests/02-core/03-arg-processor/91-unknown-declaration-opts/the-cmd b/tests/02-core/03-arg-processor/91-unknown-declaration-opts/the-cmd index fc55045..0cf3c9e 100755 --- a/tests/02-core/03-arg-processor/91-unknown-declaration-opts/the-cmd +++ b/tests/02-core/03-arg-processor/91-unknown-declaration-opts/the-cmd @@ -27,6 +27,6 @@ opt-value -zonk --var=v x opt-value ---zonk --var=v x opt-value --Zomg --var=v x -process-args "$@" || usage --short +process-args "$@" || exit "$?" echo 'Nopers.' diff --git a/tests/02-core/03-arg-processor/92-call-or-var/the-cmd b/tests/02-core/03-arg-processor/92-call-or-var/the-cmd index 69e6aae..6c88fcf 100755 --- a/tests/02-core/03-arg-processor/92-call-or-var/the-cmd +++ b/tests/02-core/03-arg-processor/92-call-or-var/the-cmd @@ -22,6 +22,6 @@ opt-toggle boop positional-arg --filter='/boop/' some-position rest-arg --filter='/x/' the-rest -process-args "$@" || usage --short +process-args "$@" || exit "$?" echo 'Nopers.' diff --git a/tests/02-core/03-arg-processor/93-spec-arg-problems/the-cmd b/tests/02-core/03-arg-processor/93-spec-arg-problems/the-cmd index 827d39f..358a426 100755 --- a/tests/02-core/03-arg-processor/93-spec-arg-problems/the-cmd +++ b/tests/02-core/03-arg-processor/93-spec-arg-problems/the-cmd @@ -49,6 +49,6 @@ opt-choice --var=var1 florp foo=x bar positional-arg --var=var2 fleep=123 rest-arg --var=var3 floop=xyz -process-args "$@" || usage --short +process-args "$@" || exit "$?" echo 'Nopers.' diff --git a/tests/02-core/03-arg-processor/94-duplicate-argument/the-cmd b/tests/02-core/03-arg-processor/94-duplicate-argument/the-cmd index 58becf3..f6c70bb 100755 --- a/tests/02-core/03-arg-processor/94-duplicate-argument/the-cmd +++ b/tests/02-core/03-arg-processor/94-duplicate-argument/the-cmd @@ -31,6 +31,6 @@ rest-arg --var=var2 a-rest rest-arg --var=var3 different-name -process-args "$@" || usage --short +process-args "$@" || exit "$?" echo 'Nopers.' diff --git a/tests/02-core/03-arg-processor/95-incorrect-required/the-cmd b/tests/02-core/03-arg-processor/95-incorrect-required/the-cmd index 1262eac..985a125 100755 --- a/tests/02-core/03-arg-processor/95-incorrect-required/the-cmd +++ b/tests/02-core/03-arg-processor/95-incorrect-required/the-cmd @@ -20,6 +20,6 @@ opt-toggle --required --var=var1 some-toggle rest-arg --required --var=var1 some-rest -process-args "$@" || usage --short +process-args "$@" || exit "$?" echo 'Nopers.' diff --git a/tests/run-all b/tests/run-all index 62919e7..b22b56a 100755 --- a/tests/run-all +++ b/tests/run-all @@ -16,7 +16,7 @@ define-usage --with-help $' Runs all the tests. ' -process-args "$@" || usage --short +process-args "$@" || exit "$?" # diff --git a/tests/run-one b/tests/run-one index 3528aaa..8bcfaa8 100755 --- a/tests/run-one +++ b/tests/run-one @@ -36,7 +36,7 @@ opt-toggle --var=doUpdate update # The test to run. positional-arg --required --var=testName --filter='/[0-9][-/a-z0-9]*$/' test-name -process-args "$@" || usage --short +process-args "$@" || exit "$?" # From 78dd0876d792ea704d7a8af3034f4c2b9db77681 Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 10:56:38 -0700 Subject: [PATCH 08/11] On second thought, automatic `exit` was a bit too magical. --- scripts/lib/bashy-core/arg-processor.sh | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/scripts/lib/bashy-core/arg-processor.sh b/scripts/lib/bashy-core/arg-processor.sh index cbaa6ba..708a48b 100644 --- a/scripts/lib/bashy-core/arg-processor.sh +++ b/scripts/lib/bashy-core/arg-processor.sh @@ -269,13 +269,14 @@ function post-process-args-call { # Returns normally upon successful processing. If there is any trouble parsing # (including if there were errors during argument/option declaration), this # prints the short form of the `usage` message (if `usage` is available) and -# then exits the process entirely with a non-zero code. +# then returns with a non-zero code. function process-args { local _argproc_error=0 local _argproc_s if (( _argproc_declarationError )); then - _argproc_error-exit 'Cannot process arguments, due to declaration errors.' + _argproc_error-coda 'Cannot process arguments, due to declaration errors.' + return 1 fi # Run all the pre-parse statements. @@ -296,7 +297,8 @@ function process-args { # Don't continue if there were problems above, because that will lead to # spurious extra errors (e.g. "missing" a required option that was # present but didn't pass a validity check). - _argproc_error-exit --code="${_argproc_error}" + _argproc_error-coda + return "${_argproc_error}" fi # Do any post-parse checks. @@ -305,7 +307,8 @@ function process-args { done if (( _argproc_error )); then - _argproc_error-exit --code="${_argproc_error}" + _argproc_error-coda + return "${_argproc_error}" fi } @@ -570,15 +573,9 @@ function _argproc_define-value-taking-arg { fi } -# Does an error-exit, printing `usage` if available. -function _argproc_error-exit { - local exitCode=1 - - if [[ $1 =~ ^--code= ]]; then - exitCode="${1#*=}" - shift - fi - +# Helper for `process-args`, which prints an optional final error message and +# then short `usage` if it is defined. +function _argproc_error-coda { local msg=("$@") if (( ${#msg[@]} != 0 )); then @@ -589,8 +586,6 @@ function _argproc_error-exit { error-msg '' usage --short fi - - exit "${exitCode}" } # Produces an argument handler body, from the given components. From ae8b2d3488747a81dc21b1b93d971327c25e829a Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 10:57:41 -0700 Subject: [PATCH 09/11] Fix. --- example/scripts/my-util | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/scripts/my-util b/example/scripts/my-util index ae3c875..c13340b 100755 --- a/example/scripts/my-util +++ b/example/scripts/my-util @@ -26,7 +26,7 @@ positional-arg --var=cmdName subcommand # The subcommand arguments (including possibly sub-subcommand names). rest-arg --var=args args -process-args "$@" || usage --short "$?" +process-args "$@" || exit "$?" # From 938c4cadf459f2a8d112abe8607bc974ec144050 Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 11:01:21 -0700 Subject: [PATCH 10/11] Drop the magical `exit` behavior. --- scripts/lib/bashy-core/misc.sh | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/scripts/lib/bashy-core/misc.sh b/scripts/lib/bashy-core/misc.sh index 519f062..b58203e 100644 --- a/scripts/lib/bashy-core/misc.sh +++ b/scripts/lib/bashy-core/misc.sh @@ -19,12 +19,8 @@ _bashy_usageMessage='' # # Defines a standard-form `usage` function, optionally adding standardized help -# options. When `usage` is defined with this, any non-zero pending exit code -# (`$?`) becomes a process exit, so, for example, it is possible to say -# something like `do-something || usage --short`, and know that that will exit -# the process on error. With option `--with-help`, this defines standard help -# options `--help` and short form `-h`, and appends help-for-help to the -# description. +# options. With option `--with-help`, this defines standard help options +# `--help` and short form `-h`, and appends help-for-help to the description. function define-usage { local withHelp=0 if [[ $1 == --with-help ]]; then @@ -49,11 +45,7 @@ function define-usage { fi local func=$'function usage { - local exitCode="$?" lib helpy print-usage --name="$(this-cmd-name)" "$@" "${_bashy_usageMessage}" - if (( exitCode != 0 )); then - exit "${exitCode}" - fi }' eval "${func}" From b43b78d7c8f7ac26e5ad6de3e79b382e081cf8dc Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 5 Oct 2023 11:04:46 -0700 Subject: [PATCH 11/11] Update test. --- .../02-define-usage/01-usage-call/expect.md | 29 ++++++++++++++----- .../02-define-usage/01-usage-call/the-cmd | 10 +++---- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/tests/02-core/02-define-usage/01-usage-call/expect.md b/tests/02-core/02-define-usage/01-usage-call/expect.md index 5dd6a87..dd23e11 100644 --- a/tests/02-core/02-define-usage/01-usage-call/expect.md +++ b/tests/02-core/02-define-usage/01-usage-call/expect.md @@ -1,12 +1,15 @@ ## short +### stdout +``` +Done. +``` + ### stderr ``` -This is not actually an error! (But we can pretend.) the-cmd -- This is the short help for the command. the-cmd another-option-variant -(no exit expected; should see this) ``` ### exit: 0 @@ -15,6 +18,11 @@ the-cmd another-option-variant ## long +### stdout +``` +Done. +``` + ### stderr ``` the-cmd -- This is the short @@ -25,7 +33,6 @@ This is the longer help. the-cmd another-option-variant And more help about that. -(no exit expected; should see this) ``` ### exit: 0 @@ -34,26 +41,34 @@ And more help about that. ## error 1 +### stdout +``` +Done. +``` + ### stderr ``` -This is an error! the-cmd -- This is the short help for the command. the-cmd another-option-variant ``` -### exit: 1 +### exit: 0 - - - - - - - - - - ## error 99 +### stdout +``` +Done. +``` + ### stderr ``` -This is an error! the-cmd -- This is the short help for the command. the-cmd another-option-variant ``` -### exit: 99 +### exit: 0 diff --git a/tests/02-core/02-define-usage/01-usage-call/the-cmd b/tests/02-core/02-define-usage/01-usage-call/the-cmd index f8a92a8..f63f631 100755 --- a/tests/02-core/02-define-usage/01-usage-call/the-cmd +++ b/tests/02-core/02-define-usage/01-usage-call/the-cmd @@ -25,16 +25,16 @@ what="$1" case "${what}" in long) usage - echo 1>&2 '(no exit expected; should see this)' ;; short) - echo 1>&2 'This is not actually an error! (But we can pretend.)' usage --short - echo 1>&2 '(no exit expected; should see this)' ;; *) - echo 1>&2 'This is an error!' + # Old behavior was that `usage` would magically `exit` if `$?` was + # non-zero upon entry. This test now verifies that it no longer does + # that. (exit "${what}") || usage --short - echo 1>&2 '(exit expected; should not see this)' ;; esac + +echo 'Done.'