#compdef -redirect-,-default-,-default-
local -a match mbegin mend
local ret=1
# Look for glob qualifiers. This is duplicated from _path_files because
# we don't want to complete them multiple times (for each file pattern).
if _have_glob_qual $PREFIX; then
compset -p ${#match[1]}
compset -S '[^\)\|\~]#(|\))'
if [[ $_comp_caller_options[extendedglob] == on ]] && compset -P '\#'; then
_globflags && ret=0
else
if [[ $_comp_caller_options[extendedglob] == on ]]; then
_describe -t globflags "glob flag" '(\#:introduce\ glob\ flag)' -Q -S '' && ret=0
fi
_globquals && ret=0
fi
return ret
fi
local opts tmp glob pat pats expl tag i def descr end ign tried
local type sdef ignvars ignvar prepath oprefix rfiles rfile
zparseopts -a opts \
'/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
type="${(@j::M)${(@)tmp#-}#?}"
if (( $tmp[(I)-g*] )); then
glob="${${${(@)${(@M)tmp:#-g*}#-g}##[[:blank:]]#}%%[[:blank:]]#}"
[[ "$glob" = *[^\\][[:blank:]]* ]] &&
glob="{${glob//(#b)([^\\])[[:blank:]]##/${match[1]},}}"
# add `#q' to the beginning of any glob qualifier if not there already
[[ "$glob" = (#b)(*\()([^\|\~]##\)) && $match[2] != \#q* ]] &&
glob="${match[1]}#q${match[2]}"
elif [[ $type = */* ]]; then
glob="*(#q-/)"
fi
tmp=$opts[(I)-F]
if (( tmp )); then
ignvars=($=opts[tmp+1])
if [[ $ignvars = _comp_ignore ]]; then
ign=( $_comp_ignore )
else
ign=()
for ignvar in $ignvars; do
ign+=(${(P)ignvar})
done
opts[tmp+1]=_comp_ignore
fi
else
ign=()
fi
if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then
pats=()
for i in ${tmp//\%p/${${glob:-\*}//:/\\:}}; do
if [[ $i = *[^\\]:* ]]; then
pats+=( " $i " )
else
pats+=( " ${i}:files " )
fi
done
elif zstyle -t ":completion:${curcontext}:" list-dirs-first; then
pats=( " *(-/):directories:directory ${${glob:-*}//:/\\:}(#q^-/):globbed-files" '*:all-files' )
else
# People prefer to have directories shown on first try as default.
# Even if the calling function didn't use -/.
pats=( "${${glob:-*}//:/\\:}:globbed-files *(-/):directories" '*:all-files ' )
fi
tried=()
for def in "$pats[@]"; do
eval "def=( ${${def//\\:/\\\\\\:}//(#b)([][()|*?^#~<>])/\\${match[1]}} )"
tmp="${(@M)def#*[^\\]:}"
(( $tried[(I)${(q)tmp}] )) && continue
tried=( "$tried[@]" "$tmp" )
for sdef in "$def[@]"; do
tag="${${sdef#*[^\\]:}%%:*}"
pat="${${sdef%%:${tag}*}//\\:/:}"
if [[ "$sdef" = *:${tag}:* ]]; then
descr="${(Q)sdef#*:${tag}:}"
else
if (( $opts[(I)-X] )); then
descr=
else
descr=file
fi
end=yes
fi
_tags "$tag"
while _tags; do
_comp_ignore=()
while _next_label "$tag" expl "$descr"; do
_comp_ignore=( $_comp_ignore $ign )
if [[ -n "$end" ]]; then
if _path_files -g "$pat" "$opts[@]" "$expl[@]"; then
ret=0
elif [[ $PREFIX$SUFFIX != */* ]] && zstyle -a ":completion:${curcontext}:$tag" recursive-files rfiles; then
local subtree
for rfile in $rfiles; do
if [[ $PWD/ = ${~rfile} ]]; then
if [[ -z $subtree ]]; then
subtree=( **/*(/) )
fi
for prepath in $subtree; do
oprefix=$PREFIX
PREFIX=$prepath/$PREFIX
_path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
PREFIX=$oprefix
done
break
fi
done
fi
else
_path_files "$expl[@]" -g "$pat" "$opts[@]" && ret=0
fi
done
(( ret )) || break
done
### For that _next_tags change mentioned above we would have to
### comment out the following line. (Or not, depending on the order
### of the patterns.)
[[ "$pat" = '*' ]] && return ret
done
(( ret )) || return 0
done
return 1