Skip to content

Commit 6d49487

Browse files
committed
feat(_comp_index_of): support options
1 parent a9a7bd3 commit 6d49487

File tree

1 file changed

+84
-12
lines changed

1 file changed

+84
-12
lines changed

completions/ARRAY

+84-12
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)