26763: fix problem on failed cd -s to relative path
[zsh.git] / Completion / Unix / Type / _files
blob4615a60e7c4ec9cd1aacca6e68a0e556bb6da0bb
1 #compdef -redirect-,-default-,-default-
3 local opts tmp glob pat pats expl tag i def descr end ign ret=1 match tried
4 local type sdef
6 zparseopts -a opts \
7     '/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
9 type="${(@j::M)${(@)tmp#-}#?}"
10 if (( $tmp[(I)-g*] )); then
11   glob="${${${${(@M)tmp:#-g*}#-g}##[[:blank:]]#}%%[[:blank:]]#}"
12   [[ "$glob" = *[^\\][[:blank:]]* ]] &&
13       glob="{${glob//(#b)([^\\])[[:blank:]]##/${match[1]},}}"
15   # add `#q' to the beginning of any glob qualifier if not there already
16   [[ "$glob" = (#b)(*\()([^\|\~]##\)) && $match[2] != \#q* ]] &&
17       glob="${match[1]}#q${match[2]}"
19 tmp=$opts[(I)-F]
20 if (( tmp )); then
21   ign=( $=opts[tmp+1] )
22   if [[ $ign = _comp_ignore ]]; then
23     ign=( $_comp_ignore )
24   else
25     opts[tmp+1]=_comp_ignore
26   fi
27 else
28   ign=
31 if zstyle -a ":completion:${curcontext}:" file-patterns tmp; then
32   [[ "$type" = */* ]] && glob="$glob,*(-/)"
33   pats=()
35   for i in ${tmp//\%p/${${glob:-\*}//:/\\:}}; do
36     if [[ $i = *[^\\]:* ]]; then
37       pats=( "$pats[@]" " $i " )
38     else
39       pats=( "$pats[@]" " ${i}:files " )
40     fi
41   done
42 elif zstyle -t ":completion:${curcontext}:" list-dirs-first; then
43   if [[ "$type" = *g* ]]; then
45     # add `^-/' after `#q' glob qualifier if not there already
46     if [[ "$glob" = (#b)(*\(\#q)(*\)) ]]; then
47       [[ $match[2] != \^-/* ]] &&
48       glob="${match[1]}^-/,${match[2]}"
49     else
50       glob="$glob(#q^-/)"
51     fi
53     pats=( " *(-/):directories:directories ${glob//:/\\:}:globbed-files" )
54   elif [[ "$type" = */* ]] then
55     pats=( '*(-/):directories ' '*:all-files ' )
56   else
57     pats=( '*(-/):directories:directories *(^-/):other-files ' )
58   fi
59 else
60   if [[ "$type" = *g* ]]; then
62   # People prefer to have directories shown on first try as default.
63   # Even if the calling function didn't use -/.
64   #
65   # if [[ "$type" = */* ]]; then
67     pats=( " ${glob//:/\\:}:globbed-files *(-/):directories" '*:all-files '
69     ### We could allow _next_tags to offer only globbed-files or directories
70     ### by adding:
71     ###   " ${glob//:/\\:}:only-globbed-files " ' *(-/):only-directories '
73       )
75   # else
76   #   pats=( " ${glob//:/\\:}:globbed-files "
77   #          '*(-/):directories ' '*:all-files ' )
78   # fi
80   elif [[ "$type" = */* ]]; then
81     pats=( '*(-/):directories ' '*:all-files ' )
82   else
83     pats=( '*:all-files ' )
84   fi
87 tried=()
88 for def in "$pats[@]"; do
89   eval "def=( ${${def:gs/\\:/\\\\\\\\\\\\:}//(#b)([][()|*?^#~<>])/\\${match[1]}} )"
91   tmp="${(@M)def#*[^\\]:}"
92   (( $tried[(I)${(q)tmp}] )) && continue
93   tried=( "$tried[@]" "$tmp" )
95   for sdef in "$def[@]"; do
97     tag="${${sdef#*[^\\]:}%%:*}"
98     pat="${${sdef%%:${tag}*}//\\:/:}"
100     if [[ "$sdef" = *:${tag}:* ]]; then
101       descr="${(Q)sdef#*:${tag}:}"
102     else
103       if (( $opts[(I)-X] )); then
104         descr=
105       else
106         descr=file
107       fi
108       end=yes
109     fi
111     _tags "$tag"
112     while _tags; do
113       _comp_ignore=()
114       while _next_label "$tag" expl "$descr"; do
115         _comp_ignore=( $_comp_ignore $ign )
116         if [[ -n "$end" ]]; then
117           _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
118         else
119           _path_files "$expl[@]" -g "$pat" "$opts[@]" && ret=0
120         fi
121       done
122       (( ret )) || break
123     done
125     ### For that _next_tags change mentioned above we would have to
126     ### comment out the following line. (Or not, depending on the order
127     ### of the patterns.)
129     [[ "$pat" = '*' ]] && return ret
131   done
132   (( ret )) || return 0
133 done
135 return 1