Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [BUG] Any type of file in command position gets misleadingly completed as 'executable file'



I wrote:
> However, it is surely a bug that $end is not reinitialised with each
> iteration of the for loop. That makes it difficult to use the
> description we were passed for the globbed-files but to put the
> globbed-files first and directories second.
>
> It also looks like a bug that the recursive-files style is only
> implemented where $end is set.

And here is a patch to address those two points. The recursive-files
code should really consider directories passed with -W instead of
$PWD but all the handling of that is down in _path_files so that's
not trivial. I've not changed the workings of recursive-files, it
appears in full in the patch due to reindentation.

The documentation claims that you can use %d in the description to get
at the description supplied to the function. This isn't working, at
least as far back as 4.2.1 and probably well beyond. It isn't even clear
how this might ever have been implemented. The zformat in _next_label,
comptags -A and $curtag perhaps. I'm not going to go further down that
rabbit hole and have removed the line in the documentation.

Oliver

diff --git a/Completion/Unix/Type/_files b/Completion/Unix/Type/_files
index 4ddec1e12..f03b4a148 100644
--- a/Completion/Unix/Type/_files
+++ b/Completion/Unix/Type/_files
@@ -92,7 +92,10 @@ for def in "$pats[@]"; do
     pat="${${sdef%%:${tag}*}//\\:/:}"
 
     if [[ "$sdef" = *:${tag}:* ]]; then
+      # If the file-patterns spec includes a description, use it and give the
+      # group/description options from it precedence over passed in parameters.
       descr="${(Q)sdef#*:${tag}:}"
+      end=
     else
       if (( $opts[(I)-X] )); then
         descr=
@@ -108,26 +111,30 @@ for def in "$pats[@]"; do
       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
-	    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
+          expl=( "$opts[@]" "$expl[@]" )
         else
-          _path_files "$expl[@]" -g "$pat" "$opts[@]" && ret=0
+          expl+=( "$opts[@]" )
+        fi
+
+        if _path_files -g "$pat" "$expl[@]"; then
+          ret=0
+        elif [[ $PREFIX$SUFFIX != */* ]] && \
+            zstyle -a ":completion:${curcontext}:$tag" recursive-files rfiles
+        then
+          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" "$expl[@]" && ret=0
+                PREFIX=$oprefix
+              done
+              break
+            fi
+          done
         fi
       done
       (( ret )) || break
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index a8beece2d..1adceb536 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -1524,9 +1524,10 @@ If no `tt(:)var(tag)' is given the `tt(files)' tag will be used.
 The var(tag) may also be followed by an optional second colon and a
 description, which will be used for the `tt(%d)' in the value of
 the tt(format) style (if that is set) instead of the default
-description supplied by the completion function.  If the description
-given here contains itself a `tt(%d)', that is replaced with the
-description supplied by the completion function.
+description supplied by the completion function.  The inclusion
+of a description also gives precedence to associated options such as
+for completion grouping so it can be used where files should be
+separated.
 
 For example, to make the tt(rm) command first complete only names of
 object files and then the names of all files if there is no matching
@@ -1548,6 +1549,15 @@ all files using the pattern `tt(*)' at the first step and stops when it
 sees this pattern.  Note also it will never try a pattern more than once
 for a single completion attempt.
 
+To separate directories into a separate group from the files but still
+complete them at the first attempt, a description needs to be given.
+Note that directories need to be explicitly excluded from the
+globbed-files because `tt(*)' will match directories. For grouping, it
+is also necessary to set the tt(group-name) style.
+
+example(zstyle ':completion:*' file-patterns \ 
+    '%p+LPAR()^-/RPAR():globbed-files *(-/):directories:location')
+
 During the execution of completion functions, the tt(EXTENDED_GLOB)
 option is in effect, so the characters `tt(#)', `tt(~)' and `tt(^)' have
 special meanings in the patterns.
@@ -1971,9 +1981,10 @@ obtained by setting the style to an empty string (i.e. tt('')).
 )
 kindex(list-dirs-first, completion style)
 item(tt(list-dirs-first))(
-This is used by file completion.  If set, directories to be completed
-are listed separately from and before completion for other files,
-regardless of tag ordering.
+This is used by file completion and corresponds to a particular
+setting of the tt(file-patterns) style.
+If set, the default directories to be completed
+are listed separately from and before completion for other files.
 )
 kindex(list-grouped, completion style)
 item(tt(list-grouped))(




Messages sorted by: Reverse Date, Date, Thread, Author