zsh-users
 help / color / mirror / code / Atom feed
* Recursive Completition
@ 2012-08-18 21:09 Karoly Negyesi
  2012-08-19  0:18 ` Bart Schaefer
  0 siblings, 1 reply; 10+ messages in thread
From: Karoly Negyesi @ 2012-08-18 21:09 UTC (permalink / raw)
  To: zsh-users

Hi,

I am working with PHP and due to PSR-0 I really need recursive
completition. I am switching to zsh because of this.

ls **/Kernel.php[Tab]

autocompletes to

core/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/Kernel.php

that's really great!

Even better would be if I could have

ls **/Kern[tab]

do that (and not just for ls, but everything else).

Perfect would be just

ls Kern[tab]

to do that. I am aware of the performance implications -- could this
be restricted to the user's home dir only so it doesnt try to read the
whole OS when in the root.

Oh, and maybe display the menu while I am writing a wishlist :)

Thanks much

Karoly Negyesi


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

* Re: Recursive Completition
  2012-08-18 21:09 Recursive Completition Karoly Negyesi
@ 2012-08-19  0:18 ` Bart Schaefer
  2012-08-19 19:44   ` Peter Stephenson
  2012-08-20  9:43   ` René Neumann
  0 siblings, 2 replies; 10+ messages in thread
From: Bart Schaefer @ 2012-08-19  0:18 UTC (permalink / raw)
  To: zsh-users

On Aug 18, 11:09pm, Karoly Negyesi wrote:
}
} ls **/Kernel.php[Tab]
} 
} autocompletes to
} 
} core/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/Kernel.php
} 
} that's really great!

Glad you like it, but you should understand the difference between
_completion_ and _expansion_ before going any further.  What you've
done right there is _expansion_ -- replace a glob pattern with the
thing(s) it matches (expands to).  This happens to be handled as part
of the completion system if you've run "compinit" but it's really not
quite the same thing, because it isn't applying any contextual clues
to the pattern, it's just expanding it.

Note that the default behavior is to try expansion first and complete
only if that fails.
 
} Even better would be if I could have
} 
} ls **/Kern[tab]
} 
} do that (and not just for ls, but everything else).

Here the glob pattern doesn't match (because there's no file named
"Kern" anywhere downstream), so it doesn't expand to anything.  If
you tried

ls **/Kern*[tab]

you'd get something (possibly many somethings).

Fortunately there's a way to move this out of the realm of expansion
and into that of completion; to whit, simply assert that you want
completion to act as if it were using glob patterns:

setopt globcomplete

Now when you try

ls **/Kern[tab]

the completion system behaves as if you'd inserted a * just before [tab],
and offers you the list of matching items as choices.

It's not quite as intutive when encountering a possible branch part way
down the **/ expansion -- you may be offered a set of directories as the
alternatives with no obvious way to choose one of them and then go on
with the same completion.  This gets easier if you force menu-selection
to occur.

} Oh, and maybe display the menu while I am writing a wishlist :)

That's all independently controlled by things like 

setopt automenu
zstyle ':completion:*' menu 'yes=long' 'select=9'

and so on.  There's a bunch of stuff about this toward the end of
section 6.5.2 http://zsh.sourceforge.net/Guide/zshguide06.html#l158
of the user guide.

} Perfect would be just
} 
} ls Kern[tab]
} 
} to do that. I am aware of the performance implications -- could this
} be restricted to the user's home dir only so it doesnt try to read the
} whole OS when in the root.

This one would require that you create a new widget or a new completion
function to insert the implicit leading **/ in the right contexts.  It's
certainly do-able, but I'm going to leave it as an exercise for someone
else, this time.


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

* Re: Recursive Completition
  2012-08-19  0:18 ` Bart Schaefer
@ 2012-08-19 19:44   ` Peter Stephenson
  2012-08-19 21:07     ` Karoly Negyesi
  2012-08-20  9:43   ` René Neumann
  1 sibling, 1 reply; 10+ messages in thread
From: Peter Stephenson @ 2012-08-19 19:44 UTC (permalink / raw)
  To: zsh-users

On Sat, 18 Aug 2012 17:18:26 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> } Perfect would be just
> } 
> } ls Kern[tab]
> } 
> } to do that. I am aware of the performance implications -- could this
> } be restricted to the user's home dir only so it doesnt try to read the
> } whole OS when in the root.
> 
> This one would require that you create a new widget or a new completion
> function to insert the implicit leading **/ in the right contexts.  It's
> certainly do-able, but I'm going to leave it as an exercise for someone
> else, this time.

Bizarrely, I think I've got this to work as part of normal file
completion, ish.  No, honestly.  Set the recursive-files style to true
and see if this does the right thing.  No documentation yet.  It only
works if there's no "/" in the word on the command line at the point
completion is tried.

I can't be sure this is the best place to put it in the file completion
calling sequence, but that statement is so obvious as hardly to be worth
mentioning...

I wonder if there's some limit we can apply to stop this going haywire?

Index: Completion/Unix/Type/_files
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_files,v
retrieving revision 1.13
diff -p -u -r1.13 _files
--- Completion/Unix/Type/_files	19 Mar 2010 16:38:26 -0000	1.13
+++ Completion/Unix/Type/_files	19 Aug 2012 19:40:55 -0000
@@ -1,7 +1,7 @@
 #compdef -redirect-,-default-,-default-
 
 local opts tmp glob pat pats expl tag i def descr end ign ret=1 match tried
-local type sdef ignvars ignvar
+local type sdef ignvars ignvar prepath oprefix
 
 zparseopts -a opts \
     '/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
@@ -118,7 +118,16 @@ for def in "$pats[@]"; do
       while _next_label "$tag" expl "$descr"; do
         _comp_ignore=( $_comp_ignore $ign )
         if [[ -n "$end" ]]; then
-          _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
+          if _path_files -g "$pat" "$opts[@]" "$expl[@]"; then
+	    ret=0
+	  elif [[ $PREFIX$SUFFIX != */* ]] && zstyle -t ":completion:${curcontext}:" recursive-files; then
+	    for prepath in **/*(/); do
+	      oprefix=$PREFIX
+	      PREFIX=$prepath/$PREFIX
+	      _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
+	      PREFIX=$oprefix
+	    done
+	  fi
         else
           _path_files "$expl[@]" -g "$pat" "$opts[@]" && ret=0
         fi

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


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

* Re: Recursive Completition
  2012-08-19 19:44   ` Peter Stephenson
@ 2012-08-19 21:07     ` Karoly Negyesi
  2012-08-20  8:57       ` Peter Stephenson
  0 siblings, 1 reply; 10+ messages in thread
From: Karoly Negyesi @ 2012-08-19 21:07 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-users

> I wonder if there's some limit we can apply to stop this going haywire?

I only need it within a git repo -- maybe that.


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

* Re: Recursive Completition
  2012-08-19 21:07     ` Karoly Negyesi
@ 2012-08-20  8:57       ` Peter Stephenson
  2012-08-20 15:33         ` Bart Schaefer
  0 siblings, 1 reply; 10+ messages in thread
From: Peter Stephenson @ 2012-08-20  8:57 UTC (permalink / raw)
  To: zsh-users

On Sun, 19 Aug 2012 23:07:50 +0200
Karoly Negyesi <karoly@negyesi.net> wrote:
> > I wonder if there's some limit we can apply to stop this going haywire?
> 
> I only need it within a git repo -- maybe that.

One thing to do might be to change the style to be an array of patterns
that are matched against the current directory and only use it in that
case.  So you could set it to "*/.git*".

-- 
Peter Stephenson <pws@csr.com>            Software Engineer
Tel: +44 (0)1223 692070                   Cambridge Silicon Radio Limited
Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, UK


Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
More information can be found at www.csr.com. Follow CSR on Twitter at http://twitter.com/CSR_PLC and read our blog at www.csr.com/blog


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

* Re: Recursive Completition
  2012-08-19  0:18 ` Bart Schaefer
  2012-08-19 19:44   ` Peter Stephenson
@ 2012-08-20  9:43   ` René Neumann
  2012-08-21  4:58     ` Bart Schaefer
  1 sibling, 1 reply; 10+ messages in thread
From: René Neumann @ 2012-08-20  9:43 UTC (permalink / raw)
  To: zsh-users

Am 19.08.2012 02:18, schrieb Bart Schaefer:
> Fortunately there's a way to move this out of the realm of expansion
> and into that of completion; to whit, simply assert that you want
> completion to act as if it were using glob patterns:
> 
> setopt globcomplete
> 
> Now when you try
> 
> ls **/Kern[tab]
> 
> the completion system behaves as if you'd inserted a * just before [tab],
> and offers you the list of matching items as choices.

Really? I tried this, and noticed you still have to enter the * before
the [tab].

The difference to noglobcomplete seems to be that now you can actually
choose a file via completion, whereas before it just pushed everything
onto the commandline.

- René


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

* Re: Recursive Completition
  2012-08-20  8:57       ` Peter Stephenson
@ 2012-08-20 15:33         ` Bart Schaefer
  2012-08-21 18:27           ` Peter Stephenson
  0 siblings, 1 reply; 10+ messages in thread
From: Bart Schaefer @ 2012-08-20 15:33 UTC (permalink / raw)
  To: zsh-users

On Aug 20,  9:57am, Peter Stephenson wrote:
}
} One thing to do might be to change the style to be an array of patterns
} that are matched against the current directory and only use it in that
} case.  So you could set it to "*/.git*".

That's more along the lines of what I was thinking.  Match the pattern
against the whole $PWD string, I presume.


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

* Re: Recursive Completition
  2012-08-20  9:43   ` René Neumann
@ 2012-08-21  4:58     ` Bart Schaefer
  0 siblings, 0 replies; 10+ messages in thread
From: Bart Schaefer @ 2012-08-21  4:58 UTC (permalink / raw)
  To: zsh-users

On Aug 20, 11:43am, René Neumann wrote:
} Subject: Re: Recursive Completition
}
} Am 19.08.2012 02:18, schrieb Bart Schaefer:
} > setopt globcomplete
} > 
} > Now when you try
} > 
} > ls **/Kern[tab]
} > 
} > the completion system behaves as if you'd inserted a * just before [tab],
} > and offers you the list of matching items as choices.
} 
} Really? I tried this, and noticed you still have to enter the * before
} the [tab].

Hmm, interesting.  I didn't try it for a sufficiently deep directory
hierarchy.  Completion seems to treat **/ as just */ -- only expansion
does the full recursive thing.

Looking more closely, completion splits **/Kern into "**" and "Kern" and
tries to find completions for ** first.  Because the slash has been
removed, ** loses its special meaning.

So it really does need somethng like PWS's recent proposed patch.  Or else
further surgery to _path_files, which is already a bit of a Frankenstein's
monster.


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

* Re: Recursive Completition
  2012-08-20 15:33         ` Bart Schaefer
@ 2012-08-21 18:27           ` Peter Stephenson
  2012-12-04  2:13             ` Karoly Negyesi
  0 siblings, 1 reply; 10+ messages in thread
From: Peter Stephenson @ 2012-08-21 18:27 UTC (permalink / raw)
  To: zsh-users

Here's a second version with documentation.

Index: Completion/Unix/Type/_files
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_files,v
retrieving revision 1.13
diff -p -u -r1.13 _files
--- Completion/Unix/Type/_files	19 Mar 2010 16:38:26 -0000	1.13
+++ Completion/Unix/Type/_files	21 Aug 2012 18:24:15 -0000
@@ -1,7 +1,7 @@
 #compdef -redirect-,-default-,-default-
 
 local opts tmp glob pat pats expl tag i def descr end ign ret=1 match tried
-local type sdef ignvars ignvar
+local type sdef ignvars ignvar prepath oprefix rfiles rfile
 
 zparseopts -a opts \
     '/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
@@ -118,7 +118,21 @@ for def in "$pats[@]"; do
       while _next_label "$tag" expl "$descr"; do
         _comp_ignore=( $_comp_ignore $ign )
         if [[ -n "$end" ]]; then
-          _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
+          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
+		for prepath in **/*(/); do
+		  oprefix=$PREFIX
+		  PREFIX=$prepath/$PREFIX
+		  _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
+		  PREFIX=$oprefix
+		done
+		break
+	      fi
+	    done
+	  fi
         else
           _path_files "$expl[@]" -g "$pat" "$opts[@]" && ret=0
         fi
Index: Doc/Zsh/compsys.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v
retrieving revision 1.247
diff -p -u -r1.247 compsys.yo
--- Doc/Zsh/compsys.yo	14 Feb 2012 17:01:17 -0000	1.247
+++ Doc/Zsh/compsys.yo	21 Aug 2012 18:24:15 -0000
@@ -2355,6 +2355,28 @@ found, or var(max) words have been tried
 
 The default is to complete all words from the history at once.
 )
+kindex(recursive-files, completion style)
+item(tt(recursive-files))(
+If this style is set, its value is an array of patterns to be
+tested against `tt($PWD/)': note the trailing slash, which allows
+directories in the pattern to be delimited unambiguously by including
+slashes on both sides.  If an ordinary file completion fails
+and the word on the command line does not yet have a directory part to its
+name, the style is retrieved using the same tag as for the completion
+just attempted, then the elements tested against tt($PWD/) in turn.
+If one matches, then the shell reattempts completion by prepending the word
+on the command line with each directory in the expansion of tt(**/*(/))
+in turn.  Typically the elements of the style will be set to restrict
+the number of directories beneath the current one to a manageable
+number, for example `tt(*/.git/*)'.
+
+For example,
+
+example(zstyle ':completion:*' recursive-files '*/zsh/*')
+
+If the current directory is tt(/home/pws/zsh/Src), then
+tt(zle_tr)em(TAB) can be completed to tt(Zle/zle_tricky.c).
+)
 kindex(regular, completion style)
 item(tt(regular))(
 This style is used by the tt(_expand_alias) completer and bindable 

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


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

* Re: Recursive Completition
  2012-08-21 18:27           ` Peter Stephenson
@ 2012-12-04  2:13             ` Karoly Negyesi
  0 siblings, 0 replies; 10+ messages in thread
From: Karoly Negyesi @ 2012-12-04  2:13 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-users

Sorry for not getting back to you sooner on this but I wanted to say a
big thanks because it works!

On Tue, Aug 21, 2012 at 11:27 AM, Peter Stephenson
<p.w.stephenson@ntlworld.com> wrote:
> Here's a second version with documentation.
>
> Index: Completion/Unix/Type/_files
> ===================================================================
> RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_files,v
> retrieving revision 1.13
> diff -p -u -r1.13 _files
> --- Completion/Unix/Type/_files 19 Mar 2010 16:38:26 -0000      1.13
> +++ Completion/Unix/Type/_files 21 Aug 2012 18:24:15 -0000
> @@ -1,7 +1,7 @@
>  #compdef -redirect-,-default-,-default-
>
>  local opts tmp glob pat pats expl tag i def descr end ign ret=1 match tried
> -local type sdef ignvars ignvar
> +local type sdef ignvars ignvar prepath oprefix rfiles rfile
>
>  zparseopts -a opts \
>      '/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
> @@ -118,7 +118,21 @@ for def in "$pats[@]"; do
>        while _next_label "$tag" expl "$descr"; do
>          _comp_ignore=( $_comp_ignore $ign )
>          if [[ -n "$end" ]]; then
> -          _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
> +          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
> +               for prepath in **/*(/); do
> +                 oprefix=$PREFIX
> +                 PREFIX=$prepath/$PREFIX
> +                 _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
> +                 PREFIX=$oprefix
> +               done
> +               break
> +             fi
> +           done
> +         fi
>          else
>            _path_files "$expl[@]" -g "$pat" "$opts[@]" && ret=0
>          fi
> Index: Doc/Zsh/compsys.yo
> ===================================================================
> RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v
> retrieving revision 1.247
> diff -p -u -r1.247 compsys.yo
> --- Doc/Zsh/compsys.yo  14 Feb 2012 17:01:17 -0000      1.247
> +++ Doc/Zsh/compsys.yo  21 Aug 2012 18:24:15 -0000
> @@ -2355,6 +2355,28 @@ found, or var(max) words have been tried
>
>  The default is to complete all words from the history at once.
>  )
> +kindex(recursive-files, completion style)
> +item(tt(recursive-files))(
> +If this style is set, its value is an array of patterns to be
> +tested against `tt($PWD/)': note the trailing slash, which allows
> +directories in the pattern to be delimited unambiguously by including
> +slashes on both sides.  If an ordinary file completion fails
> +and the word on the command line does not yet have a directory part to its
> +name, the style is retrieved using the same tag as for the completion
> +just attempted, then the elements tested against tt($PWD/) in turn.
> +If one matches, then the shell reattempts completion by prepending the word
> +on the command line with each directory in the expansion of tt(**/*(/))
> +in turn.  Typically the elements of the style will be set to restrict
> +the number of directories beneath the current one to a manageable
> +number, for example `tt(*/.git/*)'.
> +
> +For example,
> +
> +example(zstyle ':completion:*' recursive-files '*/zsh/*')
> +
> +If the current directory is tt(/home/pws/zsh/Src), then
> +tt(zle_tr)em(TAB) can be completed to tt(Zle/zle_tricky.c).
> +)
>  kindex(regular, completion style)
>  item(tt(regular))(
>  This style is used by the tt(_expand_alias) completer and bindable
>
> --
> Peter Stephenson <p.w.stephenson@ntlworld.com>
> Web page now at http://homepage.ntlworld.com/p.w.stephenson/


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

end of thread, other threads:[~2012-12-04  2:44 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-18 21:09 Recursive Completition Karoly Negyesi
2012-08-19  0:18 ` Bart Schaefer
2012-08-19 19:44   ` Peter Stephenson
2012-08-19 21:07     ` Karoly Negyesi
2012-08-20  8:57       ` Peter Stephenson
2012-08-20 15:33         ` Bart Schaefer
2012-08-21 18:27           ` Peter Stephenson
2012-12-04  2:13             ` Karoly Negyesi
2012-08-20  9:43   ` René Neumann
2012-08-21  4:58     ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).