diff --git a/lib/getopts_long.bash b/lib/getopts_long.bash index baabf95..270caa0 100644 --- a/lib/getopts_long.bash +++ b/lib/getopts_long.bash @@ -37,7 +37,10 @@ getopts_long() { # Sanitize and normalize short optspec optspec_short="${optspec_short//-:}" optspec_short="${optspec_short//-}" - [[ "${!OPTIND:0:2}" == "--" ]] && optspec_short+='-:' + if [[ -n "${!OPTIND:-}" && "${!OPTIND:0:2}" == "--" ]]; then + optspec_short+='-:' + fi + builtin getopts -- "${optspec_short}" "${optvar}" "${@}" || return ${?} [[ "${!optvar}" == '-' ]] || return 0 @@ -50,10 +53,9 @@ getopts_long() { # Missing argument if [[ -z "${OPTARG}" ]]; then - OPTARG="${!OPTIND}" && OPTIND=$(( OPTIND + 1 )) - [[ -z "${OPTARG}" ]] || return 0 - - if [[ "${optspec_short:0:1}" == ':' ]]; then + if [[ -n "${!OPTIND:-}" ]]; then + OPTARG="${!OPTIND}" && OPTIND=$(( OPTIND + 1 )) + elif [[ "${optspec_short:0:1}" == ':' ]]; then OPTARG="${!optvar}" && printf -v "${optvar}" ':' else [[ "${OPTERR}" == 0 ]] || \ diff --git a/test/bats/github_18.bats b/test/bats/github_18.bats new file mode 100644 index 0000000..20b455f --- /dev/null +++ b/test/bats/github_18.bats @@ -0,0 +1,42 @@ +#!/usr/bin/env bats + +load ../test_helper +export GETOPTS_LONG_TEST_BIN='getopts_long-nounset' + +@test "${FEATURE}: toggles, silent" { + compare '-t -t -- user_arg' \ + '-t --toggle -- user_arg' +} +@test "${FEATURE}: toggles, verbose" { + compare '-t -t -- user_arg' \ + '-t --toggle -- user_arg' +} + +@test "${FEATURE}: options, silent" { + compare '-o user_val1 -o user_val2 -- user_arg' \ + '-o user_val1 --option user_val2 -- user_arg' +} +@test "${FEATURE}: options, verbose" { + compare '-o user_val1 -o user_val2 -- user_arg' \ + '-o user_val1 --option user_val2 -- user_arg' +} + +@test "${FEATURE}: variables, silent" { + compare '-vuser_val1 -vuser_val2 -- user_arg' \ + '-vuser_val1 --variable=user_val2 -- user_arg' +} +@test "${FEATURE}: variables, verbose" { + compare '-vuser_val1 -vuser_val2 -- user_arg' \ + '-vuser_val1 --variable=user_val2 -- user_arg' +} + +@test "${FEATURE}: missing last argument, silent" { + compare '-vuser_val1 -vuser_val2 -- user_arg' \ + '-vuser_val1 --variable=user_val2 -- user_arg' +} +@test "${FEATURE}: missing last argument, verbose" { + compare '-o' \ + '--option' \ + '1{s/getopts.+verbose:/getopts-NORMALIZED:/}' \ + '1{s/(option requires an argument --) (o|option)$/\1 NORMALIZED/}' +} diff --git a/test/bin/getopts_long-explicit_args-silent b/test/bin/getopts_long-explicit_args-silent index 355d238..cd94a3e 100755 --- a/test/bin/getopts_long-explicit_args-silent +++ b/test/bin/getopts_long-explicit_args-silent @@ -58,23 +58,17 @@ variables() { getopts_function -vuser_val1 --variable=user_val2 -- user_arg } -enable_extdebug='false' -if shopt -q extdebug; then - enable_extdebug='true' +( shopt -u extdebug -fi -: "${1:?Missing required argument -- function name}" -function_name=${1} -shift + : "${1:?Missing required argument -- function name}" + function_name=${1} + shift -if declare -f "$function_name" > /dev/null; then - ${function_name} "$@" -else - echo "Function not found -- ${function_name}" - exit 1 -fi - -if ${enable_extdebug}; then - shopt -s extdebug -fi + if declare -f "$function_name" > /dev/null; then + ${function_name} "$@" + else + echo "Function not found -- ${function_name}" + exit 1 + fi +) diff --git a/test/bin/getopts_long-explicit_args-verbose b/test/bin/getopts_long-explicit_args-verbose index 538c5f0..cea485d 100755 --- a/test/bin/getopts_long-explicit_args-verbose +++ b/test/bin/getopts_long-explicit_args-verbose @@ -58,23 +58,17 @@ variables() { getopts_function -vuser_val1 --variable=user_val2 -- user_arg } -enable_extdebug='false' -if shopt -q extdebug; then - enable_extdebug='true' +( shopt -u extdebug -fi -: "${1:?Missing required parameter -- function name}" -function_name=${1} -shift + : "${1:?Missing required parameter -- function name}" + function_name=${1} + shift -if declare -f "$function_name" > /dev/null; then - ${function_name} "$@" -else - echo "Function not found -- ${function_name}" - exit 1 -fi - -if ${enable_extdebug}; then - shopt -s extdebug -fi + if declare -f "$function_name" > /dev/null; then + ${function_name} "$@" + else + echo "Function not found -- ${function_name}" + exit 1 + fi +) diff --git a/test/bin/getopts_long-nounset-silent b/test/bin/getopts_long-nounset-silent new file mode 100755 index 0000000..56cd24c --- /dev/null +++ b/test/bin/getopts_long-nounset-silent @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +TOPDIR="$(cd "$(dirname "${0}")"/../.. && pwd)" +# shellcheck disable=SC1090 +source "${TOPDIR}/lib/getopts_long.bash" + +( + set -o nounset + + while getopts_long ':to:v: toggle option: variable:' OPTKEY; do + case ${OPTKEY} in + 't'|'toggle') + printf 'toggle triggered' + ;; + 'o'|'option') + printf 'option supplied' + ;; + 'v'|'variable') + printf 'value supplied' + ;; + '?') + printf "INVALID OPTION" + ;; + ':') + printf "MISSING ARGUMENT" + ;; + *) + printf "NEVER REACHED" + ;; + esac + printf ' -- ' + declare -p OPTARG 2>&1 | grep -oe 'OPTARG.*' + done + + shift $(( OPTIND - 1 )) + + echo "OPTERR: ${OPTERR:-}" + echo "OPTKEY: ${OPTKEY:-}" + echo "OPTARG: ${OPTARG:-}" + echo "OPTIND: ${OPTIND:-}" + + args=("$@") + declare -p args | sed -e 's/declare -a args=/$@: /' +) diff --git a/test/bin/getopts_long-nounset-verbose b/test/bin/getopts_long-nounset-verbose new file mode 100755 index 0000000..1726b26 --- /dev/null +++ b/test/bin/getopts_long-nounset-verbose @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +TOPDIR="$(cd "$(dirname "${0}")"/../.. && pwd)" +# shellcheck disable=SC1090 +source "${TOPDIR}/lib/getopts_long.bash" + +( + set -o nounset + + while getopts_long 'to:v: toggle option: variable:' OPTKEY; do + case ${OPTKEY} in + 't'|'toggle') + printf 'toggle triggered' + ;; + 'o'|'option') + printf 'option supplied' + ;; + 'v'|'variable') + printf 'value supplied' + ;; + '?') + printf "INVALID OPTION or MISSING ARGUMENT" + ;; + *) + printf "NEVER REACHED" + ;; + esac + printf ' -- ' + declare -p OPTARG 2>&1 | grep -oe 'OPTARG.*' + done + + shift $(( OPTIND - 1 )) + + echo "OPTERR: ${OPTERR:-}" + echo "OPTKEY: ${OPTKEY:-}" + echo "OPTARG: ${OPTARG:-}" + echo "OPTIND: ${OPTIND:-}" + + args=("$@") + declare -p args | sed -e 's/declare -a args=/$@: /' +) diff --git a/test/bin/getopts_long-with_extdebug-silent b/test/bin/getopts_long-with_extdebug-silent index 45c0fda..b1ce67b 100755 --- a/test/bin/getopts_long-with_extdebug-silent +++ b/test/bin/getopts_long-with_extdebug-silent @@ -58,23 +58,17 @@ variables() { getopts_function -vuser_val1 --variable=user_val2 -- user_arg } -disable_extdebug='false' -if ! shopt -q extdebug; then - disable_extdebug='true' +( shopt -s extdebug -fi -: "${1:?Missing required argument -- function name}" -function_name=${1} -shift + : "${1:?Missing required argument -- function name}" + function_name=${1} + shift -if declare -f "$function_name" > /dev/null; then - ${function_name} "$@" -else - echo "Function not found -- ${function_name}" - exit 1 -fi - -if ${disable_extdebug}; then - shopt -u extdebug -fi + if declare -f "$function_name" > /dev/null; then + ${function_name} "$@" + else + echo "Function not found -- ${function_name}" + exit 1 + fi +) diff --git a/test/bin/getopts_long-with_extdebug-verbose b/test/bin/getopts_long-with_extdebug-verbose index 1bed59a..bc49db3 100755 --- a/test/bin/getopts_long-with_extdebug-verbose +++ b/test/bin/getopts_long-with_extdebug-verbose @@ -58,23 +58,17 @@ variables() { getopts_function -vuser_val1 --variable=user_val2 -- user_arg } -disable_extdebug='false' -if ! shopt -q extdebug; then - disable_extdebug='true' +( shopt -s extdebug -fi -: "${1:?Missing required parameter -- function name}" -function_name=${1} -shift + : "${1:?Missing required parameter -- function name}" + function_name=${1} + shift -if declare -f "$function_name" > /dev/null; then - ${function_name} "$@" -else - echo "Function not found -- ${function_name}" - exit 1 -fi - -if ${disable_extdebug}; then - shopt -u extdebug -fi + if declare -f "$function_name" > /dev/null; then + ${function_name} "$@" + else + echo "Function not found -- ${function_name}" + exit 1 + fi +) diff --git a/test/bin/getopts_long-without_extdebug-silent b/test/bin/getopts_long-without_extdebug-silent index 2daa2b5..57767a8 100755 --- a/test/bin/getopts_long-without_extdebug-silent +++ b/test/bin/getopts_long-without_extdebug-silent @@ -58,23 +58,17 @@ variables() { getopts_function -vuser_val1 --variable=user_val2 -- user_arg } -enable_extdebug='false' -if shopt -q extdebug; then - enable_extdebug='true' +( shopt -u extdebug -fi -: "${1:?Missing required argument -- function name}" -function_name=${1} -shift + : "${1:?Missing required argument -- function name}" + function_name=${1} + shift -if declare -f "$function_name" > /dev/null; then - ${function_name} "$@" -else - echo "Function not found -- ${function_name}" - exit 1 -fi - -if ${enable_extdebug}; then - shopt -s extdebug -fi + if declare -f "$function_name" > /dev/null; then + ${function_name} "$@" + else + echo "Function not found -- ${function_name}" + exit 1 + fi +) diff --git a/test/bin/getopts_long-without_extdebug-verbose b/test/bin/getopts_long-without_extdebug-verbose index 7f07ef3..3d3b3fb 100755 --- a/test/bin/getopts_long-without_extdebug-verbose +++ b/test/bin/getopts_long-without_extdebug-verbose @@ -58,23 +58,17 @@ variables() { getopts_function -vuser_val1 --variable=user_val2 -- user_arg } -enable_extdebug='false' -if shopt -q extdebug; then - enable_extdebug='true' +( shopt -u extdebug -fi -: "${1:?Missing required parameter -- function name}" -function_name=${1} -shift + : "${1:?Missing required parameter -- function name}" + function_name=${1} + shift -if declare -f "$function_name" > /dev/null; then - ${function_name} "$@" -else - echo "Function not found -- ${function_name}" - exit 1 -fi - -if ${enable_extdebug}; then - shopt -s extdebug -fi + if declare -f "$function_name" > /dev/null; then + ${function_name} "$@" + else + echo "Function not found -- ${function_name}" + exit 1 + fi +)