]> git.madduck.net Git - etc/zsh.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

add temp hack for #486785
authormartin f. krafft <madduck@madduck.net>
Wed, 16 Jul 2008 14:14:59 +0000 (16:14 +0200)
committermartin f. krafft <madduck@madduck.net>
Wed, 16 Jul 2008 14:14:59 +0000 (16:14 +0200)
.zsh/func/_path_files [new file with mode: 0644]

diff --git a/.zsh/func/_path_files b/.zsh/func/_path_files
new file mode 100644 (file)
index 0000000..a4aac8a
--- /dev/null
@@ -0,0 +1,743 @@
+#autoload
+
+# TEMPORARY HACK for #486785
+
+# 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 ignore pfx pfxsfx sopt gopt opt sdirs ignpar cfopt listsfx
+local nm=$compstate[nmatches] menu matcher mopts sort mid accex fake
+local listfiles listopts tmpdisp
+local -a match mbegin mend
+
+typeset -U prepaths exppaths
+
+exppaths=()
+
+# Get the options.
+
+zparseopts -a mopts \
+    'P:=pfx' '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}"
+  pats=( '*(-/)' ${${(z):-x $pats}[2,-1]} )
+else
+  pats="${(@)${(@M)tmp1:#-g*}#-g}"
+  pats=( ${${(z):-x $pats}[2,-1]} )
+fi
+pats=( "${(@)pats:# #}" )
+
+if (( $#pfx )); then
+  compset -P "$pfx[2]" || pfxsfx=( "$pfx[@]" "$pfxsfx[@]" )
+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 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 given no `-F' option, we may want to use $fignore, turned into patterns.
+
+[[ -z "$_comp_no_ignore" && $#ignore -eq 0 &&
+   ( -z $gopt || "$pats" = \ #\*\ # ) && -n $FIGNORE ]] && 
+    ignore=( "?*${^fignore[@]}" )
+
+if (( $#ignore )); then
+  _comp_ignore=( "$_comp_ignore[@]" "$ignore[@]" )
+  (( $mopts[(I)-F] )) || mopts=( "$mopts[@]" -F _comp_ignore )
+fi
+
+if [[ $#matcher -eq 0 && -o nocaseglob ]]; then
+  # If globbing is case insensitive and there's no matcher,
+  # do case-insensitive matching.
+  matcher=( -M 'm:{a-zA-Z}={A-Za-z}' )
+fi
+
+if (( $#matcher )); then
+  # Add the current matcher to the options to compadd.
+  mopts=( "$mopts[@]" "$matcher[@]" )
+fi
+
+if zstyle -s ":completion:${curcontext}:" file-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)(*[^\$])"(#q"(*)")" ]]; then
+       tmp2=( "$tmp2[@]" "${match[1]}(#q${sort}${match[2]})" )
+      elif [[ "$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
+# immediately.
+
+if zstyle -t ":completion:${curcontext}:paths" squeeze-slashes; then
+  skips='((.|..|)/)##'
+else
+  skips='((.|..)/)##'
+fi
+
+zstyle -s ":completion:${curcontext}:paths" special-dirs sdirs
+zstyle -t ":completion:${curcontext}:paths" list-suffixes &&
+    listsfx=yes
+
+[[ "$pats" = ((|*[[:blank:]])\*(|[[:blank:]]*|\([^[:blank:]]##\))|*\([^[:blank:]]#/[^[:blank:]]#\)*) ]] &&
+    sopt=$sopt/
+
+zstyle -a ":completion:${curcontext}:paths" accept-exact accex
+zstyle -a ":completion:${curcontext}:" fake-files fake
+
+zstyle -s ":completion:${curcontext}:" ignore-parents ignpar
+
+if [[ -n "$compstate[pattern_match]" &&
+      ( ( -z "$SUFFIX" && "$PREFIX" = (|*[^\$])\([^\|\~]##\) ) ||
+        "$SUFFIX" =  (|*[^\$])\([^\|\~]##\) ) ]]; then
+  # Copy all glob qualifiers from the line to
+  # the patterns used when generating matches
+  if [[ "$SUFFIX" = *\([^\|\~]##\) ]]; then
+    tmp3="${${(M)SUFFIX%\([^\|\~]##\)}[2,-2]}"
+    SUFFIX="${SUFFIX%\($tmp3\)}"
+  else
+    tmp3="${${(M)PREFIX%\([^\|\~]##\)}[2,-2]}"
+    PREFIX="${PREFIX%\($tmp3\)}"
+  fi
+  tmp2=()
+  for tmp1 in "$pats[@]"; do
+    if [[ "$tmp1" = (#b)(*[^\$])"(#q"(*)")" ]]; then
+      tmp2=( "$tmp2[@]" "${match[1]}(#q${tmp3}${match[2]})" )
+    elif [[ "$tmp1" = (#b)(*[^\$])(\(\([^\|~]##\)\)) ]]; then
+      tmp2=( "$tmp2[@]" "${match[1]}((${tmp3}${match[2][3,-1]}" )
+    elif [[ "$tmp1" = (#b)(*[^\$])(\([^\|~]##\)) ]]; then
+      tmp2=( "$tmp2[@]" "${match[1]}(${tmp3}${match[2][2,-1]}" )
+    else
+      tmp2=( "$tmp2[@]" "${tmp1}(${tmp3})" )
+    fi
+  done
+  pats=( "$tmp2[@]" )
+fi
+
+# We get the prefix and the suffix from the line and save the whole
+# original string. Then we see if we will do menu completion.
+
+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#\~}" != (|*[^\\])[][*?#~^\|\<\>]* ) ]] && menu=yes
+[[ -n "$_comp_correct" ]] && cfopt=-
+
+# Now let's have a closer look at the string to complete.
+
+if [[ "$pre" = [^][*?#^\|\<\>\\]#(\`[^\`]#\`|\$)*/* && "$compstate[quote]" != \' ]]; 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##*\$[^/]##/}"
+  eval 'realpath=${(e)~linepath}' 2>/dev/null
+  [[ -z "$realpath" || "$realpath" = "$linepath" ]] && return 1
+  pre="${pre#${linepath}}"
+  i='[^/]'
+  i="${#linepath//$i}"
+  orig="${orig[1,(in:i:)/][1,-2]}"
+  donepath=
+  prepaths=( '' )
+elif [[ "$pre[1]" = \~ && -z "$compstate[quote]" ]]; 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 [[ "$linepath" = ([-+]|)[0-9]## ]]; then
+    if [[ "$linepath" != [-+]* ]]; then
+      tmp1="$linepath"
+    else
+      if [[ "$linepath" = -* ]]; then
+        tmp1=$(( $#dirstack $linepath ))
+      else
+        tmp1=$linepath[2,-1]
+      fi
+      [[ -o pushdminus ]] && tmp1=$(( $#dirstack - $tmp1 ))
+    fi
+    if (( ! tmp1 )); then
+      realpath=$PWD/
+    elif [[ tmp1 -le $#dirstack ]]; then
+      realpath=$dirstack[tmp1]/
+    else
+      _message 'not enough directory stack entries'
+      return 1
+    fi
+  elif [[ "$linepath" = [-+] ]]; then
+    realpath=${~:-\~$linepath}/
+  else
+    eval "realpath=~${linepath}/" 2>/dev/null
+    if [[ -z "$realpath" ]]; then
+      _message "unknown user \`$linepath'"
+      return 1
+    fi
+  fi
+  linepath="~${linepath}/"
+  [[ "$realpath" = "$linepath" ]] && return 1
+  pre="${pre#*/}"
+  orig="${orig#*/}"
+  donepath=
+  prepaths=( '' )
+else
+  # If the string does not start with a `~' we don't remove a prefix from the
+  # string.
+
+  linepath=
+  realpath=
+
+  if zstyle -s ":completion:${curcontext}:" preserve-prefix tmp1 &&
+     [[ -n "$tmp1" && "$pre" = (#b)(${~tmp1})* ]]; then
+
+    pre="$pre[${#match[1]}+1,-1]"
+    orig="$orig[${#match[1]}+1,-1]"
+    donepath="$match[1]"
+    prepaths=( '' )
+
+  elif [[ "$pre[1]" = / ]]; then
+    # If it is a absolute 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.
+
+  skipped=
+  cpre=
+  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
+
+    # Force auto-mounting. There might be a better way...
+    # Commented out in the hope that `pws non-canonical hack'
+    # down below does this for us.  Can be uncommented if it
+    # doesn't.
+
+    # : ${^tmp1}/${PREFIX}${SUFFIX}/.(/)
+
+    # Get the matching files by globbing.
+
+    tmp2=( "$tmp1[@]" )
+
+    # Look for glob qualifiers.
+    # Extra nastiness to be careful about a quoted parenthesis.
+    # The initial tests look for parentheses with zero or an
+    # even number of backslashes in front.
+    # The later test looks for an outstanding quote.
+    if [[ ( -o bareglobqual && \
+             "$tpre/$tsuf" = (#b)((*[^\\]|)(\\\\)#\()([^\)]#) || \
+            -o extendedglob && \
+               "$tpre/$tsuf" = (#b)((*[^\\]|)(\\\\)#"(#q")([^\)]#) \
+         ) && -z $compstate[quote] ]]; then
+       compset -p ${#match[1]}
+       _globquals
+    elif [[ "$tpre$tsuf" = */* ]]; then
+      compfiles -P$cfopt tmp1 accex "$skipped" "$_matcher $matcher[2]" "$sdirs" fake
+    elif [[ "$sopt" = *[/f]* ]]; then
+      compfiles -p$cfopt tmp1 accex "$skipped" "$_matcher $matcher[2]" "$sdirs" fake "$pats[@]"
+    else
+      compfiles -p$cfopt tmp1 accex "$skipped" "$_matcher $matcher[2]" '' fake "$pats[@]"
+    fi
+    tmp1=( $~tmp1 ) 2> /dev/null
+
+    if [[ -n "$PREFIX$SUFFIX" ]]; then
+      # See which of them match what's on the line.
+
+      # pws non-canonical hack which seems to work so far...
+      # if we didn't match by globbing, check that there is
+      # something to match by explicit name.  This is for
+      # `clever' filing systems where names pop into existence
+      # when referenced.
+      if (( ! $#tmp1 )); then
+         for tmp3 in "$tmp2[@]"; do
+             if [[ -n $tmp3 && $tmp3 != */ ]]; then
+                 tmp3+=/
+             fi
+             if [[ -e "$tmp3${(Q)PREFIX}${(Q)SUFFIX}" ]] then
+                 tmp1+=("$tmp3${(Q)PREFIX}${(Q)SUFFIX}")
+             fi
+         done
+      fi
+
+      if (( ! $#tmp1 )); then
+        tmp2=( ${^tmp2}/$PREFIX$SUFFIX )
+      elif [[ "$tmp1[1]" = */* ]]; then
+        if [[ -n "$_comp_correct" ]]; then
+          tmp2=( "$tmp1[@]" )
+          builtin compadd -D tmp1 "$matcher[@]" - "${(@)tmp1:t}"
+
+          if [[ $#tmp1 -eq 0 ]]; then
+            tmp1=( "$tmp2[@]" )
+           compadd -D tmp1 "$matcher[@]" - "${(@)tmp2:t}"
+          fi
+        else
+          tmp2=( "$tmp1[@]" )
+          compadd -D tmp1 "$matcher[@]" - "${(@)tmp1:t}"
+        fi
+      else
+        tmp2=( '' )
+        compadd -D tmp1 "$matcher[@]" -a tmp1
+      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
+          elif [[ ${tpre}${tsuf} = */* ]]; then
+           exppaths=( "$exppaths[@]" ${tpre}${tsuf} )
+
+           ### this once was in an `else' (not `elif')
+         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
+       pfxsfx=(-S '' "$pfxsfx[@]")
+       ### Don't remember what the break was good for. We explicitly
+       ### execute this only when there are no matches in the directory,
+       ### so why continue?
+       ###
+        ### tmp1=( "$tmp2[@]" )
+       ### break
+      elif [[ -n "$haspats" && -z "$tpre$tsuf$suf" && "$pre" = */ ]]; then
+       PREFIX="${opre}"
+       SUFFIX="${osuf}"
+        compadd -nQS '' - "$linepath$donepath$orig"
+        tmp4=-
+      fi
+      continue 2
+    fi
+
+    if [[ -n "$ignpar" && -z "$_comp_no_ignore" &&
+          "$tpre$tsuf" != */* && $#tmp1 -ne 0 &&
+          ( "$ignpar" != *dir* || "$pats" = '*(-/)' ) &&
+          ( "$ignpar" != *..* || "$tmp1[1]" = *../* ) ]]; then
+
+      compfiles -i tmp1 _comp_ignore "$ignpar" "$prepath$realpath$donepath"
+
+      (( $#_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.
+
+    tmp1=( ${tmp1//(#b)([][()|*?^#~<>\\=])/\\${match[1]}} )
+    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"
+  [[ -n "${prepath}${realpath}${testpath}" ]] &&
+      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'.
+    # The return value is non-zero if the component is ambiguous.
+
+    compfiles -r tmp1 "${(Q)tmp3}"
+    tmp4=$?
+
+    if [[ "$tpre" = */* ]]; then
+      tmp2="${cpre}${tpre%%/*}"
+      PREFIX="${donepath}${linepath}${tmp2}"
+      SUFFIX="/${tpre#*/}${tsuf#*/}"
+    else
+      tmp2="${cpre}${tpre}"
+      PREFIX="${donepath}${linepath}${tmp2}"
+      SUFFIX="${tsuf}"
+    fi
+
+    # This once tested `|| [[ -n "$compstate[pattern_match]" &&
+    # "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]' but it should now be smart
+    # enough to handle multiple components with patterns.
+
+    if (( tmp4 )); then
+      # It is. For menu completion we now add the possible completions
+      # for this component with the unambiguous 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"
+      if [[ -n "$linepath" ]]; then
+        compquote -p tmp2 tmp1
+      elif [[ -n "$tmp2" ]]; then
+        compquote -p tmp1
+        compquote tmp2
+      else
+        compquote tmp1 tmp2
+      fi
+
+      if [[ -z "$_comp_correct" &&
+            "$compstate[pattern_match]" = \*  && -n "$listsfx" &&
+            "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then
+        PREFIX="$opre"
+        SUFFIX="$osuf"
+      fi
+
+      # This once tested `-n $menu ||' but our menu-completion expert says
+      # that's not what we want.
+
+      if [[ -z "$compstate[insert]" ]] ||
+         { ! zstyle -t ":completion:${curcontext}:paths" expand suffix &&
+           [[ -z "$listsfx" &&
+              ( -n "$_comp_correct" ||
+                -z "$compstate[pattern_match]" || "$SUFFIX" != */* ||
+                "${SUFFIX#*/}" = (|*[^\\])[][*?#~^\|\<\>]* ) ]] }; then
+       # We have not been told to insert the match, so we are
+       # listing, or something.
+        (( tmp4 )) && zstyle -t ":completion:${curcontext}:paths" ambiguous &&
+            compstate[to_end]=
+        if [[ "$tmp3" = */* ]]; then
+         if [[ -z "$listsfx" || "$tmp3" != */?* ]]; then
+           # I think this means we are expanding some directory
+           # back up the path.
+           tmp1=("${(@)tmp1%%/*}")
+           _list_files tmp1 "$prepath$realpath$testpath"
+           compadd -Qf "$mopts[@]" -p "$linepath$tmp2" -s "/${tmp3#*/}" \
+                   -W "$prepath$realpath$testpath" \
+                   "$pfxsfx[@]" -M "r:|/=* r:|=*" \
+                   $listopts \
+                   -a tmp1
+          else
+           # Same with a non-empty suffix
+           tmp1=("${(@)^tmp1%%/*}/${tmp3#*/}")
+           _list_files tmp1 "$prepath$realpath$testpath"
+           compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
+                   -W "$prepath$realpath$testpath" \
+                   "$pfxsfx[@]" -M "r:|/=* r:|=*" \
+                   $listopts \
+                   -a tmp1
+          fi
+       else
+         _list_files tmp1 "$prepath$realpath$testpath"
+         compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
+                 -W "$prepath$realpath$testpath" \
+                  "$pfxsfx[@]" -M "r:|/=* r:|=*" \
+                  $listopts \
+                  -a tmp1
+       fi
+      else
+       # We are inserting the match into the command line.
+        if [[ "$tmp3" = */* ]]; then
+         tmp4=( -Qf "$mopts[@]" -p "$linepath$tmp2"
+                -W "$prepath$realpath$testpath"
+                "$pfxsfx[@]" -M "r:|/=* r:|=*" )
+         if [[ -z "$listsfx" ]]; then
+            for i in "$tmp1[@]"; do
+             tmpdisp=("${i%%/*}")
+             _list_files tmpdisp "$prepath$realpath$testpath"
+             compadd "$tmp4[@]" -s "/${i#*/}" $listopts - "$tmpdisp"
+           done
+          else
+            [[ -n "$compstate[pattern_match]" ]] && SUFFIX="${SUFFIX:s./.*/}*"
+
+            for i in "$tmp1[@]"; do
+             _list_files i "$prepath$realpath$testpath"
+             compadd "$tmp4[@]" $listopts - "$i"
+           done
+          fi
+        else
+         _list_files tmp1 "$prepath$realpath$testpath"
+         compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
+                  -W "$prepath$realpath$testpath" \
+                 "$pfxsfx[@]" -M "r:|/=* r:|=*" \
+                  $listopts \
+                 -a 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]%%/*}/"
+
+    tmp3="${tmp3#*/}"
+
+    if [[ "$tpre" = */* ]]; then
+      if [[ -z "$_comp_correct" && -n "$compstate[pattern_match]" &&
+            "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then
+        cpre="${cpre}${tmp1[1]%%/*}/"
+      else
+        cpre="${cpre}${tpre%%/*}/"
+      fi
+      tpre="${tpre#*/}"
+    elif [[ "$tsuf" = */* ]]; then
+      [[ "$tsuf" != /* ]] && mid="$testpath"
+      if [[ -z "$_comp_correct" && -n "$compstate[pattern_match]" &&
+            "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then
+        cpre="${cpre}${tmp1[1]%%/*}/"
+      else
+        cpre="${cpre}${tpre}/"
+      fi
+      tpre="${tsuf#*/}"
+      tsuf=
+    else
+      tpre=
+      tsuf=
+    fi
+
+    tmp1=( "${(@)tmp1#*/}" )
+  done
+
+  if [[ -z "$tmp4" ]]; then
+    if [[ "$mid" = */ ]]; then
+      PREFIX="${opre}"
+      SUFFIX="${osuf}"
+
+      tmp4="${testpath#${mid}}"
+      tmp3="${mid%/*/}"
+      tmp2="${${mid%/}##*/}"
+      if [[ -n "$linepath" ]]; then
+        compquote -p tmp3
+      else
+        compquote tmp3
+      fi
+      compquote tmp4 tmp2 tmp1
+      for i in "$tmp1[@]"; do
+       _list_files tmp2 "$prepath$realpath${mid%/*/}"
+        compadd -Qf "$mopts[@]" -p "$linepath$tmp3/" -s "/$tmp4$i" \
+                -W "$prepath$realpath${mid%/*/}/" \
+               "$pfxsfx[@]" -M "r:|/=* r:|=*" $listopts - "$tmp2"
+      done
+    else
+      if [[ "$osuf" = */* ]]; then
+        PREFIX="${opre}${osuf}"
+        SUFFIX=
+      else
+        PREFIX="${opre}"
+        SUFFIX="${osuf}"
+      fi
+      tmp4="$testpath"
+      if [[ -n "$linepath" ]]; then
+        compquote -p tmp4 tmp1
+      elif [[ -n "$tmp4" ]]; then
+        compquote -p tmp1
+        compquote tmp4
+      else
+        compquote tmp4 tmp1
+      fi
+      if [[ -z "$_comp_correct" && -n "$compstate[pattern_match]" &&
+            "${PREFIX#\~}$SUFFIX" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then
+       tmp1=("$linepath$tmp4${(@)^tmp1}")
+       _list_files tmp1 "$prepath$realpath"
+        compadd -Qf -W "$prepath$realpath" "$pfxsfx[@]" "$mopts[@]" \
+                -M "r:|/=* r:|=*" $listopts -a tmp1
+      else
+       # Not a pattern match
+       _list_files tmp1 "$prepath$realpath$testpath"
+        compadd -Qf -p "$linepath$tmp4" -W "$prepath$realpath$testpath" \
+               "$pfxsfx[@]" "$mopts[@]" -M "r:|/=* r:|=*" $listopts -a tmp1
+      fi
+    fi
+  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. Do that only if we are currently trying the
+# last entry in the matcher-list style, otherwise other match specs might
+# make the suffix that didn't match this time match in one of the following
+# attempts.
+
+if [[ _matcher_num -eq ${#_matchers} ]] &&
+   zstyle -t ":completion:${curcontext}:paths" expand prefix &&
+   [[ nm -eq compstate[nmatches] && $#exppaths -ne 0 &&
+      "$linepath$exppaths" != "$eorig" ]]; then
+  PREFIX="${opre}"
+  SUFFIX="${osuf}"
+  compadd -Q "$mopts[@]" -S '' -M "r:|/=* r:|=*" -p "$linepath" -a exppaths
+fi
+
+[[ nm -ne compstate[nmatches] ]]