#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