zsh-users
 help / color / Atom feed
* Completion introspection
@ 2020-05-31  8:44 Roman Perepelitsa
  2020-06-01  8:07 ` Daniel Shahaf
  0 siblings, 1 reply; 5+ messages in thread
From: Roman Perepelitsa @ 2020-05-31  8:44 UTC (permalink / raw)
  To: Zsh Users


[-- Attachment #1: Type: text/plain, Size: 1025 bytes --]

What's the best way to retrieve the current completion word, tags and
contexts from a zle widget?

For example, suppose I type this:

  ls ~/foo/

If I now invoke _complete_help via its default ^X^H binding, I see this:

  tags in context :completion::complete:ls::
      argument-rest options  (_arguments _ls)
  tags in context :completion::complete:ls:argument-rest:
      globbed-files  (_files _arguments _ls)

I'd like to define a regular zle widget (not a completion widget) and am
looking for a way to retrieve:

  - the word that would be completed if I pressed tab: ~/foo/
  - the first context: :completion::complete:ls::
  - tags from the last context: globbed-files

Preferably this should be fast. If possible, I'd like to avoid the
generation of completion candidates (no globbing of ~/foo/* in this
example).

If some of these are easier to retrieve than others, I could do with a
subset. E.g., just the word would already be useful. Or just the first
context. Or just the tags from the last context.

Roman.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Completion introspection
  2020-05-31  8:44 Completion introspection Roman Perepelitsa
@ 2020-06-01  8:07 ` Daniel Shahaf
  2020-06-01  8:22   ` Roman Perepelitsa
  0 siblings, 1 reply; 5+ messages in thread
From: Daniel Shahaf @ 2020-06-01  8:07 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh Users

Roman Perepelitsa wrote on Sun, 31 May 2020 10:44 +0200:
> What's the best way to retrieve the current completion word, tags and
> contexts from a zle widget?
> 

What problem are you trying to solve?

> I'd like to define a regular zle widget (not a completion widget) and am
> looking for a way to retrieve:
> 

Why must the widget not be a completion widget?

>   - the word that would be completed if I pressed tab: ~/foo/
>   - the first context: :completion::complete:ls::
>   - tags from the last context: globbed-files


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Completion introspection
  2020-06-01  8:07 ` Daniel Shahaf
@ 2020-06-01  8:22   ` Roman Perepelitsa
  2020-06-02 13:43     ` Oliver Kiddle
  0 siblings, 1 reply; 5+ messages in thread
From: Roman Perepelitsa @ 2020-06-01  8:22 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh Users

On Mon, Jun 1, 2020 at 10:07 AM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> What problem are you trying to solve?

In addition to regular tab completion (expand-or-complete) I have
another key binding for file completion with fzf. If I complete `vi
./` with tab, it'll ask me to choose the first path segment. If I
complete it with alt-i (my fzf file completion binding), I'll be
presented with fuzzy search UI over all files in the current directory
(recursively).

Unfortunately, alt-i binding doesn't work very well. It tries to guess
which word is being completed and which command but it does it without
involving the standard zsh completion system, so it fails often. I'm
trying to improve it.

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.

> Why must the widget not be a completion widget?

I'm not sure if it must be. The current widget isn't a completion
widget and I know how to fix it if only I knew how to get the bits of
information I asked about (the word that would be completed if I
pressed tab, etc.).

Roman.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Completion introspection
  2020-06-01  8:22   ` Roman Perepelitsa
@ 2020-06-02 13:43     ` Oliver Kiddle
  2020-07-01 17:46       ` Roman Perepelitsa
  0 siblings, 1 reply; 5+ messages in thread
From: Oliver Kiddle @ 2020-06-02 13:43 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Daniel Shahaf, Zsh Users

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
completion.

  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
anyway.

Oliver

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
 	    ret=0
 	  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
       ;;
 
     (function)
-      _wanted control-function expl 'control function' \
+      _wanted control-functions expl 'control function' \
           compadd predict-on all-matches
       ;;
 
     (functions)
-      _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*}
       ;;
 
     (user-host-port)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Completion introspection
  2020-06-02 13:43     ` Oliver Kiddle
@ 2020-07-01 17:46       ` Roman Perepelitsa
  0 siblings, 0 replies; 5+ messages in thread
From: Roman Perepelitsa @ 2020-07-01 17:46 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: Daniel Shahaf, Zsh Users

On Tue, Jun 2, 2020 at 3:43 PM Oliver Kiddle <okiddle@yahoo.co.uk> wrote:
>
> There is more than one possible approach to this depending on how you
> want it to work. [...]

Thanks a lot of the detailed reply, Oliver. After meditating on it and
some trial and error I've implemented what I was after. The code is
rather hacky but I gather it's par for the course considering that
what I'm doing is outside of the intended use cases for Zsh completion
system.

I've posted some info about my code at
https://github.com/Aloxaf/fzf-tab/issues/65#issuecomment-652554798.

Roman.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, back to index

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-31  8:44 Completion introspection Roman Perepelitsa
2020-06-01  8:07 ` Daniel Shahaf
2020-06-01  8:22   ` Roman Perepelitsa
2020-06-02 13:43     ` Oliver Kiddle
2020-07-01 17:46       ` Roman Perepelitsa

zsh-users

Archives are clonable: git clone --mirror http://inbox.vuxu.org/zsh-users

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://inbox.vuxu.org/vuxu.archive.zsh.users


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git