Skip to content

Commit 270cdc6

Browse files
committed
feat(_comp_index_of): support options
1 parent 11c28cf commit 270cdc6

File tree

1 file changed

+84
-12
lines changed

1 file changed

+84
-12
lines changed

completions/ARRAY

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)