Skip to content

Commit

Permalink
refactor(xfunc ARRAY filter): separate predicate
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed May 3, 2023
1 parent 0508968 commit a9a7bd3
Showing 1 changed file with 91 additions and 49 deletions.
140 changes: 91 additions & 49 deletions completions/ARRAY
Original file line number Diff line number Diff line change
@@ -1,5 +1,86 @@
# Utility xfunc functions for array manipulations -*- shell-script -*-

# usage: _comp_xfunc_ARRAY__init_predicate pattern pattype [anchoring flags]
# @param $1 pattern Pattern
# @param $2 pattype /[EFG]/ or empty
# @param[opt] $3 anchoring /[psmx]/ or empty
# @param[opt] $4 flags /r/ or empty
# See _comp_xfunc_ARRAY_filter for details of pattern, pattype,
# anchoring, and flags.
# @var[out] _predicate
# @var[out] _predicate_pat
# @var[out] _predicate_type
# @var[out] _predicate_revert
_comp_xfunc_ARRAY__init_predicate()
{
_predicate=false
_predicate_pat=$1
_predicate_type=$2
_predicate_revert=""

local old_nocasematch=""
if shopt -q nocasematch; then
old_nocasematch=set
shopt -u nocasematch
fi

local _pattype=$2 _anchoring=${3-} flags=${4-}
case $_pattype in
E)
case $_anchoring in
p) _predicate='[[ $_value =~ ^($_predicate_pat) ]]' ;;
s) _predicate='[[ $_value =~ ($_predicate_pat)$ ]]' ;;
x) _predicate='[[ $_value =~ ^($_predicate_pat)$ ]]' ;;
*) _predicate='[[ $_value =~ $_predicate_pat ]]' ;;
esac
;;
F)
case $_anchoring in
p) _predicate='[[ $_value == "$_predicate_pat"* ]]' ;;
s) _predicate='[[ $_value == *"$_predicate_pat" ]]' ;;
x) _predicate='[[ $_value == "$_predicate_pat" ]]' ;;
*) _predicate='[[ $_value == *"$_predicate_pat"* ]]' ;;
esac
;;
G)
case $_anchoring in
p) _predicate='[[ $_value == $_predicate_pat* ]]' ;;
s) _predicate='[[ $_value == *$_predicate_pat ]]' ;;
m) _predicate='[[ $_value == *$_predicate_pat* ]]' ;;
*) _predicate='[[ $_value == $_predicate_pat ]]' ;;
esac
;;
*)
if type -t "$2" &>/dev/null; then
_predicate="$2 \"\$_value\""
else
_predicate="local -x value=\$_value; $2"
fi
;;
esac

[[ $_flags == *r* ]] && _predicate_revert=set
[[ $old_nocasematch ]] && shopt -s nocasematch
}

_comp_xfunc_ARRAY__predicate()
{
local _value=$1
eval "$_predicate"

local _ext=$?
case $_ext in
[01]) [[ $_predicate_revert ]] && _ext=$((1 - _ext)) ;;
27) ;;
*)
printf 'bash_completion: %s: %s\n' "$FUNCNAME" \
"filter condition broken '${_predicate_type:+-$_predicate_type }$2'" >&2
return 2
;;
esac
return "$_ext"
}

# Filter the array elements with the specified condition.
# @param $1 Array name (that is not "value", "_*" or other internal variable
# names)
Expand Down Expand Up @@ -80,67 +161,28 @@ _comp_xfunc_ARRAY_filter()
elif [[ $1 == @(_*|OPTIND|OPTARG|OPTERR) ]]; then
printf 'bash_completion: %s: %s\n' "$FUNCNAME" "array name '$1' is reserved for internal uses" >&2
return 2
elif [[ ! $_pattype && $1 == value ]]; then
printf 'bash_completion: %s: %s\n' "$FUNCNAME" "array name '$1' cannot be used for the predicate" >&2
return 2
fi
# When the array is empty:
eval "((\${#$1[@]}))" || return 0

local _predicate='' _pattern=$2
case $_pattype in
E)
case $_anchoring in
p) _predicate='[[ $_value =~ ^($_pattern) ]]' ;;
s) _predicate='[[ $_value =~ ($_pattern)$ ]]' ;;
x) _predicate='[[ $_value =~ ^($_pattern)$ ]]' ;;
*) _predicate='[[ $_value =~ $_pattern ]]' ;;
esac
;;
F)
case $_anchoring in
p) _predicate='[[ $_value == "$_pattern"* ]]' ;;
s) _predicate='[[ $_value == *"$_pattern" ]]' ;;
x) _predicate='[[ $_value == "$_pattern" ]]' ;;
*) _predicate='[[ $_value == *"$_pattern"* ]]' ;;
esac
;;
G)
case $_anchoring in
p) _predicate='[[ $_value == $_pattern* ]]' ;;
s) _predicate='[[ $_value == *$_pattern ]]' ;;
m) _predicate='[[ $_value == *$_pattern* ]]' ;;
*) _predicate='[[ $_value == $_pattern ]]' ;;
esac
;;
*)
if type -t "$2" &>/dev/null; then
_predicate="$2 \"\$_value\""
else
_predicate="local -x value=\$_value; $2"
fi
;;
esac
local _predicate _predicate_pat _predicate_type _predicate_revert
_comp_xfunc_ARRAY__init_predicate "$2" "$_pattype" "$_anchoring" "$_flags"

local _unset="" _expected_status=0
[[ $_flags == *r* ]] && _expected_status=1
local _unset=""

local _indices _index _value
local _indices _index _ref
eval "_indices=(\"\${!$1[@]}\")"
for _index in "${_indices[@]}"; do
eval "_value=\${$1[\$_index]}; $_predicate"
_ref="$1[\$_index]"
_comp_xfunc_ARRAY__predicate "${!_ref}"
case $? in
"$_expected_status") continue ;;
[01])
unset -v "$1[\$_index]"
0) continue ;;
1)
unset -v "$_ref"
_unset=set
;;
27) break ;;
*)
printf 'bash_completion: %s: %s\n' "$FUNCNAME" \
"filter condition broken '${_pattype:+-$_pattype }$2'" >&2
return 2
;;
*) return 2 ;;
esac
done

Expand Down

0 comments on commit a9a7bd3

Please sign in to comment.