1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-06 11:21:22 +02:00

zsh-workers/7989

This commit is contained in:
Tanaka Akira 1999-09-22 13:17:25 +00:00
parent 5d20d8fcba
commit 7d30343f32
4 changed files with 416 additions and 382 deletions

View file

@ -1,9 +1,5 @@
#autoload
## todo
# imprement `guard' to more generic branch selection.
## usage: _regex_arguments funcname regex
## configuration key used:
@ -23,118 +19,33 @@
## regex word definition:
# elt-pattern = "/" ( pattern | "[]" ) # cutoff
# | "%" pattern # non-cutoff
# lookahead = "@" pattern
# parse-action = "-" zsh-code-to-eval
# complete-action = "!" zsh-code-to-eval
# pattern = "/" ( glob | "[]" ) "/" [ "+" | "-" ]
# lookahead = "%" glob "%"
# guard = "-" zsh-code-to-eval
# action = ":" zsh-code-to-eval
## regex word sequence definition:
# element = elt-pattern [ lookahead ] [ parse-action ] [ complete-action ]
# element = pattern [ lookahead ] [ guard ] [ action ]
#
# regex = element
# | "(" regex ")"
# | regex "#"
# | regex regex
# | regex "|" regex
# | void
# | null
#
# NOTE: void and null has no explicit representation. However null can
# be represent with empty words such as \( \).
# example: (in zsh quoted form)
# $'[^\0]#\0' \# : zero or more words
## auxiliary functions definition:
# nullable : regex -> bool
# first : regex -> list of element
# match : string * list of element -> element + {bottom}
# right : string * element -> string
# left : string * element -> string
# next : regex * element -> regex + {bottom}
# trans : string * string * regex -> (string * string * regex) + {bottom}
# nullable(void) = false
# nullable(null) = true
# nullable(e) = false
# nullable(r #) = true
# nullable(r1 r2) = nullable(r1) and nullable(r2)
# nullable(r1 | r2) = nullable(r1) or nullable(r2)
# first(void) = {}
# first(null) = {}
# first(e) = [ e ]
# first(r #) = first(r)
# first(r1 r2) = nullable(r1) ? first(r1) ++ first(r2) : first(r1)
# first(r1 | r2) = first(r1) ++ first(r2)
# match(s, []) = bottom
# match(s, [e1, e2, ...]) = e if [[ $s = $elt-pattern[e]$lookahead[e]* ]]
# | match(s, [e2, ...]) otherwise
# right(s, e) = ${s##$elt-pattern[e]}
# left(s, e) = ${(M)s##$elt-pattern[e]}
### XXX: It can treat lookaheads if zsh provide $1, $2, ... in perl.
# next(void, e) = bottom
# next(null, e) = bottom
# next(e1, e0) = e1 eq e0 ? null : bottom # eq is test operator of identity equality.
# next(r #, e) = next(r, e) != bottom ? next(r, e) (r #) : bottom
# next(r1 r2, e) = next(r1, e) != bottom ? next(r1, e) r2 : next(r2, e)
# next(r1 | r2, e) = next(r1, e) != bottom ? next(r1, e) : next(r2, e)
# trans( (t, s, r) ) = ( (cutoff(e) ? '' : t ++ left(s, e)), right(s, e), next(r, e) )
# where e = match(s, first(r))
# NOTE: This `next' definition is slightly different to ordinaly one.
# This definition uses only one element of first(r) for transition
# instead of all elements of first(r).
# If _regex_arguments takes the regex r0, the first state of the state
# machine is r0. The state of the state machine transit as follows.
# ('', s0, r0) -> trans('', s0, r0) = (t1, s1, r1) -> trans(t1, s1, r1) -> ...
# If the state is reached to bottom, the state transition is stopped.
# ... -> (tN, sN, rN) -> bottom
# For each transitions (tI, sI, rI) to trans(tI, sI, rI), the state
# machine evaluate parse-action bound to match(sI, first(rI)).
# In parse-action bound to match(sI, first(rI)) = e, it can refer variables:
# _ra_left : tI+1
# _ra_match : left(sI, e)
# _ra_right : sI+1
# If the state transition is stopped, the state machine evaluate
# complete-actions bound to first(rN) if tN and sN does not contain NUL.
# When complete-actions are evaluated, completion focus is restricted to
# tN ++ sN. (This is reason of tN and sN cannot contain NUL when
# completion.)
# Also, if there are last transitions that does not cut off the string
# (tJ ++ sJ = tJ+1 ++ sJ+1 = ... = tN-1 ++ sN-1 = tN ++ sN),
# complete-actions bound to them
# --- match(sJ, first(rJ)), ..., match(sN-1, first(rN-1)) --- are also
# evaluated before complete-actions bound to first(rN).
# example:
# compdef _tst tst
# _regex_arguments _tst /$'[^\0]#\0' /$'[^\0]#\0' '!compadd aaa'
# _regex_arguments _tst /$'[^\0]#\0'/ /$'[^\0]#\0'/ :'compadd aaa'
# _tst complete `aaa' for first argument.
# First $'[^\0]#\0' is required to match with command name.
# _regex_arguments _tst /$'[^\0]#\0' \( /$'[^\0]#\0' '!compadd aaa' /$'[^\0]#\0' !'compadd bbb' \) \#
# _regex_arguments _tst /$'[^\0]#\0'/ \( /$'[^\0]#\0'/ :'compadd aaa' /$'[^\0]#\0'/ :'compadd bbb' \) \#
# _tst complete `aaa' for (2i+1)th argument and `bbb' for (2i)th argument.
# _regex_arguments _tst /$'[^\0]#\0' \( /$'[^\0]#\0' '!compadd aaa' \| /$'[^\0]#\0' !'compadd bbb' \) \#
# _regex_arguments _tst /$'[^\0]#\0'/ \( /$'[^\0]#\0'/ :'compadd aaa' \| /$'[^\0]#\0'/ :'compadd bbb' \) \#
# _tst complete `aaa' or `bbb'.
## Recursive decent regex parser
@ -146,37 +57,42 @@
# 2 : fatal parse error
_ra_parse_elt () {
: index=$index "[$regex[$index]]"
local state
local state act
if (( $#regex < index )); then
return 1
else
case "$regex[index]" in
[/%]*) state=$index
/*/([-+]|)) state=$index
first=($state)
last=($state)
nullable=
case "${regex[index][1]}" in
/) cutoff[$state]=yes ;;
%) cutoff[$state]= ;;
case "$regex[index]" in
*/+) cutoff[$state]=+;;
*/) cutoff[$state]=/;;
*/-) cutoff[$state]=-;;
esac
pattern[$state]="${regex[index++][2,-1]}"
[[ -n "$pattern[$state]" ]] && pattern[$state]="($pattern[$state])"
if [[ $index -le $#regex && $regex[index] = @* ]]; then
lookahead[$state]="${regex[index++][2,-1]}"
[[ -n "$lookahead[$state]" ]] && lookahead[$state]="($lookahead[$state])"
pattern[$state]="${${regex[index++]#/}%/([-+]|)}"
if [[ $pattern[$state] != "[]" ]]; then
pattern[$state]="(#b)((#B)$pattern[$state])"
fi
if [[ $index -le $#regex && $regex[index] = %*% ]]; then
lookahead[$state]="(#B)${regex[index++][2,-2]}"
else
lookahead[$state]=""
fi
if [[ $index -le $#regex && $regex[index] = -* ]]; then
parse_action[$state]="${regex[index++][2,-1]}"
guard[$state]="${regex[index++][2,-1]}"
else
parse_action[$state]=""
guard[$state]=""
fi
if [[ $index -le $#regex && $regex[index] = \!* ]]; then
complete_action[$state]="${regex[index++][2,-1]}"
if [[ $index -le $#regex && $regex[index] = :* ]]; then
act="${regex[index++][2,-1]}"
action[$state]="$act"
# `actions[$act]="${actions[$act]} $state"' is not work properly
# because $act on lhs is expanded twice.
: ${actions[$act]::="${actions[$act]} $state"}
else
complete_action[$state]=""
action[$state]=""
fi
;;
\() (( index++ ))
@ -193,7 +109,6 @@ _ra_parse_elt () {
}
_ra_parse_clo () {
: index=$index "[$regex[$index]]"
_ra_parse_elt || return $?
if (( index <= $#regex )) && [[ "$regex[$index]" = \# ]]; then
@ -207,7 +122,6 @@ _ra_parse_clo () {
}
_ra_parse_seq () {
: index=$index "[$regex[$index]]"
local last_seq
local first_seq nullable_seq
first_seq=()
@ -248,7 +162,6 @@ _ra_parse_seq () {
}
_ra_parse_alt () {
: index=$index "[$regex[$index]]"
local last_alt
local first_alt nullable_alt
first_alt=()
@ -286,8 +199,9 @@ _ra_parse_alt () {
_ra_gen_func () {
local old new
local state next index
local start="${(j/:/)first}"
local state index
local test tmp
local start="0"
old=()
new=($start)
@ -295,8 +209,8 @@ _ra_gen_func () {
print -lr - \
"$funcname () {" \
'setopt localoptions extendedglob' \
'local _ra_state _ra_left _ra_match _ra_right _ra_actions _ra_tmp' \
"_ra_state='$start'" \
'local _ra_state _ra_left _ra_right _ra_actions' \
"_ra_state=$start" \
'_ra_left=' \
'_ra_right="${(pj:\0:)${(@)words[1,CURRENT - 1]:Q}}"$'\''\0'\''"$PREFIX"' \
'_ra_actions=()' \
@ -307,99 +221,114 @@ _ra_gen_func () {
state="$new[1]"
shift new
old=("$old[@]" "$state")
print -lr - \
"$state)" \
'case "$_ra_right" in'
for index in ${(s/:/)state}; do
if [[ "$pattern[$index]" != "([])" ]]; then
next="${(j/:/)${(@)=tbl[$index]}}"
print -lr - \
"$pattern[$index]$lookahead[$index]*)"
if [[ -n "$pattern[$index]" ]]; then
if [[ -n "$cutoff[$index]" ]]; then
print -lr - \
'_ra_match="${(M)_ra_right##'"$pattern[$index]"'}"' \
'_ra_right="$_ra_right[$#_ra_match + 1, -1]"' \
'_ra_left=' \
'if (( $#_ra_match )); then' \
'_ra_actions=()'
if [[ -n "${complete_action[$index]:q}" ]]; then
print -lr - \
'else' \
'_ra_actions=("$_ra_actions[@]" '"${complete_action[$index]:q}"')'
fi
print -lr - \
'fi'
else
print -lr - \
'_ra_match="${(M)_ra_right##'"$pattern[$index]"'}"' \
'_ra_right="$_ra_right[$#_ra_match + 1, -1]"' \
'_ra_left="$_ra_left$_ra_match"'
if [[ -n "${complete_action[$index]:q}" ]]; then
print -lr - \
'_ra_actions=("$_ra_actions[@]" '"${complete_action[$index]:q}"')'
fi
fi
else
print -lr - \
'_ra_match=' \
'_ra_actions=("$_ra_actions[@]" '"${complete_action[$index]:q}"')'
fi
print -lr - \
"$parse_action[$index]"
if [[ -n $next ]]; then
print -lr - \
"_ra_state=$next"
(( $old[(I)$next] || $new[(I)$next] )) || new=($next "$new[@]")
else
print -lr - \
'_message "no arg"' \
'break'
fi
print -lr - \
';;'
fi
done
"$state)"
_ra_gen_parse_state
print -lr - \
'*)' \
'if [[ "$_ra_left$_ra_right" = *$'\''\0'\''* ]]; then' \
'_message "parse failed before current word"' \
'else' \
'compset -p $(( $#PREFIX - $#_ra_right - $#_ra_left ))'
print -lr - \
'for _ra_tmp in $_ra_actions; do' \
'eval "$_ra_tmp"' \
'done'
for index in ${(s/:/)state}; do
print -lr - \
"$complete_action[$index]"
done
print -lr - \
'fi' \
'break' \
';;' \
'esac' \
';;'
done
print -lr - \
'esac' \
'done' \
'while (( $#_ra_actions )); do' \
'case "$_ra_actions[1]" in'
for tmp in "${(@k)actions}"; do
#print -lr - "KEY:{$tmp}" "VAL:{$actions[$tmp]}" >&2
print -lr - "${(j:);&:)${=actions[$tmp]}})" $tmp ';;'
done
print -lr - \
'esac' \
'shift _ra_actions' \
'done' \
'}'
}
_ra_gen_parse_state () {
local actions i
test='if'
for index in $=tbl[$state]; do
if [[ "$pattern[$index]" != "[]" ]]; then
if [[ -z "$guard[$index]" ]]; then
print -lr - \
"$test [[ \$_ra_right = $pattern[$index]$lookahead[$index]* ]]"
else
print -lr - \
"$test [[ \$_ra_right = $pattern[$index]$lookahead[$index]* ]] && {" \
"$guard[$index]" \
"}"
fi
test='elif'
(( $old[(I)$index] || $new[(I)$index] )) || new=($index "$new[@]")
print -lr - \
"then" \
"_ra_state=$index" \
'_ra_right="${_ra_right[mend[1] + 1, -1]}"'
actions=()
for i in $=tbl[$index]; do
if [[ -n $action[$i] ]]; then
actions=($actions $i)
fi
done
case "$cutoff[$index]" in
+) print -lr - \
'_ra_left="$_ra_left$match[1]"'
if (( $#actions )); then
print -lr - \
"_ra_actions=($actions \$_ra_actions)"
fi
;;
/) print -lr - \
'_ra_left='
print -lr - \
'if (( mend[1] )); then' \
"_ra_actions=($actions)"
if (( $#actions )); then
print -lr - \
'else' \
"_ra_actions=($actions \$_ra_actions)"
fi
print -lr - \
'fi'
;;
-) print -lr - \
'_ra_left=' \
"_ra_actions=($actions)"
;;
esac
fi
done
if [[ $test != 'if' ]]; then
# Some branchs are exists. But all of them are failed.
print -lr - \
'else' \
'if [[ "$_ra_left$_ra_right" = *$'\''\0'\''* ]]; then' \
'_message "parse failed before current word"' \
'_ra_actions=()' \
'else' \
'compset -p $(( $#PREFIX - $#_ra_right - $#_ra_left ))' \
'fi' \
'break' \
'fi'
else
# There are no branch.
print -lr - \
'_message "no more arguments"' \
'_ra_actions=()' \
'break'
fi
}
_regex_arguments () {
setopt localoptions extendedglob
local funcname="_regex_arguments_tmp"
local funcdef
typeset -A tbl cutoff pattern lookahead parse_action complete_action
typeset -A tbl cutoff pattern lookahead guard action actions
local regex index first last nullable
local i state next
@ -408,18 +337,16 @@ _regex_arguments () {
local cache_test
if ! [[ -f "$cache_file" ]] || ! source "$cache_file" "$@"; then
cache_test='[[ $# -eq '$#' && "$*" = '"${*:q}"' ]]'
funcname="$1"
shift
regex=("$@")
regex=("${(@)argv[2,-1]}")
index=1
tbl=()
pattern=()
lookahead=()
parse_action=()
complete_action=()
guard=()
action=()
actions=()
_ra_parse_alt
if (( $? == 2 || index != $#regex + 1 )); then
@ -431,18 +358,21 @@ _regex_arguments () {
return 1
fi
funcdef="$(_ra_gen_func)"
tbl[0]=" $first"
unfunction "$funcname" 2>/dev/null
eval "${(F)funcdef}"
funcdef="$(_ra_gen_func)"
[[ -d "$cache_dir" && -w "$cache_dir" ]] && {
if [[ -d "$cache_dir" && -w "$cache_dir" ]]; then
print -lr - \
"if $cache_test; then" \
'if [[ $# -eq '$#' && "$*" = '"${*:q}"' ]]; then' \
"$funcdef" \
'true; else false; fi' > "${cache_file}.$HOST.$$"
source "${cache_file}.$HOST.$$" "$@"
mv "${cache_file}.$HOST.$$" "${cache_file}"
}
else
source =(print -lr - "$funcdef")
fi
fi
}

View file

@ -17,7 +17,7 @@ _apt_arguments () {
funcname="$1"
shift
typeset -A canonicalize options
typeset -A canonicalize num_options
local short_hasarg short_bool short_intlevel short_configfile short_arbitem
local long_hasarg long_bool long_intlevel long_configfile long_arbitem
local comp_hasarg=''
@ -28,11 +28,11 @@ _apt_arguments () {
type="${1#*:}"
case $type in
bool) options[$opts]=1;;
intlevel) options[$opts]=-1;;
configfile) options[$opts]=1;;
arbitem) options[$opts]=-1;;
*) options[$opts]=1
bool) num_options[$opts]=1;;
intlevel) num_options[$opts]=-1;;
configfile) num_options[$opts]=1;;
arbitem) num_options[$opts]=-1;;
*) num_options[$opts]=1
comp_hasarg="${comp_hasarg}$opts) $type;;"$'\n'
type=hasarg;;
esac
@ -82,25 +82,25 @@ _apt_arguments () {
comp_short=\
'if [[ $PREFIX = -'"$short_seq"' ]]; then
_apt_consume_short ${PREFIX[2,-1]}
tmp1=(${(M)${(s:,:)${(kj:,:)options[(R)*~0]}}:#-?})
tmp1=(${(M)${(s:,:)${(kj:,:)num_options[(R)*~0]}}:#-?})
tmp2=(${PREFIX}${^tmp1#-})
_describe -o option tmp1 tmp2
elif [[ -z "$PREFIX" ]]; then
tmp1=(${(M)${(s:,:)${(kj:,:)options[(R)*~0]}}:#-?})
tmp1=(${(M)${(s:,:)${(kj:,:)num_options[(R)*~0]}}:#-?})
_describe -o option tmp1
fi'
comp_long=\
'tmp1="${(j:|:)${(@)${(@M)${(@s:,:)${(@kj:,:)options[(R)*~0]}}:#--*}#--}}"
'tmp1="${(j:|:)${(@)${(@M)${(@s:,:)${(@kj:,:)num_options[(R)*~0]}}:#--*}#--}}"
tmp2=(--${(M)^long_bool:#$~tmp1} --${(M)^long_intlevel:#$~tmp1})
tmp3=(--${(M)^long_hasarg:#$~tmp1} --${(M)^long_configfile:#$~tmp1} --${(M)^long_arbitem:#$~tmp1})
_describe -o option tmp2 -- tmp3 -S= -- bool_prefix -S ""'
comp_long_prefix=\
'tmp1="${(j:|:)${(@)${(@M)${(@s:,:)${(@kj:,:)options[(R)*~0]}}:#--*}#--}}"
'tmp1="${(j:|:)${(@)${(@M)${(@s:,:)${(@kj:,:)num_options[(R)*~0]}}:#--*}#--}}"
tmp2=($_ra_left${(M)^long_bool:#$~tmp1} $_ra_left${(M)^long_intlevel:#$~tmp1})
tmp3=($_ra_left${(M)^long_hasarg:#$~tmp1} $_ra_left${(M)^long_configfile:#$~tmp1} $_ra_left${(M)^long_arbitem:#$~tmp1})
tmp1="${(j:|:)${(@)${(@M)${(@s:,:)${(@kj:,:)options[(R)*~0]}}:#-?}#-}}"
tmp1="${(j:|:)${(@)${(@M)${(@s:,:)${(@kj:,:)num_options[(R)*~0]}}:#-?}#-}}"
tmp2=("$tmp2[@]" $_ra_left${(M)^short_bool:#$~tmp1} $_ra_left${(M)^short_intlevel:#$~tmp1})
tmp3=("$tmp3[@]" $_ra_left${(M)^short_hasarg:#$~tmp1} $_ra_left${(M)^short_configfile:#$~tmp1} $_ra_left${(M)^short_arbitem:#$~tmp1})
_describe -o option tmp2 -- tmp3 -S='
@ -113,203 +113,200 @@ _describe -o option tmp2 -- tmp3 -S='
if (( $#short_hasarg )); then
regex_short=("$regex_short[@]"
/"$short_seq(${(j:|:)short_hasarg})(=|)"
-'_apt_consume_short ${_ra_match%=}; current_option=${canonicalize[-${${_ra_match%=}[-1]}]}'
\( /"$word1" !"$comp_hasarg" \| /"$nul" /"$word" !"$comp_hasarg" \) \|
/"$short_seq(${(j:|:)short_hasarg})(=|)"/
-'_apt_consume_short ${match[1]%=}; current_option=${canonicalize[-${${match[1]%=}[-1]}]}'
\( /"$word1"/ :"$comp_hasarg" \| /"$nul"/ /"$word"/ :"$comp_hasarg" \) \|
)
regex_long_prefix=("$regex_long_prefix[@]"
/"(${(j:|:)short_hasarg})$nul"
-'_apt_consume_short ${_ra_match[-2]}; current_option=${canonicalize[-${${_ra_match%$nul}[-1]}]}'
/"$word" !"$comp_hasarg" \|
/"(${(j:|:)short_hasarg})="
-'_apt_consume_short ${_ra_match[-2]}; current_option=${canonicalize[-${${_ra_match%=}[-1]}]}'
\( /"$word1" !"$comp_hasarg" \| /"$nul" /"$word" !"$comp_hasarg" \) \|
/"(${(j:|:)short_hasarg})$nul"/
-'_apt_consume_short ${match[1][-2]}; current_option=${canonicalize[-${${match[1]%$nul}[-1]}]}'
/"$word"/ :"$comp_hasarg" \|
/"(${(j:|:)short_hasarg})="/
-'_apt_consume_short ${match[1][-2]}; current_option=${canonicalize[-${${match[1]%=}[-1]}]}'
\( /"$word1"/ :"$comp_hasarg" \| /"$nul"/ /"$word"/ :"$comp_hasarg" \) \|
)
fi
if (( $#short_bool )); then
regex_short=("$regex_short[@]"
/"$short_seq(${(j:|:)short_bool})($nul(${(j:|:)bool})|(${(j:|:)bool})|)$nul"
-"_apt_consume_short \${_ra_match%%($nul(${(j:|:)bool})|(${(j:|:)bool})|)$nul}" \|
/"$short_seq(${(j:|:)short_bool})="
-"_apt_consume_short \${_ra_match%=}"
\( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
/"$short_seq(${(j:|:)short_bool})($nul(${(j:|:)bool})|(${(j:|:)bool})|)$nul"/
-"_apt_consume_short \${match[1]%%($nul(${(j:|:)bool})|(${(j:|:)bool})|)$nul}" \|
/"$short_seq(${(j:|:)short_bool})="/
-"_apt_consume_short \${match[1]%=}"
\( /"$word1"/ :"$comp_bool" \| /"$nul"/ /"$word"/ :"$comp_bool" \) \|
)
regex_long_prefix=("$regex_long_prefix[@]"
/"(${(j:|:)short_bool})="
-"_apt_consume_short \${_ra_match[-2]}"
\( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
/"(${(j:|:)short_bool})$nul"
-"_apt_consume_short \${_ra_match[-2]}"
/"((${(j:|:)bool})$nul|)" !"$comp_bool" \|
/"(${(j:|:)short_bool})="/
-"_apt_consume_short \${match[1][-2]}"
\( /"$word1"/ :"$comp_bool" \| /"$nul"/ /"$word"/ :"$comp_bool" \) \|
/"(${(j:|:)short_bool})$nul"/
-"_apt_consume_short \${match[1][-2]}"
/"((${(j:|:)bool})$nul|)"/ :"$comp_bool" \|
)
fi
if (( $#short_intlevel )); then
regex_short=("$regex_short[@]"
/"$short_seq(${(j:|:)short_intlevel})($nul$intlevel|$intlevel|)$nul"
-"_apt_consume_short \${_ra_match%%($nul$intlevel|$intlevel|)$nul}" \|
/"$short_seq(${(j:|:)short_intlevel})="
-"_apt_consume_short \${_ra_match%=}"
\( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
/"$short_seq(${(j:|:)short_intlevel})($nul$intlevel|$intlevel|)$nul"/
-"_apt_consume_short \${match[1]%%($nul$intlevel|$intlevel|)$nul}" \|
/"$short_seq(${(j:|:)short_intlevel})="/
-"_apt_consume_short \${match[1]%=}"
\( /"$word1"/ :"$comp_intlevel" \| /"$nul"/ /"$word"/ :"$comp_intlevel" \) \|
)
regex_long_prefix=("$regex_long_prefix[@]"
/"(${(j:|:)short_intlevel})="
-"_apt_consume_short \${_ra_match[-2]}"
\( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
/"(${(j:|:)short_intlevel})$nul"
-"_apt_consume_short \${_ra_match[-2]}"
/"($intlevel$nul|)" !"$comp_intlevel" \|
/"(${(j:|:)short_intlevel})="/
-"_apt_consume_short \${match[1][-2]}"
\( /"$word1"/ :"$comp_intlevel" \| /"$nul"/ /"$word"/ :"$comp_intlevel" \) \|
/"(${(j:|:)short_intlevel})$nul"/
-"_apt_consume_short \${match[1][-2]}"
/"($intlevel$nul|)"/ :"$comp_intlevel" \|
)
fi
if (( $#short_configfile )); then
regex_short=("$regex_short[@]"
/"$short_seq(${(j:|:)short_configfile})(=|)"
-"_apt_consume_short \${_ra_match%=}"
\( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
/"$short_seq(${(j:|:)short_configfile})(=|)"/
-"_apt_consume_short \${match[1]%=}"
\( /"$word1"/ :"$comp_configfile" \| /"$nul"/ /"$word"/ :"$comp_configfile" \) \|
)
regex_long_prefix=("$regex_long_prefix[@]"
/"(${(j:|:)short_configfile})$nul"
-"_apt_consume_short \${_ra_match[-2]}"
/"$word" !"$comp_configfile" \|
/"(${(j:|:)short_configfile})="
-"_apt_consume_short \${_ra_match[-2]}"
\( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
/"(${(j:|:)short_configfile})$nul"/
-"_apt_consume_short \${match[1][-2]}"
/"$word"/ :"$comp_configfile" \|
/"(${(j:|:)short_configfile})="/
-"_apt_consume_short \${match[1][-2]}"
\( /"$word1"/ :"$comp_configfile" \| /"$nul"/ /"$word"/ :"$comp_configfile" \) \|
)
fi
if (( $#short_arbitem )); then
regex_short=("$regex_short[@]"
/"$short_seq(${(j:|:)short_arbitem})(=|)"
-"_apt_consume_short \${_ra_match%=}"
\( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
/"$short_seq(${(j:|:)short_arbitem})(=|)"/
-"_apt_consume_short \${match[1]%=}"
\( /"$word1"/ :"$comp_arbitem" \| /"$nul"/ /"$word"/ :"$comp_arbitem" \) \|
)
regex_long_prefix=("$regex_long_prefix[@]"
/"(${(j:|:)short_arbitem})$nul"
-"_apt_consume_short \${_ra_match[-2]}"
/"$word" !"$comp_arbitem" \|
/"(${(j:|:)short_arbitem})="
-"_apt_consume_short \${_ra_match[-2]}"
\( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
/"(${(j:|:)short_arbitem})$nul"/
-"_apt_consume_short \${match[1][-2]}"
/"$word"/ :"$comp_arbitem" \|
/"(${(j:|:)short_arbitem})="/
-"_apt_consume_short \${match[1][-2]}"
\( /"$word1"/ :"$comp_arbitem" \| /"$nul"/ /"$word"/ :"$comp_arbitem" \) \|
)
fi
if (( $#long_hasarg )); then
regex_long=("$regex_long[@]"
/"(${(j:|:)long_hasarg})$nul"
-"_apt_consume_long \${_ra_match%$nul}; current_option=\${canonicalize[--\${_ra_match%$nul}]}"
/"$word" !"$comp_hasarg" \|
/"(${(j:|:)long_hasarg})="
-"_apt_consume_long \${_ra_match%=}; current_option=\${canonicalize[--\${_ra_match%=}]}"
\( /"$word1" !"$comp_hasarg" \| /"$nul" /"$word" !"$comp_hasarg" \) \|
/"(${(j:|:)long_hasarg})$nul"/
-"_apt_consume_long \${match[1]%$nul}; current_option=\${canonicalize[--\${match[1]%$nul}]}"
/"$word"/ :"$comp_hasarg" \|
/"(${(j:|:)long_hasarg})="/
-"_apt_consume_long \${match[1]%=}; current_option=\${canonicalize[--\${match[1]%=}]}"
\( /"$word1"/ :"$comp_hasarg" \| /"$nul"/ /"$word"/ :"$comp_hasarg" \) \|
)
regex_long_prefix=("$regex_long_prefix[@]"
/"(${(j:|:)long_hasarg})$nul"
-"_apt_consume_long \${_ra_match%$nul}; current_option=\${canonicalize[--\${_ra_match%$nul}]}"
/"$word" !"$comp_hasarg" \|
/"(${(j:|:)long_hasarg})="
-"_apt_consume_long \${_ra_match%=}; current_option=\${canonicalize[--\${_ra_match%=}]}"
\( /"$word1" !"$comp_hasarg" \| /"$nul" /"$word" !"$comp_hasarg" \) \|
/"(${(j:|:)long_hasarg})$nul"/
-"_apt_consume_long \${match[1]%$nul}; current_option=\${canonicalize[--\${match[1]%$nul}]}"
/"$word"/ :"$comp_hasarg" \|
/"(${(j:|:)long_hasarg})="/
-"_apt_consume_long \${match[1]%=}; current_option=\${canonicalize[--\${match[1]%=}]}"
\( /"$word1"/ :"$comp_hasarg" \| /"$nul"/ /"$word"/ :"$comp_hasarg" \) \|
)
fi
if (( $#long_bool )); then
regex_long=("$regex_long[@]"
/"(${(j:|:)long_bool})="
-"_apt_consume_long \${_ra_match%=}"
\( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
/"(${(j:|:)long_bool})$nul"
-"_apt_consume_long \${_ra_match%$nul}"
/"((${(j:|:)bool})$nul|)" !"$comp_bool" \|
/"(${(j:|:)long_bool})="/
-"_apt_consume_long xxx \${match[1]%=}"
\( /"$word1"/ :"$comp_bool" \| /"$nul"/ /"$word"/ :"$comp_bool" \) \|
/"(${(j:|:)long_bool})$nul"/
-"_apt_consume_long \${match[1]%$nul}"
/"((${(j:|:)bool})$nul|)"/ :"$comp_bool" \|
)
regex_long_prefix=("$regex_long_prefix[@]"
/"(${(j:|:)long_bool})="
-"_apt_consume_long \${_ra_match%=}"
\( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
/"(${(j:|:)long_bool})$nul"
-"_apt_consume_long \${_ra_match%$nul}"
/"((${(j:|:)bool})$nul|)" !"$comp_bool" \|
/"(${(j:|:)long_bool})="/
-"_apt_consume_long \${match[1]%=}"
\( /"$word1"/ :"$comp_bool" \| /"$nul"/ /"$word"/ :"$comp_bool" \) \|
/"(${(j:|:)long_bool})$nul"/
-"_apt_consume_long \${match[1]%$nul}"
/"((${(j:|:)bool})$nul|)"/ :"$comp_bool" \|
)
fi
if (( $#long_intlevel )); then
regex_long=("$regex_long[@]"
/"(${(j:|:)long_intlevel})="
-"_apt_consume_long \${_ra_match%=}"
\( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
/"(${(j:|:)long_intlevel})$nul"
-"_apt_consume_long \${_ra_match%$nul}"
/"($intlevel$nul|)" !"$comp_intlevel" \|
/"(${(j:|:)long_intlevel})="/
-"_apt_consume_long \${match[1]%=}"
\( /"$word1"/ :"$comp_intlevel" \| /"$nul"/ /"$word"/ :"$comp_intlevel" \) \|
/"(${(j:|:)long_intlevel})$nul"/
-"_apt_consume_long \${match[1]%$nul}"
/"($intlevel$nul|)"/ :"$comp_intlevel" \|
)
regex_long_prefix=("$regex_long_prefix[@]"
/"(${(j:|:)long_intlevel})$nul"
-"_apt_consume_long \${_ra_match%$nul}"
/"$intlevel" !"$comp_intlevel" /"$nul" \|
/"(${(j:|:)long_intlevel})="
-"_apt_consume_long \${_ra_match%=}"
\( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
/"(${(j:|:)long_intlevel})$nul"
-"_apt_consume_long \${_ra_match%$nul}"
/"($intlevel$nul|)" !"$comp_intlevel" \|
/"(${(j:|:)long_intlevel})="/
-"_apt_consume_long \${match[1]%=}"
\( /"$word1"/ :"$comp_intlevel" \| /"$nul"/ /"$word"/ :"$comp_intlevel" \) \|
/"(${(j:|:)long_intlevel})$nul"/
-"_apt_consume_long \${match[1]%$nul}"
/"($intlevel$nul|)"/ :"$comp_intlevel" \|
)
fi
if (( $#long_configfile )); then
regex_long=("$regex_long[@]"
/"(${(j:|:)long_configfile})$nul"
-"_apt_consume_long \${_ra_match%$nul}"
/"$word" !"$comp_configfile" \|
/"(${(j:|:)long_configfile})="
-"_apt_consume_long \${_ra_match%=}"
\( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
/"(${(j:|:)long_configfile})$nul"/
-"_apt_consume_long \${match[1]%$nul}"
/"$word"/ :"$comp_configfile" \|
/"(${(j:|:)long_configfile})="/
-"_apt_consume_long \${match[1]%=}"
\( /"$word1"/ :"$comp_configfile" \| /"$nul"/ /"$word"/ :"$comp_configfile" \) \|
)
regex_long_prefix=("$regex_long_prefix[@]"
/"(${(j:|:)long_configfile})$nul"
-"_apt_consume_long \${_ra_match%$nul}"
/"$word" !"$comp_configfile" \|
/"(${(j:|:)long_configfile})="
-"_apt_consume_long \${_ra_match%=}"
\( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
/"(${(j:|:)long_configfile})$nul"/
-"_apt_consume_long \${match[1]%$nul}"
/"$word"/ :"$comp_configfile" \|
/"(${(j:|:)long_configfile})="/
-"_apt_consume_long \${match[1]%=}"
\( /"$word1"/ :"$comp_configfile" \| /"$nul"/ /"$word"/ :"$comp_configfile" \) \|
)
fi
if (( $#long_arbitem )); then
regex_long=("$regex_long[@]"
/"(${(j:|:)long_arbitem})$nul"
-"_apt_consume_long \${_ra_match%$nul}"
/"$word" !"$comp_arbitem" \|
/"(${(j:|:)long_arbitem})="
-"_apt_consume_long \${_ra_match%=}"
\( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
/"(${(j:|:)long_arbitem})$nul"/
-"_apt_consume_long \${match[1]%$nul}"
/"$word"/ :"$comp_arbitem" \|
/"(${(j:|:)long_arbitem})="/
-"_apt_consume_long \${match[1]%=}"
\( /"$word1"/ :"$comp_arbitem" \| /"$nul"/ /"$word"/ :"$comp_arbitem" \) \|
)
regex_long_prefix=("$regex_long_prefix[@]"
/"(${(j:|:)long_arbitem})$nul"
-"_apt_consume_long \${_ra_match%$nul}"
/"$word" !"$comp_arbitem" \|
/"(${(j:|:)long_arbitem})="
-"_apt_consume_long \${_ra_match%=}"
\( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
/"(${(j:|:)long_arbitem})$nul"/
-"_apt_consume_long \${match[1]%$nul}"
/"$word"/ :"$comp_arbitem"/ \|
/"(${(j:|:)long_arbitem})="/
-"_apt_consume_long \${match[1]%=}"
\( /"$word1"/ :"$comp_arbitem" \| /"$nul"/ /"$word"/ :"$comp_arbitem" \) \|
)
fi
regex_all=(
/"$word"
\( %-- \( "$regex_long[@]"
%"(${(j:|:)bool})-"
\( "$regex_long_prefix[@]" /"[]" !"$comp_long_prefix" \) \|
/"[]" !"$comp_long" \) \|
%- \( "$regex_short[@]" /"[]" !"$comp_short; $comp_long" \) \|
/"[]" !"$comp_opt" \) \#
/"$word"/
\( /--/+ \( "$regex_long[@]"
/"(${(j:|:)bool})-"/+
\( "$regex_long_prefix[@]"
/"[]"/ :"$comp_long_prefix" \) \) \|
/-/+ \( "$regex_short[@]" /"[]"/ \) \|
/"[]"/ :"$comp_opt" \) \#
"$regex_all[@]"
)
_regex_arguments "${funcname}_sm" "$regex_all[@]"
eval "$funcname () {
typeset -A canonicalize options
typeset -A canonicalize num_options
canonicalize=(${(kv)canonicalize})
options=(${(kv)options})
num_options=(${(kv)num_options})
local short_hasarg short_bool short_intlevel short_configfile short_arbitem
local long_hasarg long_bool long_intlevel long_configfile long_arbitem
@ -341,14 +338,16 @@ _apt_consume_short () {
local short opt
for short in ${(s::)1}; do
opt="$canonicalize[-$short]"
(( 0 < options[$opt] && options[$opt]-- ))
(( 0 < num_options[$opt] && num_options[$opt]-- ))
done
return 0
}
_apt_consume_long () {
local long opt
opt="$canonicalize[--$1]"
(( 0 < options[$opt] && options[$opt]-- ))
(( 0 < num_options[$opt] && num_options[$opt]-- ))
return 0
}
_apt-get () {
@ -373,18 +372,18 @@ _apt-get () {
-c,--config-file:configfile \
-o,--option:arbitem \
-- \
/$'update\0' \| \
/$'upgrade\0' \| \
/$'install\0' /$'[^\0]#\0' !'_deb_packages uninstalled "$expl_packages[@]" || _deb_packages installed "$expl_packages[@]" ' \# \| \
/$'remove\0' /$'[^\0]#\0' !'_deb_packages installed "$expl_packages[@]"' \# \| \
/$'dist-upgrade\0' \| \
/$'dselect-upgrade\0' \| \
/$'clean\0' \| \
/$'autoclean\0' \| \
/$'check\0' \| \
/$'source\0' /$'[^\0]#\0' !'_deb_packages avail "$expl_packages[@]"' \# \| \
/$'help\0' \| \
/"[]" !'compadd "$expl_action[@]" update upgrade install remove dist-upgrade dselect-upgrade clean autoclean check source help'
/$'update\0'/ \| \
/$'upgrade\0'/ \| \
/$'install\0'/ /$'[^\0]#\0'/ :'_deb_packages uninstalled "$expl_packages[@]" || _deb_packages installed "$expl_packages[@]" ' \# \| \
/$'remove\0'/ /$'[^\0]#\0'/ :'_deb_packages installed "$expl_packages[@]"' \# \| \
/$'dist-upgrade\0'/ \| \
/$'dselect-upgrade\0'/ \| \
/$'clean\0'/ \| \
/$'autoclean\0'/ \| \
/$'check\0'/ \| \
/$'source\0'/ /$'[^\0]#\0'/ :'_deb_packages avail "$expl_packages[@]"' \# \| \
/$'help\0/' \| \
/"[]"/ :'compadd "$expl_action[@]" update upgrade install remove dist-upgrade dselect-upgrade clean autoclean check source help'
_apt-get () {
local expl_action expl_packages
@ -410,19 +409,19 @@ _apt-cache () {
-c,--config-file:configfile \
-o,--option:arbitem \
-- \
/$'help\0' \| \
/$'add\0' /$'[^\0]#\0' !'_files' \# \| \
/$'gencaches\0' \| \
/$'showpkg\0' /$'[^\0]#\0' !'_deb_packages avail "$expl_packages[@]"' \# \| \
/$'stats\0' \| \
/$'dump\0' \| \
/$'dumpavail\0' \| \
/$'unmet\0' \| \
/$'check\0' \| \
/$'search\0' \| \
/$'show\0' \| \
/$'depends\0' \| \
/"[]" !'compadd "$expl_action[@]" help add gencaches showpkg stats dump dumpavail unmet check search show depends'
/$'help\0'/ \| \
/$'add\0'/ /$'[^\0]#\0'/ :'_files' \# \| \
/$'gencaches\0'/ \| \
/$'showpkg\0'/ /$'[^\0]#\0'/ :'_deb_packages avail "$expl_packages[@]"' \# \| \
/$'stats\0'=$status[4]/ \| \
/$'dump\0'/ \| \
/$'dumpavail\0'/ \| \
/$'unmet\0'/ \| \
/$'check\0'/ \| \
/$'search\0'/ \| \
/$'show\0'/ \| \
/$'depends\0'/ \| \
/"[]"/ :'compadd "$expl_action[@]" help add gencaches showpkg stats dump dumpavail unmet check search show depends'
_apt-cache () {
local expl_action expl_packages expl_pkg_cache expl_src_cache
@ -450,8 +449,8 @@ _apt-cdrom () {
-c,--config-file:configfile \
-o,--option:arbitem \
-- \
/$'add\0' \| \
/"[]" !'compadd "$expl_action[@]" add'
/$'add\0'/ \| \
/"[]"/ :'compadd "$expl_action[@]" add'
_apt-cdrom () {
local expl_action expl_mount_point
@ -471,13 +470,13 @@ _apt-config () {
-c,--config-file:configfile \
-o,--option:arbitem \
-- \
/$'shell\0' \
/$'shell\0'/ \
\( \
/$'[^\0]#\0' !'compgen "$expl_shell_var[@]" -v' \
/$'[^\0]#\0' !'compadd "$expl_config_key[@]" - ${${(f)"$(apt-config dump 2>&1)"}% *}' \
/$'[^\0]#\0'/ :'compgen "$expl_shell_var[@]" -v' \
/$'[^\0]#\0'/ :'compadd "$expl_config_key[@]" - ${${(f)"$(apt-config dump 2>&1)"}% *}' \
\) \# \| \
/$'dump\0' \| \
/"[]" !'compadd "$expl_action[@]" shell dump'
/$'dump\0'/ \| \
/"[]"/ :'compadd "$expl_action[@]" shell dump'
_apt-config () {
local expl_action expl_shell_var expl_config_key

View file

@ -1,9 +1,9 @@
#autoload
# Usage:
# _combination [-s SEP] VARIABLE KEYi=PATi KEYj=PATj ... KEYm=PATm KEY EXPL...
# _combination [-s S] V[:K1:...] Ki1[:Ni1]=Pi1 Ki2[:Ni2]=Pi2 ... Kim[:Nim]=Pim Kj[:Nj] EXPL...
#
# VARIABLE must be formd as PREFIX_KEY1_..._KEYn.
# It is assumed that V is formed as PRE_K1_..._Kn if `:K1:...' is not specified.
#
# Example: telnet
#
@ -48,7 +48,7 @@
# the port argument if they are exist. And if it is failed, `_users' is
# called.
local sep var keys pats key tmp
local sep var keys pats key num tmp
if [[ "$1" = -s ]]; then
sep="$2"
@ -60,21 +60,31 @@ fi
var=$1
shift
keys=( "${(@s:_:)${var#*_}}" )
if [[ $var = *:* ]]; then
keys=( ${(s/:/)var} )
shift keys
var="${var%%:*}"
else
keys=( "${(@s:_:)${var#*_}}" )
fi
pats=( "${(@)keys/*/*}" )
while [[ "$1" = *=* ]]; do
pats[$keys[(i)${1%%\=*}]]="${1#*\=}"
tmp="${1%%\=*}"
key="${tmp%:*}"
num="${${tmp##*:}:-1}"
pats[$keys[(in:num:)$key]]="${1#*\=}"
shift
done
key="$1"
key="${1%:*}"
num="${${1##*:}:-1}"
shift
if (( ${(P)+${var}} )); then
eval "tmp=( \"\${(@M)${var}:#\${(j!$sep!)~pats}}\" )"
if (( keys[(i)$key] != 1 )); then
eval "tmp=( \${tmp#\${(j!${sep}!)~\${(@)\${(@)keys[2,(r)\$key]}/*/*}}$sep} )"
eval "tmp=( \"\${(@M)${var}:#\${(j($sep))~pats}}\" )"
if (( keys[(in:num:)$key] != 1 )); then
eval "tmp=( \${tmp#\${(j(${sep}))~\${(@)\${(@)keys[2,(rn:num:)\$key]}/*/*}}$sep} )"
fi
tmp=( ${tmp%%$sep*} )

View file

@ -1011,6 +1011,93 @@ arguments) should be printed, the configuration key
tt(describe_values) is used in the same way as the key
tt(describe_options) is used by the tt(_arguments) function.
)
item(tt(_regex_arguments))(
This function is a compiler to generate a completion function. The
first argument specifies the name of generated function and rest arguments
specifies a completion specification in the notation like regular
expression with acions. The generated function is formed as a state
machine whose state corresponds each part of the specification of the
completion. The state machine runs on a command line and evaluate actions
when the command line is exhausted. The command line is represented by
single string that is generated by concatinating unquoted tt(words)
(before tt(CURRENT)) and tt(PREFIX) using the null character as a
separator.
The specification is one of following forms. (Metacharacters such as
`tt(LPAR())', `tt(RPAR())', `tt(#)' and `tt(|)' should be quoted.)
startitem()
item(tt(/)var(pattern)tt(/) [tt(%)var(lookahead)tt(%)] [tt(-)var(guard)] [tt(:)var(action)])(
This is a primitive element for the specification and corresponds to the
state of the compiled state machine. When the state machine is trying to
enter to this state, the state machine tries to match the pattern
`tt((#b)LPAR()(#B))var(pattern)tt(RPAR()(#B))var(lookahead)tt(*)' against to
the command line string. If it is matched, `var(guard)' is evaluated and
its return status is examined. If it is success, the state machine is
entered to this state. Otherwise when the pattern match or the guard
evaluation is failed, the state machine is failed to enter to this state
and other candidates are tried. If `var(pattern)' is the string `tt([])',
it is treated as the pattern which never match.
When the state machine is entered to this state, the left part of the
command line string matched against to `var(pattern)' is removed and next
states of this state are tried to enter with inner-to-outer, left-to-right
fashion.
If all tries are failed and remaining command line string contains no null
character, completion target is restricted to correspondence of remaining
command line string and `var(action)'s for the target is evaluated. Since
this state may not remove non-empty string from command line string,
prior states and its neighborhoods may have `var(actions)'s for the
target.
)
item(tt(/)var(pattern)tt(/+) [tt(%)var(lookahead)tt(%)] [tt(-)var(guard)] [tt(:)var(action)])(
This is similar to `tt(/)var(pattern)tt(/) ...' but the left part of
command line string is also considered as part of the completion target.
)
item(tt(/)var(pattern)tt(/-) [tt(%)var(lookahead)tt(%)] [tt(-)var(guard)] [tt(:)var(action)])(
This is similar to `tt(/)var(pattern)tt(/) ...' but `var(action)'s of this
and prior states are ignored even if following state's `var(pattern)'
matches empty string.
)
item(tt(LPAR()) var(spec) tt(RPAR()))(
This groups `var(spec)'.
)
item(var(spec) tt(#))(
This is repetation of `var(spec)'.
)
item(var(spec) var(spec))(
This is concatination of two `var(spec)'s.
)
item(var(spec) tt(|) var(spec))(
This is alternation of two `var(spec)'s.
)
enditem()
)
item(tt(_combination))(
This function uses a array to represent combinations of completing texts.
The first argument is a name of the array optionally appended completing
field names separated by colon. If it contains no colon, it is assumed
that the name is formed as `var(prefix)_var(fieldname)_..._var(fieldname)'
which `var(prefix)' and `var(fieldname)'s does not contain a underscore.
A each element of the array should be colon-separated completing texts
which correspond to the field names. The option `tt(-s) var(sepchar)'
can be given before the array name to change the delimiter in the array
element from colon.
Since second argument, zero or more arguments formed as
`var(fieldname)tt(=)var(pattern)' can be given. It restricts completion
candidates from the array by maching a text that corresponds to
`var(fieldname)' against to `var(pattern)'. If `tt(:)var(num)' is
specified between `var(fieldname)' and `tt(=)', `var(num)'th field in
named as `var(fieldname)' is used instead of the first.
After above arguments, completing field name should be given. It may have
suffix `tt(:)var(num)' to use a arbitrary field instead of the first as
above.
If there are no array element to match all of specified pattern and the
function `tt(_)var(fieldname)' exists, the function is called.
)
enditem()
texinode(Completion Directories)(Bindable Commands)(Completion Functions)(Completion System)
@ -1527,4 +1614,12 @@ is set to a non-empty value, this function will not try to use the
tt(stat) module to generate only names of modified files in the
appropriate places.
)
item(tt(regex_arguments_path))(
This specifies cache directory for the tt(_regex_arguments). If it is
empty, tt($HOME/.zsh/regex_arguments) is assumed.
If tt(regex_arguments_path) is an existing writable directory,
tt(_regex_arguments) sotores a compiled function definition into the
directory.
)
enditem()