mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-10-31 06:00:54 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			564 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			564 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| #autoload
 | |
| 
 | |
| # Utility function for in-path completion. This allows `/u/l/b<TAB>'
 | |
| # to complete to `/usr/local/bin'.
 | |
| 
 | |
| local linepath realpath donepath prepath testpath exppath skips
 | |
| local tmp1 tmp2 tmp3 tmp4 i orig eorig pre suf tpre tsuf opre osuf cpre
 | |
| local pats haspats=no ignore group expl addpfx addsfx remsfx rem remt
 | |
| local nm=$compstate[nmatches] menu mspec matcher mopts atmp sort match
 | |
| 
 | |
| typeset -U prepaths exppaths
 | |
| 
 | |
| setopt localoptions nullglob rcexpandparam
 | |
| unsetopt markdirs globsubst shwordsplit nounset
 | |
| 
 | |
| local sopt='-' gopt='' opt
 | |
| exppaths=()
 | |
| prepaths=('')
 | |
| ignore=()
 | |
| group=()
 | |
| pats=()
 | |
| addpfx=()
 | |
| addsfx=()
 | |
| remsfx=()
 | |
| expl=()
 | |
| matcher=()
 | |
| mopts=()
 | |
| 
 | |
| # Get the options.
 | |
| 
 | |
| while getopts "P:S:qr:R:W:F:J:V:X:f/g:M:12n" opt; do
 | |
|   case "$opt" in
 | |
|   [12n]) mopts=( "$mopts[@]" "-$opt" )
 | |
|          ;;
 | |
|   P)     addpfx=(-P "$OPTARG")
 | |
|          ;;
 | |
|   S)     addsfx=(-S "$OPTARG")
 | |
|          ;;
 | |
|   q)     tmp1=yes
 | |
|          ;;
 | |
|   [rR])  remsfx=("-$opt" "$OPTARG")
 | |
|          ;;
 | |
|   W)     tmp1="$OPTARG"
 | |
|          if [[ "$tmp1[1]" = '(' ]]; then
 | |
|            prepaths=( ${^=tmp1[2,-2]%/}/ )
 | |
| 	 elif [[ "$tmp1[1]" = '/' ]]; then
 | |
|            prepaths=( "$tmp1/" )
 | |
|          else
 | |
| 	   # In this case the variable should be an array, so
 | |
| 	   # don't use an extra ${=...}.
 | |
|            prepaths=( ${(P)^tmp1%/}/ )
 | |
|            (( ! $#prepaths )) && prepaths=( ${tmp1%/}/ )
 | |
|          fi
 | |
|          (( ! $#prepaths )) && prepaths=( '' )
 | |
|          ;;
 | |
|   F)     tmp1="$OPTARG"
 | |
|          if [[ "$tmp1[1]" = '(' ]]; then
 | |
|            ignore=( ${=tmp1[2,-2]} )
 | |
|          else
 | |
|            ignore=( ${(P)tmp1} )
 | |
|          fi
 | |
|          ;;
 | |
|   [JV])  group=("-$opt" "$OPTARG")
 | |
|          ;;
 | |
|   X)     expl=(-X "$OPTARG")
 | |
|          ;;
 | |
|   f)     sopt="${sopt}f"
 | |
|          pats=("$pats[@]" '*')
 | |
| 	 ;;
 | |
|   /)     sopt="${sopt}/"
 | |
|          pats=("$pats[@]" '*(-/)')
 | |
| 	 haspats=yes
 | |
| 	 ;;
 | |
|   g)     gopt='-g'
 | |
|          pats=("$pats[@]" ${=OPTARG})
 | |
| 	 haspats=yes
 | |
| 	 ;;
 | |
|   M)     mspec="$OPTARG"
 | |
|          matcher=(-M "$OPTARG")
 | |
|          ;;
 | |
|   esac
 | |
| done
 | |
| 
 | |
| if [[ -z "$_file_pat_checked" ]] &&
 | |
|    zstyle -s ":completion${curcontext}:files" file-patterns tmp1 &&
 | |
|    [[ -n "$tmp1" ]]; then
 | |
|   if [[ "$tmp1" = '*(-/)' ]]; then
 | |
|     gopt=''
 | |
|     sopt=-/
 | |
|   else
 | |
|     gopt='-g'
 | |
|     sopt=-
 | |
|   fi
 | |
|   pats=( $=tmp1 )
 | |
|   haspats=yes
 | |
| fi
 | |
| 
 | |
| if (( ! ( $#group + $#expl ) )); then
 | |
|   if [[ -z "$gopt" && "$sopt" = -/ ]]; then
 | |
|     _description directories expl directory
 | |
|   else
 | |
|     _description files expl file
 | |
|   fi
 | |
|   tmp1=$expl[(I)-M]
 | |
|   if (( tmp1 )); then
 | |
|     mspec="$mspec $expl[1+tmp1]"
 | |
|     if (( $#matcher )); then
 | |
|       matcher[2]="$matcher[2] $expl[1+tmp1]"
 | |
|     else
 | |
|       matcher=(-M "$expl[1+tmp1]")
 | |
|     fi
 | |
|   fi
 | |
| fi
 | |
| 
 | |
| [[ -n "$tmp1" && $#addsfx -ne 0 ]] && addsfx[1]=-qS
 | |
| 
 | |
| # If we were given no file selection option, we behave as if we were given
 | |
| # a `-f'.
 | |
| 
 | |
| if [[ "$sopt" = - ]]; then
 | |
|   if [[ -z "$gopt" ]]; then
 | |
|     sopt='-f'
 | |
|     pats=('*')
 | |
|   else
 | |
|     unset sopt
 | |
|   fi
 | |
| fi
 | |
| 
 | |
| if zstyle -s ":completion${curcontext}:files" sort tmp1; then
 | |
|   case "$tmp1" in
 | |
|   *size*)             sort=oL;;
 | |
|   *links*)            sort=ol;;
 | |
|   *(time|date|modi)*) sort=om;;
 | |
|   *access*)           sort=oa;;
 | |
|   *(inode|change)*)   sort=oc;;
 | |
|   *)                  sort=on;;
 | |
|   esac
 | |
|   [[ "$tmp1" = *rev* ]] && sort[1]=O
 | |
| 
 | |
|   if [[ "$sort" = on ]]; then
 | |
|     sort=''
 | |
|   else
 | |
|     group=( "${(@)group/#-J/-V}" )
 | |
|     expl=( "${(@)expl/#-J/-V}" )
 | |
| 
 | |
|     tmp2=()
 | |
|     for tmp1 in "$pats[@]"; do
 | |
|       if [[ "$tmp1" = (#b)(?*)(\(\([^\|~]##\)\)) ]]; then
 | |
|         tmp2=( "$tmp2[@]" "${match[1]}((${sort}${match[2][3,-1]}" )
 | |
|       elif [[ "$tmp1" = (#b)(?*)(\([^\|~]##\)) ]]; then
 | |
|         tmp2=( "$tmp2[@]" "${match[1]}(${sort}${match[2][2,-1]}" )
 | |
|       else
 | |
|         tmp2=( "$tmp2[@]" "${tmp1}(${sort})" )
 | |
|       fi
 | |
|     done
 | |
|     pats=( "$tmp2[@]" )
 | |
|   fi
 | |
| fi
 | |
| 
 | |
| # Skip over sequences of slashes.
 | |
| 
 | |
| zstyle -t ":completion${curcontext}:paths" squeeze-slashes && skips=yes
 | |
| 
 | |
| # We get the prefix and the suffix from the line and save the whole
 | |
| # original string. Then we see if we will do menucompletion.
 | |
| 
 | |
| pre="$PREFIX"
 | |
| suf="$SUFFIX"
 | |
| opre="$PREFIX"
 | |
| osuf="$SUFFIX"
 | |
| orig="${PREFIX}${SUFFIX}"
 | |
| eorig="$orig"
 | |
| 
 | |
| [[ $compstate[insert] = (*menu|[0-9]*) || -n "$_comp_correct" ||
 | |
|    ( $#compstate[pattern_match] -ne 0 &&
 | |
|      "${orig#\~}" != "${${orig#\~}:q}" ) ]] && menu=yes
 | |
| 
 | |
| # If given no `-F' option, we may want to use $fignore, turned into patterns.
 | |
| 
 | |
| [[ $#ignore -eq 0 && -z $gopt && -n $FIGNORE ]] && 
 | |
|    ignore=( "?*${^fignore[@]}" )
 | |
| 
 | |
| if (( $#ignore )); then
 | |
|   _comp_ignore=( "$_comp_ignore[@]" "$ignore[@]" )
 | |
|   (( $expl[(I)-F] )) || expl=( "$expl[@]" -F _comp_ignore )
 | |
| fi
 | |
| 
 | |
| # Now let's have a closer look at the string to complete.
 | |
| 
 | |
| if [[ "$pre[1]" = \~ ]]; then
 | |
|   # It begins with `~', so remember anything before the first slash to be able
 | |
|   # to report it to the completion code. Also get an expanded version of it
 | |
|   # (in `realpath'), so that we can generate the matches. Then remove that
 | |
|   # prefix from the string to complete, set `donepath' to build the correct
 | |
|   # paths and make sure that the loop below is run only once with an empty
 | |
|   # prefix path by setting `prepaths'.
 | |
|   
 | |
|   linepath="${pre%%/*}/"
 | |
|   realpath=$~linepath
 | |
|   [[ "$realpath" = "$linepath" ]] && return 1
 | |
|   pre="${pre#*/}"
 | |
|   orig="${orig#*/}"
 | |
|   donepath=''
 | |
|   prepaths=( '' )
 | |
| elif [[ "$pre" = *\$*/* ]]; then
 | |
| 
 | |
|   # If there is a parameter expansion in the word from the line, we try
 | |
|   # to complete the beast by expanding the prefix and completing anything
 | |
|   # after the first slash after the parameter expansion.
 | |
|   # This fails for things like `f/$foo/b/<TAB>' where the first `f' is
 | |
|   # meant as a partial path.
 | |
| 
 | |
|   linepath="${(M)pre##*\$[^/]##/}"
 | |
|   realpath=${(e)~linepath}
 | |
|   [[ "$realpath" = "$linepath" ]] && return 1
 | |
|   pre="${pre#${linepath}}"
 | |
|   i="${#linepath//[^\\/]}"
 | |
|   orig="${orig[1,(in:i:)/][1,-2]}"
 | |
|   donepath=''
 | |
|   prepaths=( '' )
 | |
| else
 | |
|   # If the string does not start with a `~' we don't remove a prefix from the
 | |
|   # string.
 | |
| 
 | |
|   linepath=''
 | |
|   realpath=''
 | |
| 
 | |
|   if [[ "$pre[1]" = / ]]; then
 | |
|     # If it is a absolut path name, we remove the first slash and put it in
 | |
|     # `donepath' meaning that we treat it as the path that was already handled.
 | |
|     # Also, we don't use the paths from `-W'.
 | |
| 
 | |
|     pre="$pre[2,-1]"
 | |
|     orig="$orig[2,-1]"
 | |
|     donepath='/'
 | |
|     prepaths=( '' )
 | |
|   else
 | |
|     # The common case, we just use the string as it is, unless it begins with
 | |
|     # `./' or `../' in which case we don't use the paths from `-W'.
 | |
|     
 | |
|     [[ "$pre" = (.|..)/* ]] && prepaths=( '' )
 | |
|     donepath=''
 | |
|   fi
 | |
| fi
 | |
| 
 | |
| # Now we generate the matches. First we loop over all prefix paths given
 | |
| # with the `-W' option.
 | |
| 
 | |
| for prepath in "$prepaths[@]"; do
 | |
| 
 | |
|   # Get local copies of the prefix, suffix, and the prefix path to use
 | |
|   # in the following loop, which walks through the pathname components
 | |
|   # in the string from the line.
 | |
| 
 | |
|   tpre="$pre"
 | |
|   tsuf="$suf"
 | |
|   testpath="$donepath"
 | |
| 
 | |
|   tmp1=( "$prepath$realpath$donepath" )
 | |
| 
 | |
|   while true; do
 | |
| 
 | |
|     # Skip over `./' and `../'.
 | |
| 
 | |
|     if [[ "$tpre" = (.|..)/* ]]; then
 | |
|       tmp1=( ${^tmp1}${tpre%%/*}/ )
 | |
|       tpre="${tpre#*/}"
 | |
|       continue
 | |
|     fi
 | |
| 
 | |
|     # Skip over multiple slashes?
 | |
| 
 | |
|     if [[ -n "$skips" && "$tpre" = /* ]]; then
 | |
|       tmp1=( ${^tmp1}/ )
 | |
|       tpre="${tpre#/}"
 | |
|       continue
 | |
|     fi
 | |
| 
 | |
|     # Get the prefix and suffix for matching.
 | |
| 
 | |
|     if [[ "$tpre" = */* ]]; then
 | |
|       PREFIX="${tpre%%/*}"
 | |
|       SUFFIX=""
 | |
|     else
 | |
|       PREFIX="${tpre}"
 | |
|       SUFFIX="${tsuf%%/*}"
 | |
|     fi
 | |
| 
 | |
|     # Get the matching files by globbing.
 | |
| 
 | |
|     if [[ "$tpre$tsuf" = */* ]]; then
 | |
|       tmp2=( ${^tmp1}*(-/) )
 | |
|       [[ ! -o globdots && "$PREFIX" = .* ]] &&
 | |
|           tmp2=( "$tmp2[@]" ${^tmp1}.*(-/) )
 | |
|       if [[ -o globdots || "$PREFIX" = .* ]] &&
 | |
|          zstyle -s ":completion${curcontext}:paths" special-dirs atmp; then
 | |
| 	if [[ "$atmp" = (yes|true|1|on) ]]; then
 | |
| 	  tmp2=( "$tmp2[@]" . .. )
 | |
| 	elif [[ "$atmp" = .. ]]; then
 | |
| 	  tmp2=( "$tmp2[@]" .. )
 | |
|         fi
 | |
|       fi
 | |
|     else
 | |
|       tmp2=( ${^tmp1}${^~pats} )
 | |
|       [[ ! -o globdots && "$PREFIX" = .* ]] &&
 | |
|           tmp2=( "$tmp2[@]" ${^tmp1}.${^~pats} )
 | |
|       if (( $#tmp2 )) &&
 | |
|          zstyle -s ":completion${curcontext}:files" ignore-parents rem &&
 | |
| 	 [[ ( "$rem" != *dir* || "$pats" = '*(-/)' ) &&
 | |
| 	    ( "$rem" != *..* || "$tmp1" = *../* ) ]]; then
 | |
|         if [[ "$rem" = *parent* ]]; then
 | |
| 	  for i in "$tmp2[@]"; do
 | |
| 	    if [[ -d "$i" && "$i" = */* ]]; then
 | |
| 	      remt="${i%/*}"
 | |
| 	      while [[ "$remt" = */* ]]; do
 | |
| 		[[ "$remt" -ef "$i" ]] && break
 | |
| 		remt="${remt%/*}"
 | |
| 	      done
 | |
| 	      [[ "$remt" = */* || "$remt" -ef "$i" ]] &&
 | |
| 	          _comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
 | |
| 	    fi
 | |
| 	  done
 | |
|         fi
 | |
|         if [[ "$rem" = *pwd* ]]; then
 | |
|           for i in "$tmp2[@]"; do
 | |
| 	    [[ "$i" -ef "$PWD" ]] && _comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
 | |
| 	  done
 | |
|         fi
 | |
|        (( $#_comp_ignore )) && (( $expl[(I)-F] )) ||
 | |
|            expl=( "$expl[@]" -F _comp_ignore )
 | |
|       fi
 | |
|       if [[ "$sopt" = *[/f]* && ( -o globdots || "$PREFIX" = .* ) ]] &&
 | |
| 	  zstyle -s ":completion${curcontext}:paths" special-dirs atmp; then
 | |
| 	if [[ "$atmp" = (yes|true|1|on) ]]; then
 | |
| 	  tmp2=( "$tmp2[@]" . .. )
 | |
| 	elif [[ "$atmp" = .. ]]; then
 | |
| 	  tmp2=( "$tmp2[@]" .. )
 | |
|         fi
 | |
|       fi
 | |
|     fi
 | |
|     tmp1=( "$tmp2[@]" )
 | |
| 
 | |
|     if [[ -n "$PREFIX$SUFFIX" ]]; then
 | |
|       # See which of them match what's on the line.
 | |
| 
 | |
|       builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
 | |
| 
 | |
|       if [[ $#tmp1 -eq 0 && -n "$_comp_correct" ]]; then
 | |
|         tmp1=( "$tmp2[@]" )
 | |
| 	compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp2:t}"
 | |
|       fi
 | |
| 
 | |
|       # If no file matches, save the expanded path and continue with
 | |
|       # the outer loop.
 | |
| 
 | |
|       if [[ $#tmp1 -eq 0 ]]; then
 | |
|  	if [[ "$tmp2[1]" = */* ]]; then
 | |
| 	  tmp2=( "${(@)tmp2#${prepath}${realpath}}" )
 | |
| 	  if [[ "$tmp2[1]" = */* ]]; then
 | |
| 	    tmp2=( "${(@)tmp2:h}" )
 | |
| 	    compquote tmp2
 | |
| 	    if [[ "$tmp2" = */ ]]; then
 | |
| 	      exppaths=( "$exppaths[@]" ${^tmp2}${tpre}${tsuf} )
 | |
| 	    else
 | |
| 	      exppaths=( "$exppaths[@]" ${^tmp2}/${tpre}${tsuf} )
 | |
| 	    fi
 | |
|           else
 | |
| 	    exppaths=( "$exppaths[@]" ${tpre}${tsuf} )
 | |
| 	  fi
 | |
|         fi
 | |
|         continue 2
 | |
|       fi
 | |
|     elif (( ! $#tmp1 )); then
 | |
|       # A little extra hack: if we were completing `foo/<TAB>' and `foo'
 | |
|       # contains no files, this will normally produce no matches and other
 | |
|       # completers might think that's it's their time now. But if the next
 | |
|       # completer is _correct or something like that, this will result in
 | |
|       # an attempt to correct a valid directory name. So we just add the
 | |
|       # original string in such a case so that the command line doesn't 
 | |
|       # change but other completers still think there are matches.
 | |
|       # We do this only if we weren't given a `-g' or `-/' option because
 | |
|       # otherwise this would keep `_files' from completing all filenames
 | |
|       # if none of the patterns match.
 | |
| 
 | |
|       if [[ -z "$tpre$tsuf" && -n "$pre$suf" ]]; then
 | |
|         tmp1=( "$tmp2[@]" )
 | |
| 	addsfx=(-S '')
 | |
| 	remsfx=()
 | |
| 	break;
 | |
|       elif [[ "$haspats" = no && -z "$tpre$tsuf" &&
 | |
| 	"$pre" = */ && -z "$suf" ]]; then
 | |
| 	PREFIX="${opre}"
 | |
| 	SUFFIX="${osuf}"
 | |
|         compadd -nQS '' - "$linepath$donepath$orig"
 | |
|         tmp4=-
 | |
|       fi
 | |
|       continue 2
 | |
|     fi
 | |
| 
 | |
|     # Step over to the next component, if any.
 | |
| 
 | |
|     if [[ "$tpre" = */* ]]; then
 | |
|       tpre="${tpre#*/}"
 | |
|     elif [[ "$tsuf" = */* ]]; then
 | |
|       tpre="${tsuf#*/}"
 | |
|       tsuf=""
 | |
|     else
 | |
|       break
 | |
|     fi
 | |
| 
 | |
|     # There are more components, so add a slash to the files we are
 | |
|     # collecting.
 | |
| 
 | |
|     tmp1=( ${^tmp1}/ )
 | |
|   done
 | |
| 
 | |
|   # The next loop searches the first ambiguous component.
 | |
| 
 | |
|   tmp3="$pre$suf"
 | |
|   tpre="$pre"
 | |
|   tsuf="$suf"
 | |
|   tmp1=( "${(@)tmp1#${prepath}${realpath}${testpath}}" )
 | |
| 
 | |
|   while true; do
 | |
| 
 | |
|     # First we check if some of the files match the original string
 | |
|     # for this component. If there are some we remove all other
 | |
|     # names. This avoids having `foo' complete to `foo' and `foobar'.
 | |
| 
 | |
|     if [[ "$tmp3" = */* ]]; then
 | |
|       tmp4=( "${(@M)tmp1:#${tmp3%%/*}/*}" )
 | |
|       if (( $#tmp4 )); then
 | |
|         tmp1=( "$tmp4[@]" )
 | |
|       fi
 | |
|     fi
 | |
| 
 | |
|     # Next we see if this component is ambiguous.
 | |
| 
 | |
|     if [[ "$tmp3" = */* ]]; then
 | |
|       tmp4=( "${(@)tmp1:#${tmp1[1]%%/*}/*}" )
 | |
|     else
 | |
|       tmp4=( "${(@)tmp1:#${tmp1[1]}}" )
 | |
|     fi
 | |
| 
 | |
|     if (( $#tmp4 )); then
 | |
| 
 | |
|       # It is. For menucompletion we now add the possible completions
 | |
|       # for this component with the unambigous prefix we have built
 | |
|       # and the rest of the string from the line as the suffix.
 | |
|       # For normal completion we add the rests of the filenames
 | |
|       # collected as the suffixes to make the completion code expand
 | |
|       # it as far as possible.
 | |
| 
 | |
|       if [[ "$tpre" = */* ]]; then
 | |
|         PREFIX="${donepath}${linepath}${cpre}${tpre%%/*}"
 | |
| 	SUFFIX="/${tsuf#*/}"
 | |
|       else
 | |
|         PREFIX="${donepath}${linepath}${cpre}${tpre}"
 | |
| 	SUFFIX="${tsuf}"
 | |
|       fi
 | |
| 
 | |
|       tmp4="$testpath"
 | |
|       compquote tmp1 tmp4
 | |
| 
 | |
|       if [[ -n $menu ]] ||
 | |
|          ! zstyle -t ":completion${curcontext}:paths" expand suffix; then
 | |
|         zstyle -t ":completion${curcontext}:paths" cursor &&
 | |
|             compstate[to_end]=''
 | |
|         if [[ "$tmp3" = */* ]]; then
 | |
| 	  compadd -Qf "$mopts[@]" -p "$linepath$tmp4" -s "/${tmp3#*/}" \
 | |
| 	          -W "$prepath$realpath$testpath" \
 | |
| 		  "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
 | |
|                   -M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
 | |
| 		  - "${(@)tmp1%%/*}"
 | |
| 	else
 | |
| 	  compadd -Qf "$mopts[@]" -p "$linepath$tmp4" \
 | |
| 	          -W "$prepath$realpath$testpath" \
 | |
| 		   "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
 | |
|                    -M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
 | |
| 		   - "$tmp1[@]"
 | |
| 	fi
 | |
|       else
 | |
|         if [[ "$tmp3" = */* ]]; then
 | |
| 	  atmp=( -Qf "$mopts[@]" -p "$linepath$tmp4"
 | |
| 	         -W "$prepath$realpath$testpath"
 | |
| 	         "$addpfx[@]" "$addsfx[@]" "$remsfx[@]"
 | |
|                  -M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" )
 | |
|           for i in "$tmp1[@]"; do
 | |
| 	    compadd "$atmp[@]" -s "/${i#*/}" - "${i%%/*}"
 | |
| 	  done
 | |
|         else
 | |
| 	  compadd -Qf "$mopts[@]" -p "$linepath$tmp4" \
 | |
| 		  -W "$prepath$realpath$testpath" \
 | |
| 		  "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
 | |
|                   -M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
 | |
| 		  - "$tmp1[@]"
 | |
|         fi
 | |
|       fi
 | |
|       tmp4=-
 | |
|       break
 | |
|     fi
 | |
| 
 | |
|     # If we have checked all components, we stop now and add the 
 | |
|     # strings collected after the loop.
 | |
| 
 | |
|     if [[ "$tmp3" != */* ]]; then
 | |
|       tmp4=""
 | |
|       break
 | |
|     fi
 | |
| 
 | |
|     # Otherwise we add the unambiguous component to `testpath' and
 | |
|     # take it from the filenames.
 | |
| 
 | |
|     testpath="${testpath}${tmp1[1]%%/*}/"
 | |
|     tmp1=( "${(@)tmp1#*/}" )
 | |
| 
 | |
|     tmp3="${tmp3#*/}"
 | |
| 
 | |
|     if [[ "$tpre" = */* ]]; then
 | |
|       cpre="${cpre}${tpre%%/*}/"
 | |
|       tpre="${tpre#*/}"
 | |
|     elif [[ "$tsuf" = */* ]]; then
 | |
|       cpre="${cpre}${tpre}/"
 | |
|       tpre="${tsuf#*/}"
 | |
|       tsuf=""
 | |
|     else
 | |
|       tpre=""
 | |
|       tsuf=""
 | |
|     fi
 | |
|   done
 | |
| 
 | |
|   if [[ -z "$tmp4" ]]; then
 | |
|     if [[ "$osuf" = */* ]]; then
 | |
|       PREFIX="${opre}${osuf}"
 | |
|       SUFFIX=""
 | |
|     else
 | |
|       PREFIX="${opre}"
 | |
|       SUFFIX="${osuf}"
 | |
|     fi
 | |
|     tmp4="$testpath"
 | |
|     compquote tmp4 tmp1
 | |
|     compadd -Qf "$mopts[@]" -p "$linepath$tmp4" \
 | |
| 	    -W "$prepath$realpath$testpath" \
 | |
| 	    "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
 | |
|             -M "r:|/=* r:|=* $mspec" "$group[@]" "$expl[@]" \
 | |
| 	    - "$tmp1[@]"
 | |
|   fi
 | |
| done
 | |
| 
 | |
| # If we are configured to expand paths as far as possible and we collected
 | |
| # expanded paths that are different from the string on the line, we add
 | |
| # them as possible matches.
 | |
| 
 | |
| exppaths=( "${(@)exppaths:#$eorig}" )
 | |
| 
 | |
| if zstyle -t ":completion${curcontext}:paths" expand prefix &&
 | |
|    [[ $#exppaths -gt 0 && nm -eq compstate[nmatches] ]]; then
 | |
|   PREFIX="${opre}"
 | |
|   SUFFIX="${osuf}"
 | |
|   compadd -Q "$mopts[@]" -S '' "$group[@]" "$expl[@]" \
 | |
|           -M "r:|/=* r:|=* $mspec" -p "$linepath" - "$exppaths[@]"
 | |
| fi
 | |
| 
 | |
| [[ nm -ne compstate[nmatches] ]]
 |