]> git.corax.cc Git - toolbox/commitdiff
include/opt: Add array options
authorMatthias Kruk <m@m10k.eu>
Sat, 17 Dec 2022 04:50:31 +0000 (13:50 +0900)
committerMatthias Kruk <m@m10k.eu>
Sat, 17 Dec 2022 04:50:31 +0000 (13:50 +0900)
Options with multiple values stored in an array can be implemented
using callbacks, but it is somewhat hacky and would be nicer if the
opt module had explicit support for options with multiple values.

This commit adds the "a" attribute, allowing options to be declared
as arrays. The default value of an array option must be the name of
the array that values shall be appended to.

include/opt.sh
test/opt_spec.sh

index 9129933ed59570d96f3723c1860b7057b6a47423..bb9f222be1490c450ea361964f141c16057933fb 100644 (file)
@@ -23,10 +23,12 @@ __init() {
 
        declare -xgir __opt_flag_required=1
        declare -xgir __opt_flag_has_value=2
+       declare -xgir __opt_flag_is_array=6 # is_array implies has_value
 
        declare -xgAr __opt_flags_map=(
                ["r"]="$__opt_flag_required"
                ["v"]="$__opt_flag_has_value"
+               ["a"]="$__opt_flag_is_array"
        )
 
        declare -Axg __opt_short
@@ -109,6 +111,12 @@ opt_add_arg() {
                return 1
        fi
 
+       if (( ( parsed_flags & __opt_flag_is_array ) == __opt_flag_is_array )) &&
+          ! declare -p "$default" &>/dev/null; then
+               log_error "Default value of array options must be the name of an array"
+               return 1
+       fi
+
        __opt_short["$long"]="$short"
        __opt_flags["$long"]="$parsed_flags"
        __opt_desc["$long"]="$desc"
@@ -148,7 +156,17 @@ opt_print_help() {
                       "$short" "$long" "${__opt_desc[$long]}"
                if (( ${__opt_flags["$long"]} & __opt_flag_has_value )) &&
                   array_contains "$long" "${!__opt_default[@]}"; then
-                       printf '\t\t\t(Default: %s)\n' "${__opt_default[$long]}"
+                       if (( ${__opt_flags["$long"]} & __opt_flag_is_array )); then
+                               local -n __opt_print_help_array="${__opt_default[$long]}"
+
+                               if (( ${#__opt_print_help_array[@]} > 0 )); then
+                                       printf '\t\t\t(Default:\n'
+                                       printf '\t\t\t     %s\n' "${__opt_print_help_array[@]}"
+                                       printf '\t\t\t)\n'
+                               fi
+                       else
+                               printf '\t\t\t(Default: %s)\n' "${__opt_default[$long]}"
+                       fi
                fi
        done | column -s $'\t' -t
 
@@ -216,6 +234,11 @@ opt_parse() {
                                log_error "Value \"$value\" doesn't match \"$regex\""
                                return 1
                        fi
+
+                       if (( ( flags & __opt_flag_is_array ) == __opt_flag_is_array )); then
+                               local -n __opt_parse_array="${__opt_default[$long]}"
+                               __opt_parse_array+=("$value")
+                       fi
                else
                        value=$(( __opt_value[$long] + 1 ))
                fi
index c4a3ad0df1fb8c40bbf6111fd5c330d90a8be82d..50d8d663d1abd096c2073687e7fa3949c6fe1f39 100644 (file)
@@ -28,20 +28,26 @@ Describe "opt_add_arg() - Attributes"
   Parameters
   "r"    0 "accepts"
   "v"    0 "accepts"
+  "a"    0 "accepts"         "array"
   "rv"   0 "accepts"
+  "rva"  0 "accepts"         "array"
   "vr"   0 "accepts"
   "rvrv" 0 "accepts"
   "x"    1 "does not accept"
+  "a"    1 "does not accept"
   End
 
   _test_opt_add_arg_attr() (
          local attr="$1"
+         local default="$2"
 
-         opt_add_arg "o" "opt" "$attr" 2>/dev/null
+         declare -a array
+
+         opt_add_arg "o" "opt" "$attr" "$default" 2>/dev/null
   )
 
   It "$3 the attribute '$1'"
-    When call _test_opt_add_arg_attr "$1"
+    When call _test_opt_add_arg_attr "$1" "$4"
     The status should equal "$2"
   End
 End
@@ -143,6 +149,53 @@ Describe "opt_parse()"
     When call _test_opt_parse_callback_retval
     The status should equal 123
   End
+
+  It "adds elements to an array"
+    _test_opt_parse_array_append() (
+           declare -a array
+           declare -a expected
+
+           expected=(
+                   123
+           )
+
+           opt_add_arg "o" "opt" "a" "array"
+           opt_parse "-o" "123"
+
+           array_identical array expected
+           return "$?"
+    )
+
+    When call _test_opt_parse_array_append
+    The status should equal 0
+  End
+
+  It "does not overwrite existing elements"
+    _test_opt_parse_array_no_overwrite() (
+           declare -a array
+           declare -a expected
+
+           array=(
+                   123
+                   234
+           )
+           expected=(
+                   123
+                   234
+                   345
+                   456
+           )
+
+           opt_add_arg "o" "opt" "a" "array"
+           opt_parse "-o" "345" "--opt" "456"
+
+           array_identical array expected
+           return "$?"
+    )
+
+    When call _test_opt_parse_array_no_overwrite
+    The status should equal 0
+  End
 End
 
 Describe "opt_get()"