Skip to content

Commit

Permalink
[GH-15] Support for adjacent variable-value syntax (#20)
Browse files Browse the repository at this point in the history
* Refactored internal variable names used in tests
* Fixed github #15
* Replaced regex with globing to improve performance
  • Loading branch information
UrsaDK authored Dec 10, 2024
1 parent 5f8fafb commit f8e8e89
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 109 deletions.
16 changes: 13 additions & 3 deletions lib/getopts_long.bash
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,19 @@ getopts_long() {
builtin getopts "${optspec_short}" "${optvar}" "${@}" || return 1
[[ "${!optvar}" == '-' ]] || return 0

printf -v "${optvar}" "%s" "${OPTARG%%=*}"
if [[ "${OPTARG}" == *=* ]]; then
printf -v "${optvar}" "%s" "${OPTARG%%=*}"
else
for optspec in $(echo "${optspec_long}" | tr ' ' '\n' | sort -ur); do
if [[ "${optspec}" == *: && "${OPTARG}" == "${optspec%?}"* ]]; then
printf -v "${optvar}" "%s" "${optspec%?}"
break
fi
done
[[ "${!optvar}" == '-' ]] && printf -v "${optvar}" "%s" "${OPTARG}"
fi

if [[ "${optspec_long}" =~ (^|[[:space:]])${!optvar}:([[:space:]]|$) ]]; then
if [[ " ${optspec_long} " == *" ${!optvar}: "* ]]; then
OPTARG="${OPTARG#"${!optvar}"}"
OPTARG="${OPTARG#=}"

Expand All @@ -39,7 +49,7 @@ getopts_long() {
unset OPTARG && printf -v "${optvar}" '?'
fi
fi
elif [[ "${optspec_long}" =~ (^|[[:space:]])${!optvar}([[:space:]]|$) ]]; then
elif [[ " ${optspec_long} " == *" ${!optvar} "* ]]; then
unset OPTARG
else
# Invalid option
Expand Down
21 changes: 21 additions & 0 deletions test/bats/github_15.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bats

load ../test_helper

@test "${FEATURE}: short option, silent" {
compare '-o-- user_arg' \
'-o-- user_arg'
}
@test "${FEATURE}: short option, verbose" {
compare '-o-- user_arg' \
'-o-- user_arg'
}

@test "${FEATURE}: long option, silent" {
compare '-o-- user_arg' \
'--option-- user_arg'
}
@test "${FEATURE}: long option, verbose" {
compare '-o-- user_arg' \
'--option-- user_arg'
}
28 changes: 14 additions & 14 deletions test/bats/invalid_arguments.bats
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ load ../test_helper
compare '-i' \
'--invalid' \
'/^INVALID OPTION -- /d'
expect "${expected_lines[0]}" == 'INVALID OPTION -- OPTARG=i'
expect "${actual_lines[0]}" == 'INVALID OPTION -- OPTARG=invalid'
expect "${bash_getopts_lines[0]}" == 'INVALID OPTION -- OPTARG=i'
expect "${getopts_long_lines[0]}" == 'INVALID OPTION -- OPTARG=invalid'
}
@test "${FEATURE}: long option, verbose" {
compare '-i' \
Expand All @@ -41,8 +41,8 @@ load ../test_helper
compare '-i user_arg' \
'--invalid user_arg' \
'/^INVALID OPTION -- /d'
expect "${expected_lines[0]}" == 'INVALID OPTION -- OPTARG=i'
expect "${actual_lines[0]}" == 'INVALID OPTION -- OPTARG=invalid'
expect "${bash_getopts_lines[0]}" == 'INVALID OPTION -- OPTARG=i'
expect "${getopts_long_lines[0]}" == 'INVALID OPTION -- OPTARG=invalid'
}
@test "${FEATURE}: long option, extra arguments, verbose" {
compare '-i user_arg' \
Expand All @@ -55,53 +55,53 @@ load ../test_helper
@test "${FEATURE}: short option, terminator, extra arguments, silent" {
compare '-i -- user_arg' \
'-i -- user_arg'
expect "${actual_lines[5]}" == '$@: user_arg'
expect "${getopts_long_lines[5]}" == '$@: user_arg'
}
@test "${FEATURE}: short option, terminator, extra arguments, verbose" {
compare '-i -- user_arg' \
'-i -- user_arg' \
's/getopts_long-verbose/getopts-verbose/g'
expect "${actual_lines[6]}" == '$@: user_arg'
expect "${getopts_long_lines[6]}" == '$@: user_arg'
}

@test "${FEATURE}: long option, terminator, extra arguments, silent" {
compare '-i -- user_arg' \
'--invalid -- user_arg' \
'/^INVALID OPTION -- /d'
expect "${expected_lines[0]}" == 'INVALID OPTION -- OPTARG=i'
expect "${actual_lines[0]}" == 'INVALID OPTION -- OPTARG=invalid'
expect "${actual_lines[5]}" == '$@: user_arg'
expect "${bash_getopts_lines[0]}" == 'INVALID OPTION -- OPTARG=i'
expect "${getopts_long_lines[0]}" == 'INVALID OPTION -- OPTARG=invalid'
expect "${getopts_long_lines[5]}" == '$@: user_arg'
}
@test "${FEATURE}: long option, terminator, extra arguments, verbose" {
compare '-i -- user_arg' \
'--invalid -- user_arg' \
's/getopts_long-verbose: (.*) invalid$/getopts-verbose: \1 i/g'
expect "${actual_lines[6]}" == '$@: user_arg'
expect "${getopts_long_lines[6]}" == '$@: user_arg'
}

# terminator followed by options

@test "${FEATURE}: terminator, short option, extra arguments, silent" {
compare '-- -i user_arg' \
'-- -i user_arg'
expect "${actual_lines[4]}" == '$@: -i user_arg'
expect "${getopts_long_lines[4]}" == '$@: -i user_arg'
}
@test "${FEATURE}: terminator, short option, extra arguments, verbose" {
compare '-- -i user_arg' \
'-- -i user_arg' \
's/getopts_long-verbose/getopts-verbose/g'
expect "${actual_lines[4]}" == '$@: -i user_arg'
expect "${getopts_long_lines[4]}" == '$@: -i user_arg'
}

@test "${FEATURE}: terminator, long option, extra arguments, silent" {
compare '-- -i user_arg' \
'-- --invalid user_arg' \
'/^\$@: /d'
expect "${actual_lines[4]}" == '$@: --invalid user_arg'
expect "${getopts_long_lines[4]}" == '$@: --invalid user_arg'
}
@test "${FEATURE}: terminator, long option, extra arguments, verbose" {
compare '-- -i user_arg' \
'-- --invalid user_arg' \
'/^\$@: /d'
expect "${actual_lines[4]}" == '$@: --invalid user_arg'
expect "${getopts_long_lines[4]}" == '$@: --invalid user_arg'
}
4 changes: 2 additions & 2 deletions test/bats/no_arguments.bats
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ load ../test_helper
@test "${FEATURE}: terminator, extra arguments, silent" {
compare '-- user_arg' \
'-- user_arg'
expect "${actual_lines[4]}" == '$@: user_arg'
expect "${getopts_long_lines[4]}" == '$@: user_arg'
}
@test "${FEATURE}: terminator, extra arguments, verbose" {
compare '-- user_arg' \
'-- user_arg'
expect "${actual_lines[4]}" == '$@: user_arg'
expect "${getopts_long_lines[4]}" == '$@: user_arg'
}
57 changes: 39 additions & 18 deletions test/bats/option_supplied.bats
Original file line number Diff line number Diff line change
Expand Up @@ -45,77 +45,77 @@ load ../test_helper
@test "${FEATURE}: short option, terminator, extra arguments, silent" {
compare '-o user_val -- user_arg' \
'-o user_val -- user_arg'
expect "${actual_lines[5]}" == '$@: user_arg'
expect "${getopts_long_lines[5]}" == '$@: user_arg'
}
@test "${FEATURE}: short option, terminator, extra arguments, verbose" {
compare '-o user_val -- user_arg' \
'-o user_val -- user_arg'
expect "${actual_lines[5]}" == '$@: user_arg'
expect "${getopts_long_lines[5]}" == '$@: user_arg'
}

@test "${FEATURE}: long option, terminator, extra arguments, silent" {
compare '-o user_val -- user_arg' \
'--option user_val -- user_arg'
expect "${actual_lines[5]}" == '$@: user_arg'
expect "${getopts_long_lines[5]}" == '$@: user_arg'
}
@test "${FEATURE}: long option, terminator, extra arguments, verbose" {
compare '-o user_val -- user_arg' \
'--option user_val -- user_arg'
expect "${actual_lines[5]}" == '$@: user_arg'
expect "${getopts_long_lines[5]}" == '$@: user_arg'
}

# multiple same arguments

@test "${FEATURE}: short option, multiple same arguments, silent" {
compare '-o user_val1 -o user_val2' \
'-o user_val1 -o user_val2'
expect "${actual_lines[0]}" == 'option supplied -- OPTARG=user_val1'
expect "${actual_lines[1]}" == 'option supplied -- OPTARG=user_val2'
expect "${getopts_long_lines[0]}" == 'option supplied -- OPTARG=user_val1'
expect "${getopts_long_lines[1]}" == 'option supplied -- OPTARG=user_val2'
}
@test "${FEATURE}: short option, multiple same arguments, verbose" {
compare '-o user_val1 -o user_val2' \
'-o user_val1 -o user_val2'
expect "${actual_lines[0]}" == 'option supplied -- OPTARG=user_val1'
expect "${actual_lines[1]}" == 'option supplied -- OPTARG=user_val2'
expect "${getopts_long_lines[0]}" == 'option supplied -- OPTARG=user_val1'
expect "${getopts_long_lines[1]}" == 'option supplied -- OPTARG=user_val2'
}

@test "${FEATURE}: long option, multiple same arguments, silent" {
compare '-o user_val1 -o user_val2' \
'--option user_val1 --option user_val2'
expect "${actual_lines[0]}" == 'option supplied -- OPTARG=user_val1'
expect "${actual_lines[1]}" == 'option supplied -- OPTARG=user_val2'
expect "${getopts_long_lines[0]}" == 'option supplied -- OPTARG=user_val1'
expect "${getopts_long_lines[1]}" == 'option supplied -- OPTARG=user_val2'
}
@test "${FEATURE}: long option, multiple same arguments, verbose" {
compare '-o user_val1 -o user_val2' \
'--option user_val1 --option user_val2'
expect "${actual_lines[0]}" == 'option supplied -- OPTARG=user_val1'
expect "${actual_lines[1]}" == 'option supplied -- OPTARG=user_val2'
expect "${getopts_long_lines[0]}" == 'option supplied -- OPTARG=user_val1'
expect "${getopts_long_lines[1]}" == 'option supplied -- OPTARG=user_val2'
}

# terminator followed by options

@test "${FEATURE}: terminator, short option, extra arguments, silent" {
compare '-- -o user_val user_arg' \
'-- -o user_val user_arg'
expect "${actual_lines[4]}" == '$@: -o user_val user_arg'
expect "${getopts_long_lines[4]}" == '$@: -o user_val user_arg'
}
@test "${FEATURE}: terminator, short option, extra arguments, verbose" {
compare '-- -o user_val user_arg' \
'-- -o user_val user_arg'
expect "${actual_lines[4]}" == '$@: -o user_val user_arg'
expect "${getopts_long_lines[4]}" == '$@: -o user_val user_arg'
}

@test "${FEATURE}: terminator, long option, extra arguments, silent" {
compare '-- -o user_val user_arg' \
'-- --option user_val user_arg' \
'/^\$@: /d'
expect "${actual_lines[4]}" == '$@: --option user_val user_arg'
expect "${getopts_long_lines[4]}" == '$@: --option user_val user_arg'
}
@test "${FEATURE}: terminator, long option, extra arguments, verbose" {
compare '-- -o user_val user_arg' \
'-- --option user_val user_arg' \
'/^\$@: /d'
expect "${actual_lines[4]}" == '$@: --option user_val user_arg'
expect "${getopts_long_lines[4]}" == '$@: --option user_val user_arg'
}

# option without an argument
Expand All @@ -134,8 +134,8 @@ load ../test_helper
compare '-o' \
'--option' \
'/^MISSING ARGUMENT -- /d'
expect "${expected_lines[0]}" == 'MISSING ARGUMENT -- OPTARG=o'
expect "${actual_lines[0]}" == 'MISSING ARGUMENT -- OPTARG=option'
expect "${bash_getopts_lines[0]}" == 'MISSING ARGUMENT -- OPTARG=o'
expect "${getopts_long_lines[0]}" == 'MISSING ARGUMENT -- OPTARG=option'
}
@test "${FEATURE}: long option, missing value, verbose" {
compare '-o' \
Expand Down Expand Up @@ -182,3 +182,24 @@ load ../test_helper
compare '-o =user_val' \
'--option =user_val'
}

# option with an adjoined value

@test "${FEATURE}: short option, adjoined value, silent" {
compare '-ouser_val' \
'-ouser_val'
}
@test "${FEATURE}: short option, adjoined value, verbose" {
compare '-ouser_val' \
'-ouser_val'
}

@test "${FEATURE}: long option, adjoined value, silent" {
compare '-ouser_val' \
'--optionuser_val'
}

@test "${FEATURE}: long option, adjoined value, verbose" {
compare '-ouser_val' \
'--optionuser_val'
}
32 changes: 16 additions & 16 deletions test/bats/toggle_triggered.bats
Original file line number Diff line number Diff line change
Expand Up @@ -45,75 +45,75 @@ load ../test_helper
@test "${FEATURE}: short option, terminator, extra arguments, silent" {
compare '-t -- user_arg' \
'-t -- user_arg'
expect "${actual_lines[5]}" == '$@: user_arg'
expect "${getopts_long_lines[5]}" == '$@: user_arg'
}
@test "${FEATURE}: short option, terminator, extra arguments, verbose" {
compare '-t -- user_arg' \
'-t -- user_arg'
expect "${actual_lines[5]}" == '$@: user_arg'
expect "${getopts_long_lines[5]}" == '$@: user_arg'
}

@test "${FEATURE}: long option, terminator, extra arguments, silent" {
compare '-t -- user_arg' \
'--toggle -- user_arg'
expect "${actual_lines[5]}" == '$@: user_arg'
expect "${getopts_long_lines[5]}" == '$@: user_arg'
}
@test "${FEATURE}: long option, terminator, extra arguments, verbose" {
compare '-t -- user_arg' \
'--toggle -- user_arg'
expect "${actual_lines[5]}" == '$@: user_arg'
expect "${getopts_long_lines[5]}" == '$@: user_arg'
}

# multiple same arguments

@test "${FEATURE}: short option, multiple same arguments, silent" {
compare '-t -t' \
'-t -t'
expect "${actual_lines[0]}" == "${actual_lines[1]}"
expect "${actual_lines[0]}" == 'toggle triggered -- OPTARG is unset'
expect "${getopts_long_lines[0]}" == "${getopts_long_lines[1]}"
expect "${getopts_long_lines[0]}" == 'toggle triggered -- OPTARG is unset'
}
@test "${FEATURE}: short option, multiple same arguments, verbose" {
compare '-t -t' \
'-t -t'
expect "${actual_lines[0]}" == "${actual_lines[1]}"
expect "${actual_lines[0]}" == 'toggle triggered -- OPTARG is unset'
expect "${getopts_long_lines[0]}" == "${getopts_long_lines[1]}"
expect "${getopts_long_lines[0]}" == 'toggle triggered -- OPTARG is unset'
}

@test "${FEATURE}: long option, multiple same arguments, silent" {
compare '-t -t' \
'--toggle --toggle'
expect "${actual_lines[0]}" == "${actual_lines[1]}"
expect "${actual_lines[0]}" == 'toggle triggered -- OPTARG is unset'
expect "${getopts_long_lines[0]}" == "${getopts_long_lines[1]}"
expect "${getopts_long_lines[0]}" == 'toggle triggered -- OPTARG is unset'
}
@test "${FEATURE}: long option, multiple same arguments, verbose" {
compare '-t -t' \
'--toggle --toggle'
expect "${actual_lines[0]}" == "${actual_lines[1]}"
expect "${actual_lines[0]}" == 'toggle triggered -- OPTARG is unset'
expect "${getopts_long_lines[0]}" == "${getopts_long_lines[1]}"
expect "${getopts_long_lines[0]}" == 'toggle triggered -- OPTARG is unset'
}

# terminator followed by options

@test "${FEATURE}: terminator, short option, extra arguments, silent" {
compare '-- -t user_arg' \
'-- -t user_arg'
expect "${actual_lines[4]}" == '$@: -t user_arg'
expect "${getopts_long_lines[4]}" == '$@: -t user_arg'
}
@test "${FEATURE}: terminator, short option, extra arguments, verbose" {
compare '-- -t user_arg' \
'-- -t user_arg'
expect "${actual_lines[4]}" == '$@: -t user_arg'
expect "${getopts_long_lines[4]}" == '$@: -t user_arg'
}

@test "${FEATURE}: terminator, long option, extra arguments, silent" {
compare '-- -t user_arg' \
'-- --toggle user_arg' \
'/^\$@: /d'
expect "${actual_lines[4]}" == '$@: --toggle user_arg'
expect "${getopts_long_lines[4]}" == '$@: --toggle user_arg'
}
@test "${FEATURE}: terminator, long option, extra arguments, verbose" {
compare '-- -t user_arg' \
'-- --toggle user_arg' \
'/^\$@: /d'
expect "${actual_lines[4]}" == '$@: --toggle user_arg'
expect "${getopts_long_lines[4]}" == '$@: --toggle user_arg'
}
Loading

0 comments on commit f8e8e89

Please sign in to comment.