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