Ultima attività 1 month ago

nuno ha revisionato questo gist 1 month ago. Vai alla revisione

1 file changed, 137 insertions

gistfile1.txt(file creato)

@@ -0,0 +1,137 @@
1 + function flag::parse() {
2 + local ctx="${_CURRENT_COMMAND:-__global__}"
3 +
4 + # Reset runtime
5 + _FLAG_VALUES=(); _FLAG_ARRAYS=(); _FLAG_SET=(); _FLAG_ARGS=()
6 +
7 + # Check for --help/-h first (fast path)
8 + local arg
9 + for arg in "$@"; do
10 + if [[ "$arg" == "--help" || "$arg" == "-h" ]]; then
11 + local cmd="${_CURRENT_COMMAND%%::*}"
12 + declare -f hook::fire &>/dev/null && \
13 + hook::fire "command:help:${cmd}" "$cmd" "${_CURRENT_COMMAND##*::}"
14 + return 1
15 + fi
16 + done
17 +
18 + # Initialize from per-command index (fast — no full registry scan)
19 + local flag key type default_val
20 + for flag in ${_FLAG_INDEX[$ctx]:-}; do
21 + key="${ctx}:${flag}"
22 + [[ -z "${_FLAG_REGISTRY[$key]+x}" ]] && continue
23 + type="${_FLAG_REGISTRY[$key]%%|*}"
24 + default_val="${_FLAG_C_DEFAULT[$key]:-}"
25 + case "$type" in
26 + bool) _FLAG_VALUES["$flag"]="${default_val:-false}" ;;
27 + value) [[ -n "$default_val" ]] && _FLAG_VALUES["$flag"]="$default_val" ;;
28 + array) _FLAG_ARRAYS["$flag"]="" ;;
29 + esac
30 + done
31 +
32 + # Parse args
33 + while [[ $# -gt 0 ]]; do
34 + arg="$1"
35 +
36 + if [[ "$arg" == "--" ]]; then
37 + shift; _FLAG_ARGS+=("$@"); break
38 + fi
39 +
40 + if [[ "$arg" != --* ]]; then
41 + _FLAG_ARGS+=("$arg"); shift; continue
42 + fi
43 +
44 + key="${ctx}:${arg}"
45 + if [[ -z "${_FLAG_REGISTRY[$key]+x}" ]]; then
46 + log::error "Unknown flag: ${arg}"; return 1
47 + fi
48 +
49 + type="${_FLAG_REGISTRY[$key]%%|*}"
50 +
51 + case "$type" in
52 + bool)
53 + _FLAG_VALUES["$arg"]="true"
54 + _FLAG_SET["$arg"]="1"
55 + shift
56 + ;;
57 + value)
58 + if [[ $# -lt 2 || "$2" == --* ]]; then
59 + log::error "Flag ${arg} requires a value"; return 1
60 + fi
61 + local val="$2"
62 + local vtype="${_FLAG_C_TYPE[$key]:-}"
63 + if [[ "$vtype" == "int" ]]; then
64 + if ! [[ "$val" =~ ^[0-9]+$ ]]; then
65 + log::error "Flag ${arg} requires an integer, got: ${val}"; return 1
66 + fi
67 + local min="${_FLAG_C_MIN[$key]:-}" max="${_FLAG_C_MAX[$key]:-}"
68 + [[ -n "$min" && "$val" -lt "$min" ]] && \
69 + log::error "Flag ${arg} minimum is ${min}, got: ${val}" && return 1
70 + [[ -n "$max" && "$val" -gt "$max" ]] && \
71 + log::error "Flag ${arg} maximum is ${max}, got: ${val}" && return 1
72 + fi
73 + local choices="${_FLAG_C_CHOICES[$key]:-}"
74 + if [[ -n "$choices" ]]; then
75 + local valid=false choice
76 + local OLD_IFS="$IFS"
77 + IFS='|'
78 + local -a choice_list=($choices)
79 + IFS="$OLD_IFS"
80 + local choice
81 + for choice in "${choice_list[@]}"; do
82 + [[ "$val" == "$choice" ]] && valid=true && break
83 + done
84 + unset IFS
85 + if ! $valid; then
86 + log::error "Flag ${arg} must be one of: ${choices//|/, }, got: ${val}"
87 + return 1
88 + fi
89 + fi
90 + _FLAG_VALUES["$arg"]="$val"
91 + _FLAG_SET["$arg"]="1"
92 + shift 2
93 + ;;
94 + array)
95 + if [[ $# -lt 2 || "$2" == --* ]]; then
96 + log::error "Flag ${arg} requires a value"; return 1
97 + fi
98 + if [[ -n "${_FLAG_ARRAYS[$arg]:-}" ]]; then
99 + _FLAG_ARRAYS["$arg"]+=$'\n'"$2"
100 + else
101 + _FLAG_ARRAYS["$arg"]="$2"
102 + fi
103 + _FLAG_SET["$arg"]="1"
104 + shift 2
105 + ;;
106 + esac
107 + done
108 +
109 + # Validate required
110 + for flag in ${_FLAG_INDEX[$ctx]:-}; do
111 + key="${ctx}:${flag}"
112 + [[ -z "${_FLAG_C_REQUIRED[$key]:-}" ]] && continue
113 + if [[ -z "${_FLAG_SET[$flag]+x}" && -z "${_FLAG_VALUES[$flag]:-}" ]]; then
114 + log::error "Flag ${flag} is required"; return 1
115 + fi
116 + done
117 +
118 + # Validate exclusive groups
119 + local groups="${_FLAG_EXCLUSIVE_GROUPS[${_CURRENT_COMMAND%%::*}]:-}"
120 + if [[ -n "$groups" ]]; then
121 + local group
122 + while IFS= read -r group; do
123 + [[ -z "$group" ]] && continue
124 + local -a members=()
125 + local OLD_IFS="$IFS"; IFS=','; read -ra members <<< "$group"; IFS="$OLD_IFS"
126 + local found_count=0 found_flags="" member
127 + for member in "${members[@]}"; do
128 + flag::set "$member" && (( found_count++ )) && found_flags+=" $member"
129 + done
130 + if [[ $found_count -gt 1 ]]; then
131 + log::error "Flags${found_flags} are mutually exclusive"; return 1
132 + fi
133 + done < <(printf '%s' "$groups" | tr '|' '\n')
134 + fi
135 +
136 + return 0
137 + }
Più nuovi Più vecchi