diff --git a/lib/opt.sh b/lib/opt.sh index 46d0bc8..3d7198a 100644 --- a/lib/opt.sh +++ b/lib/opt.sh @@ -1,11 +1,16 @@ #!/usr/bin/env bash # ----------------------------------------------------------------------------- -# bat-extras | Copyright (C) 2019 eth-p | MIT License +# bat-extras | Copyright (C) 2019-2020 eth-p | MIT License # # Repository: https://github.com/eth-p/bat-extras # Issues: https://github.com/eth-p/bat-extras/issues # ----------------------------------------------------------------------------- source "${LIB}/constants.sh" + +# An array of functions to call before returning from `shiftopt`. +# +# If one of these functions returns a successful exit code, the +# option will be transparently skipped instead of handled. SHIFTOPT_HOOKS=() # Sets the internal _ARGV, _ARGV_INDEX, and _ARGV_LAST variables used when @@ -16,6 +21,12 @@ setargs() { _ARGV_INDEX=0 } +# Resets the internal _ARGV* variables to the original script arguments. +# This is the equivalent of storing the top-level $@ and using setargs with it. +resetargs() { + setargs "${_ARGV_ORIGINAL[@]}" +} + # Gets the next option passed to the script. # # Variables: @@ -88,3 +99,4 @@ shiftval() { # ----------------------------------------------------------------------------- setargs "$@" +_ARGV_ORIGINAL=("$@") diff --git a/test/suite/lib_opt.sh b/test/suite/lib_opt.sh index 161647d..6d04240 100644 --- a/test/suite/lib_opt.sh +++ b/test/suite/lib_opt.sh @@ -14,6 +14,10 @@ setup() { source "${LIB}/opt.sh" } +assert_opt_name() { + assert [ "$OPT" = "$1" ] +} + assert_opt_value() { assert [ "$OPT_VAL" = "$1" ] } @@ -22,6 +26,7 @@ assert_opt_valueless() { assert [ -z "$OPT_VAL" ] } + test:long() { description "Parse long options." @@ -118,3 +123,49 @@ test:short_value_explicit() { fail 'Failed to find option.' } + +test:hook() { + description "Option hooks." + + SHIFTOPT_HOOKS=("example_hook") + + found=false + example_hook() { + if [[ "$OPT" = "pos1" ]]; then + found=true + return 0 + fi + return 1 + } + + while shiftopt; do + if [[ "$OPT" = "pos1" ]]; then + fail "Option was not filtered by hook." + fi + done + + if ! "$found"; then + fail "Option was not found by hook." + fi +} + +test:fn_setargs() { + description "Function setargs." + + setargs "--setarg=true" + shiftopt || true + shiftval + + assert_opt_name "--setarg" + assert_opt_value "true" +} + +test:fn_resetargs() { + description "Function resetargs." + + setargs "--setarg=true" + resetargs + shiftopt || true + + assert_opt_name "pos1" +}