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

Re: Completion introspection

Roman Perepelitsa wrote:
> Maybe there is another way? Perhaps it's possible to configure zsh
> completion system so that all file completions are recursive? My tab
> binding is actually also using fzf if there are multiple possible
> completions, so if file completions were recursive, that would work.

There is more than one possible approach to this depending on how you
want it to work. There is a recursive-files style or you can approach it
via the the file-patterns style.

For a custom completion widget, the usual starting point is to use
_generic, this creates one and binds it:

  zle -C recursive-files complete-word _generic
  bindkey '\ef' recursive-files

Now you probably want to define a completer, if that's not covered by
a generic style. _complete is a reasonable minimum but others (such as
_approximate) may be useful. Or perhaps _files if you want to ignore
completion or as a fallback if _complete fails.

  zstyle ':completion:recursive-files::::' completer _complete

You can now try this style:
  zstyle ':completion:recursive-files:*' recursive-files '*'

Or, try a different approach:

  zstyle ':completion:recursive-files:*' file-patterns \
      '**/%p:globbed-files' '**/%p(#qD):hidden-globbed-files' '**/*(-.):all-files'
  zstyle ':completion:recursive-files:*' matcher 'r:/||[^/]=**'

The matcher is what ensures that "two" on the command-line will match to
"one/two". It'll also match "one/two/three" (I'd be interested if anyone
knows of a way around that). You could go all-in and use 'b:=*' so that
any substring will match.

There may be cases where this doesn't work, especially where _files is
somewhat bypassed such as for git completion. The recursive glob doesn't
work well with how _path_files normally handles hidden files – hence
the workaround of including it in file-patterns.

Using menu-selection along with it's search feature gets closer to fzf.
You'll need to load the complist module if you're not already doing
that. Then we can force the use of a menu in the case of ambiguities.
This is especially useful in cases where completion has determined
that there are multiple possible insertion points to disambiguate a

  zstyle ":completion:recursive-files:*:default" menu yes=1 select=0 search

The search is not fuzzy and the list is not filtered and reordered to
only give the matching entries but it has some advantages like using
columns and much less space below the cursor. How valuable really is the
fuzzy aspect of the fzf searching?

The recursive-files style declares an array local inside a loop which
causes it to be printed on subsequent loops. The _zstyle completer
didn't complete it, and could perhaps complete a generated list of
functions for the second part of the context. A patch for this is
attached. Rather than using $PWD, shouldn't the recursive-files
completer take notice of the -W and -P options plus and directory
portion in $PREFIX. I'm not sure of the use case for limiting it by $PWD


diff --git a/Completion/Unix/Type/_files b/Completion/Unix/Type/_files
index 6adaa8154..4ddec1e12 100644
--- a/Completion/Unix/Type/_files
+++ b/Completion/Unix/Type/_files
@@ -1,6 +1,7 @@
 #compdef -redirect-,-default-,-default-
 local -a match mbegin mend
+local -a subtree
 local ret=1
 # Look for glob qualifiers. This is duplicated from _path_files because
@@ -110,7 +111,6 @@ for def in "$pats[@]"; do
           if _path_files -g "$pat" "$opts[@]" "$expl[@]"; then
 	  elif [[ $PREFIX$SUFFIX != */* ]] && zstyle -a ":completion:${curcontext}:$tag" recursive-files rfiles; then
-	    local subtree
 	    for rfile in $rfiles; do
 	      if [[ $PWD/ = ${~rfile} ]]; then
 		if [[ -z $subtree ]]; then
diff --git a/Completion/Zsh/Command/_zstyle b/Completion/Zsh/Command/_zstyle
index 07b60605f..e9a5d800c 100644
--- a/Completion/Zsh/Command/_zstyle
+++ b/Completion/Zsh/Command/_zstyle
@@ -100,6 +100,7 @@ styles=(
   preserve-prefix        c:preserve-prefix
   range                  c:
   recent-dirs-insert     c:recent-dirs-insert
+  recursive-files        c:
   regular                c:bool
   rehash		 c:bool
   remote-access		 c:bool
@@ -409,14 +410,15 @@ while (( $#state )); do
-      _wanted control-function expl 'control function' \
+      _wanted control-functions expl 'control function' \
           compadd predict-on all-matches
-      _wanted comp-widget expl 'completion widget' \
-          compadd $suf - all-matches complete-debug complete-tag \
-	  correct-word expand-word expand-alias-word history-words
+      _wanted comp-widgets expl 'completion widget' \
+          compadd $suf -M 'r:|-=* r:|=*' - all-matches complete-debug complete-tag \
+	  correct-word expand-word expand-alias-word history-words \
+	  ${${${(M)${(f)"$(_call_program comp-widgets zle -l)"}:#*-C*}:#_*}/ -C*}

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