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).
- [ ] 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] 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] Fix typo in FAQ (#92, @gmasse)
- [x] Fix Travis CI failure on src/templater.sh (@gmasse)
- [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)
## 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
-n --no-color Disable color output
-1 --one Do just one thing
-i --input [arg] File to process. Can be repeated.
-x Specify a flag. Can be repeated.
EOF
# shellcheck disable=SC2034
@ -122,6 +124,18 @@ info "arg_f: ${arg_f}"
info "arg_d: ${arg_d}"
info "arg_v: ${arg_v}"
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/'")"

49
main.sh
View File

@ -144,6 +144,8 @@ function help () {
-h --help This page
-n --no-color Disable color output
-1 --one Do just one thing
-i --input [arg] File to process. Can be repeated.
-x Specify a flag. Can be repeated.
EOF
# 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"
fi
__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
[[ "${__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"
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:-}"
# run getopts only if options were specified in __usage
@ -256,16 +266,27 @@ if [[ "${__b3bp_tmp_opts:-}" ]]; then
fi
# we have set opt/OPTARG to the short value and the argument as OPTARG if it exists
fi
__b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}"
__b3bp_tmp_default="${!__b3bp_tmp_varname}"
__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}"
debug "cli arg ${__b3bp_tmp_varname} = (${__b3bp_tmp_default}) -> ${!__b3bp_tmp_varname}"
__b3bp_tmp_varname="__b3bp_tmp_is_array_${__b3bp_tmp_opt:0:1}"
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
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_v: ${arg_v}"
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/'")"

View File

@ -9,6 +9,8 @@ ACCPTST:STDIO_REPLACE_DATETIMES
{datetime} UTC [ info] arg_d: 0
{datetime} UTC [ info] arg_v: 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 #2
{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_v: 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 #2
{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
-n --no-color Disable color output
-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
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_v: 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 #2
{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