]> git.corax.cc Git - toolbox/commitdiff
include/opt: Use associative array to track missing options
authorMatthias Kruk <m@m10k.eu>
Thu, 11 Aug 2022 17:09:07 +0000 (02:09 +0900)
committerMatthias Kruk <m@m10k.eu>
Thu, 11 Aug 2022 17:09:07 +0000 (02:09 +0900)
The opt module does not track missing options, but instead checks
on demand if required options are missing by inspecting all options'
flags and value. This approach is needlessly complicated and slow.

This commit changes the opt module to track required options using
an associative array, allowing the check for missing options to be
performed in constant time.

include/opt.sh

index bc844a6fb546c2ed62bdd2a166ce326015ebbff8..2fce9c5fb05f66f63ff85b2f0a5dc49c341d0fdb 100644 (file)
@@ -38,6 +38,7 @@ __init() {
        declare -Axg __opt_regex
        declare -Axg __opt_action
        declare -Axg __opt_map
+       declare -Axg __opt_required
 
        opt_add_arg "h" "help" "" 0 \
                    "Print this text" \
@@ -125,6 +126,10 @@ opt_add_arg() {
                __opt_default["$long"]="$default"
        fi
 
+       if (( parsed_flags & __opt_flag_required )); then
+               __opt_required["$long"]="$long"
+       fi
+
        return 0
 }
 
@@ -156,10 +161,23 @@ opt_print_help() {
        return 2
 }
 
+_opt_have_required() {
+       local option
+       local -i err
+
+       err=0
+
+       for option in "${!__opt_required[@]}"; do
+               log_error "Missing required option: --$option"
+               err=1
+       done
+
+       return "$err"
+}
+
 opt_parse() {
        local argv=("$@")
 
-       local optname
        local err
        local i
 
@@ -187,6 +205,10 @@ opt_parse() {
                action="${__opt_action[$long]}"
                regex="${__opt_regex[$long]}"
 
+               if [[ -n "${__opt_required[$long]}" ]]; then
+                       unset __opt_required["$long"]
+               fi
+
                if (( flags & __opt_flag_has_value )); then
                        ((i++))
 
@@ -220,20 +242,9 @@ opt_parse() {
                fi
        done
 
-       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
+       if ! _opt_have_required; then
+               return 1
+       fi
 
        return "$err"
 }