|
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