|
1 | 1 | # Utility xfunc functions for array manipulations -*- shell-script -*- |
2 | 2 |
|
| 3 | +# usage: _comp_xfunc_ARRAY__init_predicate pattern pattype [anchoring flags] |
| 4 | +# @param $1 pattern Pattern |
| 5 | +# @param $2 pattype /[EFG]/ or empty |
| 6 | +# @param[opt] $3 anchoring /[psmx]/ or empty |
| 7 | +# @param[opt] $4 flags /r/ or empty |
| 8 | +# See _comp_xfunc_ARRAY_filter for details of pattern, pattype, |
| 9 | +# anchoring, and flags. |
| 10 | +# |
| 11 | +# @var[out] _predicate[0] command |
| 12 | +# @var[out] _predicate[1] pattern |
| 13 | +# @var[out] _predicate[2] type |
| 14 | +# @var[out] _predicate[3] revert |
| 15 | +_comp_xfunc_ARRAY__init_predicate() |
| 16 | +{ |
| 17 | + _predicate[0]=false |
| 18 | + _predicate[1]=$1 |
| 19 | + _predicate[2]=$2 |
| 20 | + _predicate[3]="" |
| 21 | + |
| 22 | + local old_nocasematch="" |
| 23 | + if shopt -q nocasematch; then |
| 24 | + old_nocasematch=set |
| 25 | + shopt -u nocasematch |
| 26 | + fi |
| 27 | + |
| 28 | + local _pattype=$2 _anchoring=${3-} flags=${4-} |
| 29 | + case $_pattype in |
| 30 | + E) |
| 31 | + case $_anchoring in |
| 32 | + p) _predicate[0]='[[ $_value =~ ^(${_predicate[1]}) ]]' ;; |
| 33 | + s) _predicate[0]='[[ $_value =~ (${_predicate[1]})$ ]]' ;; |
| 34 | + x) _predicate[0]='[[ $_value =~ ^(${_predicate[1]})$ ]]' ;; |
| 35 | + *) _predicate[0]='[[ $_value =~ ${_predicate[1]} ]]' ;; |
| 36 | + esac |
| 37 | + ;; |
| 38 | + F) |
| 39 | + case $_anchoring in |
| 40 | + p) _predicate[0]='[[ $_value == "${_predicate[1]}"* ]]' ;; |
| 41 | + s) _predicate[0]='[[ $_value == *"${_predicate[1]}" ]]' ;; |
| 42 | + x) _predicate[0]='[[ $_value == "${_predicate[1]}" ]]' ;; |
| 43 | + *) _predicate[0]='[[ $_value == *"${_predicate[1]}"* ]]' ;; |
| 44 | + esac |
| 45 | + ;; |
| 46 | + G) |
| 47 | + case $_anchoring in |
| 48 | + p) _predicate[0]='[[ $_value == ${_predicate[1]}* ]]' ;; |
| 49 | + s) _predicate[0]='[[ $_value == *${_predicate[1]} ]]' ;; |
| 50 | + m) _predicate[0]='[[ $_value == *${_predicate[1]}* ]]' ;; |
| 51 | + *) _predicate[0]='[[ $_value == ${_predicate[1]} ]]' ;; |
| 52 | + esac |
| 53 | + ;; |
| 54 | + *) |
| 55 | + if type -t "$2" &>/dev/null; then |
| 56 | + _predicate[0]="$2 \"\$_value\"" |
| 57 | + else |
| 58 | + _predicate[0]="local -x value=\$_value; $2" |
| 59 | + fi |
| 60 | + ;; |
| 61 | + esac |
| 62 | + |
| 63 | + [[ $_flags == *r* ]] && _predicate[3]=set |
| 64 | + [[ $old_nocasematch ]] && shopt -s nocasematch |
| 65 | +} |
| 66 | + |
| 67 | +_comp_xfunc_ARRAY__predicate() |
| 68 | +{ |
| 69 | + local _value=$1 |
| 70 | + eval "${_predicate[0]}" |
| 71 | + |
| 72 | + local _ext=$? |
| 73 | + case $_ext in |
| 74 | + [01]) [[ ${_predicate[3]} ]] && _ext=$((1 - _ext)) ;; |
| 75 | + 27) ;; |
| 76 | + *) |
| 77 | + printf 'bash_completion: %s: %s\n' "$FUNCNAME" \ |
| 78 | + "filter condition broken '${_predicate[2]:+-${_predicate[2]} }$2'" >&2 |
| 79 | + return 2 |
| 80 | + ;; |
| 81 | + esac |
| 82 | + return "$_ext" |
| 83 | +} |
| 84 | + |
3 | 85 | # Filter the array elements with the specified condition. |
4 | 86 | # @param $1 Array name (that is not "value", "_*" or other internal variable |
5 | 87 | # names) |
@@ -80,67 +162,28 @@ _comp_xfunc_ARRAY_filter() |
80 | 162 | elif [[ $1 == @(_*|OPTIND|OPTARG|OPTERR) ]]; then |
81 | 163 | printf 'bash_completion: %s: %s\n' "$FUNCNAME" "array name '$1' is reserved for internal uses" >&2 |
82 | 164 | return 2 |
83 | | - elif [[ ! $_pattype && $1 == value ]]; then |
84 | | - printf 'bash_completion: %s: %s\n' "$FUNCNAME" "array name '$1' cannot be used for the predicate" >&2 |
85 | | - return 2 |
86 | 165 | fi |
87 | 166 | # When the array is empty: |
88 | 167 | eval "((\${#$1[@]}))" || return 0 |
89 | 168 |
|
90 | | - local _predicate='' _pattern=$2 |
91 | | - case $_pattype in |
92 | | - E) |
93 | | - case $_anchoring in |
94 | | - p) _predicate='[[ $_value =~ ^($_pattern) ]]' ;; |
95 | | - s) _predicate='[[ $_value =~ ($_pattern)$ ]]' ;; |
96 | | - x) _predicate='[[ $_value =~ ^($_pattern)$ ]]' ;; |
97 | | - *) _predicate='[[ $_value =~ $_pattern ]]' ;; |
98 | | - esac |
99 | | - ;; |
100 | | - F) |
101 | | - case $_anchoring in |
102 | | - p) _predicate='[[ $_value == "$_pattern"* ]]' ;; |
103 | | - s) _predicate='[[ $_value == *"$_pattern" ]]' ;; |
104 | | - x) _predicate='[[ $_value == "$_pattern" ]]' ;; |
105 | | - *) _predicate='[[ $_value == *"$_pattern"* ]]' ;; |
106 | | - esac |
107 | | - ;; |
108 | | - G) |
109 | | - case $_anchoring in |
110 | | - p) _predicate='[[ $_value == $_pattern* ]]' ;; |
111 | | - s) _predicate='[[ $_value == *$_pattern ]]' ;; |
112 | | - m) _predicate='[[ $_value == *$_pattern* ]]' ;; |
113 | | - *) _predicate='[[ $_value == $_pattern ]]' ;; |
114 | | - esac |
115 | | - ;; |
116 | | - *) |
117 | | - if type -t "$2" &>/dev/null; then |
118 | | - _predicate="$2 \"\$_value\"" |
119 | | - else |
120 | | - _predicate="local -x value=\$_value; $2" |
121 | | - fi |
122 | | - ;; |
123 | | - esac |
| 169 | + local _predicate |
| 170 | + _comp_xfunc_ARRAY__init_predicate "$2" "$_pattype" "$_anchoring" "$_flags" |
124 | 171 |
|
125 | | - local _unset="" _expected_status=0 |
126 | | - [[ $_flags == *r* ]] && _expected_status=1 |
| 172 | + local _unset="" |
127 | 173 |
|
128 | | - local _indices _index _value |
| 174 | + local _indices _index _ref |
129 | 175 | eval "_indices=(\"\${!$1[@]}\")" |
130 | 176 | for _index in "${_indices[@]}"; do |
131 | | - eval "_value=\${$1[\$_index]}; $_predicate" |
| 177 | + _ref="$1[\$_index]" |
| 178 | + _comp_xfunc_ARRAY__predicate "${!_ref}" |
132 | 179 | case $? in |
133 | | - "$_expected_status") continue ;; |
134 | | - [01]) |
135 | | - unset -v "$1[\$_index]" |
| 180 | + 0) continue ;; |
| 181 | + 1) |
| 182 | + unset -v "$_ref" |
136 | 183 | _unset=set |
137 | 184 | ;; |
138 | 185 | 27) break ;; |
139 | | - *) |
140 | | - printf 'bash_completion: %s: %s\n' "$FUNCNAME" \ |
141 | | - "filter condition broken '${_pattype:+-$_pattype }$2'" >&2 |
142 | | - return 2 |
143 | | - ;; |
| 186 | + *) return 2 ;; |
144 | 187 | esac |
145 | 188 | done |
146 | 189 |
|
|
0 commit comments