Add support for repeatable arguments (#118)

* Add support for declaring arguments as repeatable

If the usage of the argument includes the phrase "Can be repeated.",
the corresponding arg_ variable will be an array containing one element
per instance of the argument.

* Add example and test for using repeated parameters

* Add example and test for using repeated flags
This commit is contained in:
Lukas Stockner 2019-09-20 11:40:06 +02:00 committed by Kevin van Zonneveld
parent ff89a1154b
commit 95b9cb1469
10 changed files with 94 additions and 9 deletions

View File

@ -14,13 +14,14 @@ Released: TBA.
[Diff](https://github.com/kvz/bash3boilerplate/compare/v2.3.0...master). [Diff](https://github.com/kvz/bash3boilerplate/compare/v2.3.0...master).
- [ ] Upgrade to `lanyon@0.0.55` - [ ] Upgrade to `lanyon@0.0.55`
- [ ] Allow counting how many times an argument is used - [x] Allow counting how many times an argument is used (@genesiscloud)
- [x] Fix typos in megamount (thanks @gsaponaro) - [x] Fix typos in megamount (thanks @gsaponaro)
- [x] Enable color in screen or tmux (#92, @gmasse) - [x] Enable color in screen or tmux (#92, @gmasse)
- [x] Change `egrep` to `grep -E` in test and lib scripts to comply with ShellCheck (#92, @gmasse) - [x] Change `egrep` to `grep -E` in test and lib scripts to comply with ShellCheck (#92, @gmasse)
- [x] Fix typo in FAQ (#92, @gmasse) - [x] Fix typo in FAQ (#92, @gmasse)
- [x] Fix Travis CI failure on src/templater.sh (@gmasse) - [x] Fix Travis CI failure on src/templater.sh (@gmasse)
- [x] Add magic variable which contains full command invocation - [x] Add magic variable which contains full command invocation
- [x] Add support for repeatable arguments (@genesiscloud)
- [x] Fix remaining warnings with shellcheck v0.7.0 (#107, @genesiscloud) - [x] Fix remaining warnings with shellcheck v0.7.0 (#107, @genesiscloud)
## v2.3.0 ## v2.3.0

View File

@ -36,6 +36,8 @@ read -r -d '' __usage <<-'EOF' || true # exits non-zero when EOF encountered
-h --help This page -h --help This page
-n --no-color Disable color output -n --no-color Disable color output
-1 --one Do just one thing -1 --one Do just one thing
-i --input [arg] File to process. Can be repeated.
-x Specify a flag. Can be repeated.
EOF EOF
# shellcheck disable=SC2034 # shellcheck disable=SC2034
@ -122,6 +124,18 @@ info "arg_f: ${arg_f}"
info "arg_d: ${arg_d}" info "arg_d: ${arg_d}"
info "arg_v: ${arg_v}" info "arg_v: ${arg_v}"
info "arg_h: ${arg_h}" info "arg_h: ${arg_h}"
if [[ -v arg_i ]]
then
info "arg_i: ${#arg_i[@]}"
for input_file in "${arg_i[@]}"
do
info " - ${input_file}"
done
else
info "arg_i: 0"
fi
# shellcheck disable=SC2015
[[ -v arg_x ]] && info "arg_x: ${#arg_x[@]}" || info "arg_x: 0"
info "$(echo -e "multiple lines example - line #1\\nmultiple lines example - line #2\\nimagine logging the output of 'ls -al /path/'")" info "$(echo -e "multiple lines example - line #1\\nmultiple lines example - line #2\\nimagine logging the output of 'ls -al /path/'")"

49
main.sh
View File

@ -144,6 +144,8 @@ function help () {
-h --help This page -h --help This page
-n --no-color Disable color output -n --no-color Disable color output
-1 --one Do just one thing -1 --one Do just one thing
-i --input [arg] File to process. Can be repeated.
-x Specify a flag. Can be repeated.
EOF EOF
# shellcheck disable=SC2015 # shellcheck disable=SC2015
@ -187,6 +189,13 @@ while read -r __b3bp_tmp_line; do
printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "0" printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "0"
fi fi
__b3bp_tmp_opts="${__b3bp_tmp_opts:-}${__b3bp_tmp_opt}" __b3bp_tmp_opts="${__b3bp_tmp_opts:-}${__b3bp_tmp_opt}"
if [[ "${__b3bp_tmp_line}" =~ ^Can\ be\ repeated\. ]] || [[ "${__b3bp_tmp_line}" =~ \.\ *Can\ be\ repeated\. ]]; then
# remember that this option can be repeated
printf -v "__b3bp_tmp_is_array_${__b3bp_tmp_opt:0:1}" '%s' "1"
else
printf -v "__b3bp_tmp_is_array_${__b3bp_tmp_opt:0:1}" '%s' "0"
fi
fi fi
[[ "${__b3bp_tmp_opt:-}" ]] || continue [[ "${__b3bp_tmp_opt:-}" ]] || continue
@ -214,7 +223,8 @@ while read -r __b3bp_tmp_line; do
printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "2" printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "2"
fi fi
printf -v "arg_${__b3bp_tmp_opt:0:1}" '%s' "${__b3bp_tmp_init}" __b3bp_tmp_varname="__b3bp_tmp_is_array_${__b3bp_tmp_opt:0:1}"
[[ "${!__b3bp_tmp_varname}" = "0" ]] && printf -v "arg_${__b3bp_tmp_opt:0:1}" '%s' "${__b3bp_tmp_init}"
done <<< "${__usage:-}" done <<< "${__usage:-}"
# run getopts only if options were specified in __usage # run getopts only if options were specified in __usage
@ -256,16 +266,27 @@ if [[ "${__b3bp_tmp_opts:-}" ]]; then
fi fi
# we have set opt/OPTARG to the short value and the argument as OPTARG if it exists # we have set opt/OPTARG to the short value and the argument as OPTARG if it exists
fi fi
__b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}"
__b3bp_tmp_default="${!__b3bp_tmp_varname}"
__b3bp_tmp_value="${OPTARG}" __b3bp_tmp_value="${OPTARG}"
if [[ -z "${OPTARG}" ]]; then
__b3bp_tmp_value=$((__b3bp_tmp_default + 1))
fi
printf -v "${__b3bp_tmp_varname}" '%s' "${__b3bp_tmp_value}" __b3bp_tmp_varname="__b3bp_tmp_is_array_${__b3bp_tmp_opt:0:1}"
debug "cli arg ${__b3bp_tmp_varname} = (${__b3bp_tmp_default}) -> ${!__b3bp_tmp_varname}" if [[ "${!__b3bp_tmp_varname}" != "0" ]]; then
__b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}[@]"
# shellcheck disable=SC2016
declare -a "${__b3bp_tmp_varname}"='("${!__b3bp_tmp_varname}" "${__b3bp_tmp_value}")'
debug "cli arg ${__b3bp_tmp_varname} append ${__b3bp_tmp_value}"
else
__b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}"
__b3bp_tmp_default="${!__b3bp_tmp_varname}"
if [[ -z "${OPTARG}" ]]; then
__b3bp_tmp_value=$((__b3bp_tmp_default + 1))
fi
printf -v "${__b3bp_tmp_varname}" '%s' "${__b3bp_tmp_value}"
debug "cli arg ${__b3bp_tmp_varname} = (${__b3bp_tmp_default}) -> ${!__b3bp_tmp_varname}"
fi
done done
set -o nounset # no more unbound variable references expected set -o nounset # no more unbound variable references expected
@ -383,6 +404,18 @@ info "arg_f: ${arg_f}"
info "arg_d: ${arg_d}" info "arg_d: ${arg_d}"
info "arg_v: ${arg_v}" info "arg_v: ${arg_v}"
info "arg_h: ${arg_h}" info "arg_h: ${arg_h}"
if [[ -v arg_i ]]
then
info "arg_i: ${#arg_i[@]}"
for input_file in "${arg_i[@]}"
do
info " - ${input_file}"
done
else
info "arg_i: 0"
fi
# shellcheck disable=SC2015
[[ -v arg_x ]] && info "arg_x: ${#arg_x[@]}" || info "arg_x: 0"
info "$(echo -e "multiple lines example - line #1\\nmultiple lines example - line #2\\nimagine logging the output of 'ls -al /path/'")" info "$(echo -e "multiple lines example - line #1\\nmultiple lines example - line #2\\nimagine logging the output of 'ls -al /path/'")"

View File

@ -9,6 +9,8 @@ ACCPTST:STDIO_REPLACE_DATETIMES
{datetime} UTC [ info] arg_d: 0 {datetime} UTC [ info] arg_d: 0
{datetime} UTC [ info] arg_v: 0 {datetime} UTC [ info] arg_v: 0
{datetime} UTC [ info] arg_h: 0 {datetime} UTC [ info] arg_h: 0
{datetime} UTC [ info] arg_i: 0
{datetime} UTC [ info] arg_x: 0
{datetime} UTC [ info] multiple lines example - line #1 {datetime} UTC [ info] multiple lines example - line #1
{datetime} UTC [ info] multiple lines example - line #2 {datetime} UTC [ info] multiple lines example - line #2
{datetime} UTC [ info] imagine logging the output of 'ls -al /path/' {datetime} UTC [ info] imagine logging the output of 'ls -al /path/'

View File

@ -9,6 +9,8 @@ ACCPTST:STDIO_REPLACE_DATETIMES
{datetime} UTC [ info] arg_d: 0 {datetime} UTC [ info] arg_d: 0
{datetime} UTC [ info] arg_v: 0 {datetime} UTC [ info] arg_v: 0
{datetime} UTC [ info] arg_h: 0 {datetime} UTC [ info] arg_h: 0
{datetime} UTC [ info] arg_i: 0
{datetime} UTC [ info] arg_x: 0
{datetime} UTC [ info] multiple lines example - line #1 {datetime} UTC [ info] multiple lines example - line #1
{datetime} UTC [ info] multiple lines example - line #2 {datetime} UTC [ info] multiple lines example - line #2
{datetime} UTC [ info] imagine logging the output of 'ls -al /path/' {datetime} UTC [ info] imagine logging the output of 'ls -al /path/'

View File

@ -9,6 +9,8 @@ ACCPTST:STDIO_REPLACE_DATETIMES
-h --help This page -h --help This page
-n --no-color Disable color output -n --no-color Disable color output
-1 --one Do just one thing -1 --one Do just one thing
-i --input [arg] File to process. Can be repeated.
-x Specify a flag. Can be repeated.
This is Bash3 Boilerplate's help text. Feel free to add any description of your This is Bash3 Boilerplate's help text. Feel free to add any description of your
program or elaborate more on command-line arguments. This section is not program or elaborate more on command-line arguments. This section is not

View File

@ -9,6 +9,8 @@ ACCPTST:STDIO_REPLACE_DATETIMES
{datetime} UTC [ info] arg_d: 0 {datetime} UTC [ info] arg_d: 0
{datetime} UTC [ info] arg_v: 0 {datetime} UTC [ info] arg_v: 0
{datetime} UTC [ info] arg_h: 0 {datetime} UTC [ info] arg_h: 0
{datetime} UTC [ info] arg_i: 0
{datetime} UTC [ info] arg_x: 0
{datetime} UTC [ info] multiple lines example - line #1 {datetime} UTC [ info] multiple lines example - line #1
{datetime} UTC [ info] multiple lines example - line #2 {datetime} UTC [ info] multiple lines example - line #2
{datetime} UTC [ info] imagine logging the output of 'ls -al /path/' {datetime} UTC [ info] imagine logging the output of 'ls -al /path/'

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,9 @@
ACCPTST:STDIO_REPLACE_DATETIMES
{datetime} UTC [ info] arg_i: 5
{datetime} UTC [ info] - simple_input
{datetime} UTC [ info] - input_in_quotes
{datetime} UTC [ info] - input with spaces
{datetime} UTC [ info] - input with "quotes"
{datetime} UTC [ info] - last_input
{datetime} UTC [ info] arg_x: 3
{datetime} UTC [ info] arg_x: 4

View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
# set -o pipefail
# set -o errexit
set -o nounset
# set -o xtrace
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
__root="$(cd "$(dirname "$(dirname "$(dirname "${__dir}")")")" && pwd)"
echo "ACCPTST:STDIO_REPLACE_DATETIMES"
(
env LOG_LEVEL=6 bash "${__root}/main.sh" -f dummy -i simple_input -i "input_in_quotes" -i "input with spaces" -i "input with \"quotes\"" -i last_input
) 2>&1 |grep arg_i -A 5
(
env LOG_LEVEL=6 bash "${__root}/main.sh" -x -f dummy -x -x
env LOG_LEVEL=6 bash "${__root}/main.sh" -f dummy -xxxx
) 2>&1 |grep arg_x