@@ -224,25 +224,97 @@ _comp_compact()
224224 _comp_compact__array=(" ${_comp_compact__array[@]} " )
225225}
226226
227+ # @version bash-4.3
228+ _comp_xfunc_ARRAY_reverse ()
229+ {
230+ _comp_compact " $1 "
231+ local -n _comp_reverse__arr=$1
232+ local _comp_reverse__i=0
233+ local _comp_reverse__j=$(( ${# _comp_reverse__arr[@]} - 1 ))
234+ local _comp_reverse__tmp
235+ while (( _comp_reverse__i < _comp_reverse__j)) ; do
236+ _comp_reverse__tmp=${_comp_reverse__arr[_comp_reverse__i]}
237+ _comp_reverse__arr[_comp_reverse__i]=${_comp_reverse__arr[_comp_reverse__j]}
238+ _comp_reverse__arr[_comp_reverse__j]=$_comp_reverse__tmp
239+ (( _comp_reverse__i++, _comp_reverse__j-- ))
240+ done
241+ }
242+
243+ # usage: _comp_index_of [-EFGpxmxrl] array pattern
227244# Find the index of a matching element
245+ # Options:
246+ #
247+ # -EFGe Select the type of the pattern. The default is -F.
248+ # -psmx Select the anchoring option.
249+ # -r Revert the condition.
250+ # See _comp_xfunc_ARRAY_filter for the details of these options.
251+ #
252+ # -l Get the last index of matching elements.
253+ #
228254# @var[out] ret
229255# @version bash-4.3
230256_comp_index_of ()
231257{
232- # TODO getopts -> -r gets rightmost (last) index
233- # TODO getopts: -R uses regex instead of glob
234- local -n _comp_index_of__array=$1
235- local _comp_compact__pattern=$2
236-
237- local -i _comp_index_of__i
238- for _comp_index_of__i in " ${! _comp_index_of__array[@]} " ; do
239- # shellcheck disable=SC2053
240- if [[ ${_comp_index_of__array[_comp_index_of__i]} == $_comp_compact__pattern ]]; then
241- ret=$_comp_index_of__i
242- return 0
243- fi
258+ local _old_nocasematch=" "
259+ if shopt -q nocasematch; then
260+ _old_nocasematch=set
261+ shopt -u nocasematch
262+ fi
263+ local _flags=" " _pattype=F _anchoring=" "
264+ local OPTIND=1 OPTARG=" " OPTERR=0 _opt=" "
265+ while getopts ' EFGepsmxrl' _opt " $@ " ; do
266+ case $_opt in
267+ [EFGe]) _pattype=$_opt ;;
268+ [psmx]) _anchoring=$_opt ;;
269+ [rl]) _flags+=$_opt ;;
270+ * )
271+ printf ' bash_completion: %s: %s\n' " $FUNCNAME " ' usage error' >&2
272+ printf ' usage: %s %s\n' " $FUNCNAME " " [-EFGepsmxrl] ARRAY_NAME CONDITION" >&2
273+ return 2
274+ ;;
275+ esac
244276 done
277+ shift " $(( OPTIND - 1 )) "
278+ if (( $# != 2 )) ; then
279+ printf ' bash_completion: %s: %s\n' " $FUNCNAME " " unexpected number of arguments: $# " >&2
280+ printf ' usage: %s %s\n' " $FUNCNAME " " [-EFGepsmxrl] ARRAY_NAME CONDITION" >&2
281+ [[ $_old_nocasematch ]] && shopt -s nocasematch
282+ return 2
283+ elif [[ $1 != [a-zA-Z_]* ([a-zA-Z_0-9]) ]]; then
284+ printf ' bash_completion: %s: %s\n' " $FUNCNAME " " invalid array name '$1 '." >&2
285+ [[ $_old_nocasematch ]] && shopt -s nocasematch
286+ return 2
287+ elif [[ $1 == @ (_* | OPTIND| OPTARG| OPTERR) ]]; then
288+ printf ' bash_completion: %s: %s\n' " $FUNCNAME " " array name '$1 ' is reserved for internal uses" >&2
289+ [[ $_old_nocasematch ]] && shopt -s nocasematch
290+ return 2
291+ fi
292+ [[ $_old_nocasematch ]] && shopt -s nocasematch
245293
246294 ret=-1
295+
296+ local -n _array=$1
297+ if (( ${# _array[@]} )) ; then
298+ local _predicate
299+ _comp_xfunc_ARRAY__init_predicate " $2 " " $_pattype " " $_anchoring " " $_flags "
300+
301+ local -a _indices=(" ${! _array[@]} " )
302+ [[ $_flags == * l* ]] && _comp_xfunc_ARRAY_reverse _indices
303+
304+ local -i _i
305+ for _i in " ${_indices[@]} " ; do
306+ _comp_xfunc_ARRAY__predicate " ${_array[_i]} "
307+ case $? in
308+ 0)
309+ ret=$_i
310+ return 0
311+ ;;
312+ 1) continue ;;
313+ 27) return 27 ;;
314+ * ) return 2 ;;
315+ esac
316+ done
317+ fi
318+
247319 return 1
248320}
0 commit comments