mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-11-04 07:21:06 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			548 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			548 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 skipped
 | 
						|
local tmp1 tmp2 tmp3 tmp4 i orig eorig pre suf tpre tsuf opre osuf cpre
 | 
						|
local pats haspats=no ignore pfxsfx rem remt sopt gopt opt
 | 
						|
local nm=$compstate[nmatches] menu matcher mopts atmp sort match
 | 
						|
 | 
						|
typeset -U prepaths exppaths
 | 
						|
 | 
						|
setopt localoptions nullglob rcexpandparam
 | 
						|
unsetopt markdirs globsubst shwordsplit nounset
 | 
						|
 | 
						|
exppaths=()
 | 
						|
 | 
						|
# Get the options.
 | 
						|
 | 
						|
zparseopts -a mopts \
 | 
						|
    'P:=pfxsfx' 'S:=pfxsfx' 'q=pfxsfx' 'r:=pfxsfx' 'R:=pfxsfx' \
 | 
						|
    'W:=prepaths' 'F:=ignore' 'M+:=matcher' \
 | 
						|
    J: V: X: 1: 2: n: 'f=tmp1' '/=tmp1' 'g+:-=tmp1'
 | 
						|
 | 
						|
sopt="-${(@j::M)${(@)tmp1#-}#?}"
 | 
						|
(( $tmp1[(I)-[/g]*] )) && haspats=yes
 | 
						|
(( $tmp1[(I)-g*] )) && gopt=yes
 | 
						|
if (( $tmp1[(I)-/] )); then
 | 
						|
  pats=( '*(-/)' ${=${(M)tmp1:#-g*}#-g} )
 | 
						|
else
 | 
						|
  pats=( "${(@)=${(@M)tmp1:#-g*}#-g}" )
 | 
						|
fi
 | 
						|
 | 
						|
if (( $#prepaths )); then
 | 
						|
  tmp1="${prepaths[2]}"
 | 
						|
  if [[ "$tmp1[1]" = '(' ]]; then
 | 
						|
    prepaths=( ${^=tmp1[2,-2]%/}/ )
 | 
						|
  elif [[ "$tmp1[1]" = '/' ]]; then
 | 
						|
    prepaths=( "${tmp1%/}/" )
 | 
						|
  else
 | 
						|
    prepaths=( ${(P)^tmp1%/}/ )
 | 
						|
    (( ! $#prepaths )) && prepaths=( ${tmp1%/}/ )
 | 
						|
  fi
 | 
						|
  (( ! $#prepaths )) && prepaths=( '' )
 | 
						|
else
 | 
						|
  prepaths=( '' )
 | 
						|
fi
 | 
						|
 | 
						|
if (( $#ignore )); then
 | 
						|
  if [[ "${ignore[2]}" = \(* ]]; then
 | 
						|
    ignore=( ${=ignore[2][2,-2]} )
 | 
						|
  else
 | 
						|
    ignore=( ${(P)ignore[2]} )
 | 
						|
  fi
 | 
						|
fi  
 | 
						|
 | 
						|
if [[ -z "$_file_pat_checked" ]] &&
 | 
						|
   zstyle -s ":completion:${curcontext}:files" file-patterns tmp1 &&
 | 
						|
   [[ -n "$tmp1" ]]; then
 | 
						|
  if [[ "$tmp1" = '*(-/)' ]]; then
 | 
						|
    gopt=''
 | 
						|
    sopt=-/
 | 
						|
  else
 | 
						|
    gopt=yes
 | 
						|
    sopt=-
 | 
						|
  fi
 | 
						|
  pats=( $=tmp1 )
 | 
						|
  haspats=yes
 | 
						|
fi
 | 
						|
 | 
						|
# If we were given no file selection option, we behave as if we were given
 | 
						|
# a `-f'.
 | 
						|
 | 
						|
if [[ "$sopt" = -(f|) ]]; then
 | 
						|
  if [[ -z "$gopt" ]]; then
 | 
						|
    sopt='-f'
 | 
						|
    pats=('*')
 | 
						|
  else
 | 
						|
    unset sopt
 | 
						|
  fi
 | 
						|
fi
 | 
						|
 | 
						|
if (( ! $mopts[(I)-[JVX]] )); then
 | 
						|
  local expl
 | 
						|
 | 
						|
  if [[ -z "$gopt" && "$sopt" = -/ ]]; then
 | 
						|
    _description directories expl directory
 | 
						|
  else
 | 
						|
    _description files expl file
 | 
						|
  fi
 | 
						|
  tmp1=$expl[(I)-M*]
 | 
						|
  if (( tmp1 )); then
 | 
						|
    if (( $#matcher )); then
 | 
						|
      matcher[2]="$matcher[2] $expl[1+tmp1]"
 | 
						|
    else
 | 
						|
      matcher=(-M "$expl[1+tmp1]")
 | 
						|
    fi
 | 
						|
  fi
 | 
						|
  mopts=( "$mopts[@]" "$expl[@]" )
 | 
						|
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
 | 
						|
    mopts=( "${(@)mopts/#-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
 | 
						|
 | 
						|
# Check if we have to skip over sequences of slashes. The value of $skips
 | 
						|
# is used below to match the pathname components we always have to accept
 | 
						|
# immediatly.
 | 
						|
 | 
						|
if zstyle -t ":completion:${curcontext}:paths" squeeze-slashes; then
 | 
						|
  skips='((.|..|)/)##'
 | 
						|
else
 | 
						|
  skips='((.|..)/)##'
 | 
						|
fi
 | 
						|
 | 
						|
# 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" ||
 | 
						|
   ( -n "$compstate[pattern_match]" &&
 | 
						|
     "${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[@]" )
 | 
						|
  (( $mopts[(I)-F] )) || mopts=( "$mopts[@]" -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[2,-1]%%/*}"
 | 
						|
  if [[ -z "$linepath" ]]; then
 | 
						|
    realpath="${HOME%/}/"
 | 
						|
  elif (( $+userdirs[$linepath] )); then
 | 
						|
    realpath="${userdirs[$linepath]%/}/"
 | 
						|
  elif (( $+nameddirs[$linepath] )); then
 | 
						|
    realpath="${nameddirs[$linepath]%/}/"
 | 
						|
  else
 | 
						|
    _message "unknown user \`$linepath'"
 | 
						|
    return 1
 | 
						|
  fi
 | 
						|
  linepath="~${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"
 | 
						|
 | 
						|
  tmp2="${(M)tpre##${~skips}}"
 | 
						|
  tpre="${tpre#$tmp2}"
 | 
						|
 | 
						|
  tmp1=( "$prepath$realpath$donepath$tmp2" )
 | 
						|
 | 
						|
  while true; do
 | 
						|
 | 
						|
    # 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.
 | 
						|
 | 
						|
    tmp2=( "$tmp1[@]" )
 | 
						|
    if [[ "$tpre$tsuf" = */* ]]; then
 | 
						|
      if [[ ! -o globdots && "$PREFIX" = .* ]]; then
 | 
						|
        tmp1=( ${^tmp1}${skipped}*(-/) ${^tmp1}${skipped}.*(-/) )
 | 
						|
      else
 | 
						|
        tmp1=( ${^tmp1}${skipped}*(-/) )
 | 
						|
      fi
 | 
						|
      if [[ -o globdots || "$PREFIX" = .* ]] &&
 | 
						|
         zstyle -s ":completion:${curcontext}:paths" special-dirs atmp; then
 | 
						|
	if [[ "$atmp" = (yes|true|1|on) ]]; then
 | 
						|
	  tmp1=( "$tmp1[@]" . .. )
 | 
						|
	elif [[ "$atmp" = .. ]]; then
 | 
						|
	  tmp1=( "$tmp1[@]" .. )
 | 
						|
        fi
 | 
						|
      fi
 | 
						|
    else
 | 
						|
      if [[ ! -o globdots && "$PREFIX" = .* ]]; then
 | 
						|
        tmp1=( ${^tmp1}${skipped}${^~pats} ${^tmp1}${skipped}.${^~pats} )
 | 
						|
      else
 | 
						|
        tmp1=( ${^tmp1}${skipped}${^~pats} )
 | 
						|
      fi
 | 
						|
      if [[ "$sopt" = *[/f]* && ( -o globdots || "$PREFIX" = .* ) ]] &&
 | 
						|
	  zstyle -s ":completion:${curcontext}:paths" special-dirs atmp; then
 | 
						|
	if [[ "$atmp" = (yes|true|1|on) ]]; then
 | 
						|
	  tmp1=( "$tmp1[@]" . .. )
 | 
						|
	elif [[ "$atmp" = .. ]]; then
 | 
						|
	  tmp1=( "$tmp1[@]" .. )
 | 
						|
        fi
 | 
						|
      fi
 | 
						|
    fi
 | 
						|
 | 
						|
    if [[ -n "$PREFIX$SUFFIX" ]]; then
 | 
						|
      # See which of them match what's on the line.
 | 
						|
 | 
						|
      if [[ -n "$_comp_correct" ]]; then
 | 
						|
        tmp2=( "$tmp1[@]" )
 | 
						|
        builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
 | 
						|
 | 
						|
        if [[ $#tmp1 -eq 0 ]]; then
 | 
						|
          tmp1=( "$tmp2[@]" )
 | 
						|
	  compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp2:t}"
 | 
						|
        fi
 | 
						|
      else
 | 
						|
        [[ "$tmp1[1]" = */* ]] && tmp2=( "$tmp1[@]" )
 | 
						|
 | 
						|
        builtin compadd -D tmp1 -F _comp_ignore "$matcher[@]" - "${(@)tmp1:t}"
 | 
						|
      fi
 | 
						|
 | 
						|
      # If no file matches, save the expanded path and continue with
 | 
						|
      # the outer loop.
 | 
						|
 | 
						|
      if (( ! $#tmp1 )); 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[@]" )
 | 
						|
	pfxsfx=(-S '' "$pfxsfx[@]")
 | 
						|
	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
 | 
						|
 | 
						|
    if [[ "$tpre$tsuf" != */* && $#tmp1 -ne 0 ]] &&
 | 
						|
       zstyle -s ":completion:${curcontext}:files" ignore-parents rem &&
 | 
						|
       [[ ( "$rem" != *dir* || "$pats" = '*(-/)' ) &&
 | 
						|
	  ( "$rem" != *..* || "$tmp1" = *../* ) ]]; then
 | 
						|
      if [[ "$rem" = *parent* ]]; then
 | 
						|
	for i in ${(M)^tmp1:#*/*}(-/); do
 | 
						|
	  remt="${${i#$prepath$realpath$donepath}%/*}"
 | 
						|
	  while [[ "$remt" = */* &&
 | 
						|
	           ! "$prepath$realpath$donepath$remt" -ef "$i" ]]; do
 | 
						|
	    remt="${remt%/*}"
 | 
						|
	  done
 | 
						|
	  [[ "$remt" = */* || "$remt" -ef "$i" ]] &&
 | 
						|
	      _comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
 | 
						|
	done
 | 
						|
      fi
 | 
						|
      if [[ "$rem" = *pwd* ]]; then
 | 
						|
        for i in ${^tmp1}(-/); do
 | 
						|
	  [[ "$i" -ef "$PWD" ]] && _comp_ignore=( "$_comp_ignore[@]" "${(q)i}" )
 | 
						|
	done
 | 
						|
      fi
 | 
						|
      (( $#_comp_ignore && $mopts[(I)-F] )) || mopts=( "$mopts[@]" -F _comp_ignore )
 | 
						|
    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 skip over the next components and make a
 | 
						|
    # slash be added.
 | 
						|
 | 
						|
    tmp2="${(M)tpre##((.|..|)/)##}"
 | 
						|
    if [[ -n "$tmp2" ]]; then
 | 
						|
      skipped="/$tmp2"
 | 
						|
      tpre="${tpre#$tmp2}"
 | 
						|
    else
 | 
						|
      skipped=/
 | 
						|
    fi
 | 
						|
  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%%/*}/*}" )
 | 
						|
      (( $#tmp4 )) && tmp1=( "$tmp4[@]" )
 | 
						|
    fi
 | 
						|
 | 
						|
    # Next we see if this component is ambiguous.
 | 
						|
 | 
						|
    if [[ "$tmp3" = */* ]]; then
 | 
						|
       tmp4=$tmp1[(I)^${tmp1[1]%%/*}/*]
 | 
						|
    else
 | 
						|
       tmp4=$tmp1[(I)^${tmp1[1]}]
 | 
						|
    fi
 | 
						|
 | 
						|
    if [[ "$tpre" = */* ]]; then
 | 
						|
      tmp2="${cpre}${tpre%%/*}"
 | 
						|
      PREFIX="${donepath}${linepath}${tmp2}"
 | 
						|
      SUFFIX="/${tpre#*/}${tsuf#*/}"
 | 
						|
    else
 | 
						|
      tmp2="${cpre}${tpre}"
 | 
						|
      PREFIX="${donepath}${linepath}${tmp2}"
 | 
						|
      SUFFIX="${tsuf}"
 | 
						|
    fi
 | 
						|
 | 
						|
    if (( tmp4 )) ||
 | 
						|
       [[ -n "$compstate[pattern_match]" && "$tmp2" != "${(q)tmp2}" ]]; 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.
 | 
						|
 | 
						|
      tmp2="$testpath"
 | 
						|
      compquote tmp1 tmp2
 | 
						|
 | 
						|
      if [[ -n $menu || -z "$compstate[insert]" ]] ||
 | 
						|
         ! zstyle -t ":completion:${curcontext}:paths" expand suffix; then
 | 
						|
        (( tmp4 )) && zstyle -t ":completion:${curcontext}:paths" cursor &&
 | 
						|
            compstate[to_end]=''
 | 
						|
        if [[ "$tmp3" = */* ]]; then
 | 
						|
	  compadd -Qf "$mopts[@]" -p "$linepath$tmp2" -s "/${tmp3#*/}" \
 | 
						|
	          -W "$prepath$realpath$testpath" \
 | 
						|
		  "$pfxsfx[@]" "$matcher[@]" "r:|/=* r:|=*" \
 | 
						|
		  - "${(@)tmp1%%/*}"
 | 
						|
	else
 | 
						|
	  compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
 | 
						|
	          -W "$prepath$realpath$testpath" \
 | 
						|
		   "$pfxsfx[@]" "$matcher[@]" "r:|/=* r:|=*" \
 | 
						|
		   - "$tmp1[@]"
 | 
						|
	fi
 | 
						|
      else
 | 
						|
        if [[ "$tmp3" = */* ]]; then
 | 
						|
	  atmp=( -Qf "$mopts[@]" -p "$linepath$tmp2"
 | 
						|
	         -W "$prepath$realpath$testpath"
 | 
						|
	         "$pfxsfx[@]" "$matcher[@]" "r:|/=* r:|=*" )
 | 
						|
          for i in "$tmp1[@]"; do
 | 
						|
	    compadd "$atmp[@]" -s "/${i#*/}" - "${i%%/*}"
 | 
						|
	  done
 | 
						|
        else
 | 
						|
	  compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
 | 
						|
                  -W "$prepath$realpath$testpath" \
 | 
						|
		  "$pfxsfx[@]" "$matcher[@]" "r:|/=* r:|=*" \
 | 
						|
		  - "$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" \
 | 
						|
	    "$pfxsfx[@]" "$matcher[@]" "r:|/=* r:|=*" - "$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.
 | 
						|
 | 
						|
if zstyle -t ":completion:${curcontext}:paths" expand prefix &&
 | 
						|
   [[ nm -eq compstate[nmatches] ]]; then
 | 
						|
 | 
						|
  exppaths=( "${(@)exppaths:#$eorig}" )
 | 
						|
 | 
						|
  if (( $#exppaths )); then
 | 
						|
    PREFIX="${opre}"
 | 
						|
    SUFFIX="${osuf}"
 | 
						|
    compadd -Q "$mopts[@]" -S '' "$matcher[@]" "r:|/=* r:|=*" -p "$linepath" - "$exppaths[@]"
 | 
						|
  fi
 | 
						|
fi
 | 
						|
 | 
						|
[[ nm -ne compstate[nmatches] ]]
 |