From 17dbd31636d781c86767e7287b1e6d7b46e07ecf Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Mon, 19 Apr 2021 08:38:43 +0900 Subject: [PATCH] include/opt: Add flag to define required arguments The opt module currently does not provide a means to define required arguments, making it hard for the callee to determine if an argument was provided on the commandline, or if the default value was returned by opt_get(). This commit adds a flag to specify if an argument must be provided on the commandline. Further, since multiple flags can now be passed to opt_add_arg(), the flag format is changed: now, a string containing all flags as characters must be passed. The implementation understands the following flags: r - Argument is required v - Argument has a value (e.g. is followed by a second argument) For example, to declare a required argument with a value, one would pass the flags "rv". --- include/opt.sh | 69 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/include/opt.sh b/include/opt.sh index d04e3e8..1a612ed 100644 --- a/include/opt.sh +++ b/include/opt.sh @@ -5,24 +5,28 @@ __init() { return 1 fi + declare -xgir __opt_flag_required=1 + declare -xgir __opt_flag_has_value=2 + declare -Axg __opt_short=() declare -Axg __opt_long=() declare -Axg __opt_desc=() declare -Axg __opt_flags=() declare -Axg __opt_value=() + declare -Axg __opt_default=() declare -Axg __opt_action=() declare -Axg __opt_map=() declare -xgi __opt_num=0 declare -xgi __opt_longest=0 - opt_add_arg "h" "help" "no" 0 \ + opt_add_arg "h" "help" "" 0 \ "Print this text" \ opt_print_help - opt_add_arg "v" "verbose" "no" 0 \ + opt_add_arg "v" "verbose" "" 0 \ "Be more verbose" \ log_increase_verbosity - opt_add_arg "w" "shush" "no" 0 \ + opt_add_arg "w" "shush" "" 0 \ "Be less verbose" \ log_decrease_verbosity @@ -38,6 +42,9 @@ opt_add_arg() { local action local optlen + local num_flags + local bflags + local i short="$1" long="$2" @@ -51,13 +58,32 @@ opt_add_arg() { return 1 fi + num_flags="${#flags}" + bflags=0 + + for (( i = 0; i < num_flags; i++ )); do + case "${flags:$i:1}" in + "r") + ((bflags |= __opt_flag_required)) + ;; + + "v") + ((bflags |= __opt_flag_has_value)) + ;; + + *) + return 1 + ;; + esac + done + optlen="${#long}" __opt_short["$long"]="$short" __opt_long["$short"]="$long" - __opt_flags["$long"]="$flags" + __opt_flags["$long"]="$bflags" __opt_desc["$long"]="$desc" - __opt_value["$long"]="$default" + __opt_default["$long"]="$default" __opt_action["$long"]="$action" __opt_map["-$short"]="$long" @@ -105,11 +131,14 @@ opt_print_help() { } opt_parse() { - local opt + local optname + local err local i declare -argx __opt_argv=("$@") + err=0 + for (( i = 1; i <= $#; i++ )); do local param local long @@ -128,7 +157,7 @@ opt_parse() { flags="${__opt_flags[$long]}" action="${__opt_action[$long]}" - if [[ "$flags" == "yes" ]]; then + if (( flags & __opt_flag_has_value )); then ((i++)) if (( i > $# )); then @@ -144,7 +173,7 @@ opt_parse() { __opt_value["$long"]="$value" - if ! [[ -z "$action" ]]; then + if [[ -n "$action" ]]; then local err "$action" "$long" "$value" @@ -156,7 +185,22 @@ opt_parse() { fi done - return 0 + for optname in "${__opt_long[@]}"; do + local flags + + flags="${__opt_flags[$optname]}" + + if ! (( flags & __opt_flag_required )); then + continue + fi + + if ! array_contains "$optname" "${!__opt_value[@]}"; then + log_error "Missing required argument: $optname" + err=1 + fi + done + + return "$err" } opt_get() { @@ -164,11 +208,12 @@ opt_get() { long="$1" - if ! array_contains "$long" "${!__opt_value[@]}"; then - return 1 + if array_contains "$long" "${!__opt_value[@]}"; then + echo "${__opt_value[$long]}" + else + echo "${__opt_default[$long]}" fi - echo "${__opt_value[$long]}" return 0 } -- 2.47.3