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

Re: need completion help....

On Apr 17,  4:51pm, Timothy J Luoma wrote:
: Subject: need completion help....
: I don't understand completion at all.

You probably aren't alone.

: mva will move files from the directory $asub
: 	BUT it needs to ignore any files which begin with
: 		the letters "README" (all in capitals, may not be
: 		any more letters than just "README" or can be
: 		any length after that
: 	   AND files named 'files.html' and 'index'		
: but the problem is that I want to use the command like this:
: mva [tab here to get files in $asub] ../[tab here to get list of directories 
: 	in parent directory, which will always be the contents of the
: 	folder $new]

I'm going to ignore $new and ../, and just deal with one of the arguments
giving the name of a directory.

One way to reason about this is as follows:

You have a command (mva) that needs to complete in two different ways --
(1) relative to $asub and (2) relative to a directory prefix you supply
on the command line.

The simple built-in complctl options are able to complete only one way
(per option, of course).  That is, if you use only simple compctls, all
the options are tried for whatever word the cursor is on, no matter what
that word "looks like"; but you need different options to be tried on
different words.

So you need to either (a) use a function with -K that will figure out
which of the two cases is appropriate, or (b) use extended completion.
(With the new completion patches for 3.1.5, there are more ways to use
a function, but it still comes down to either a function or extended

Extended completion is appropriate if the rules for determining which
way to complete can be expressed as simple patterns.  In the case you
describe, the rules might be something like "if the current word has a
slash in it, complete directories using the word so far as the path to
those directories; otherwise complete files in $asub".  The first part
is easily expressed in extended completion patterns; but there's no way
to expand $asub at completion time except with a function, so you're
going to have to have a -K function anyway.  So it's a toss-up in this
case whether you want to try extended completion (unless $asub never
changes during a shell session).

Supposing you want to try extended completion, it would look something
like this (3.0.5 syntax):

    compctl -K asubfiles -x 'C[0,*/*]' -g '*(D/)' -- mva

(In 3.1.4+, use -/ instead of -g '*(D/)', for better results.)

The part before the -x is what's tried if none of the patterns after
the -x match the current line.  The C[0,*/*] means "count 0 words from
the current word, and then compare the word you get to */*".  If that
pattern matches, -g means use a glob pattern (which is attached to the
end of the selected word), and *(D/) means match directories including
those whose names begin with a dot.

Now, what about the asubfiles function?

: OK, here's what I have:
: function asubfiles ()
: {
:     reply=( $(/bin/ls $asub |\
:                 egrep -v "README*|files.html|index") )
: }

That actually would probably work OK, though you might want "/bin/ls -1"
(that's "dash one") to be sure there's only one file per line.  However,
it might be better to do the whole thing with globbing like so:

    function asubfiles ()
	setopt localoptions extendedglob nocshnullglob nullglob
	reply=( $asub/*~*/(README*|files.html|index) )
	reply=( $reply:t )

You need extendedglob to get the ~ in the middle to mean "discard any
file names that match the following pattern".  The other two options
are just to prevent "no match" errors in case $asub is empty.

: compctl -K asubfiles  'S[-]' -- mva

I'm not sure what you were trying to do here ... I think there should be
a -x in front of 'S[-]' and something between 'S[-]' and --, but from
what you told us I don't know what goes there.  Does mva have any command
line options?

: Sorry for being unclear.

No problem.

Oh, supposing you had wanted to try this only with -K, you'd need to do
the pattern matching of the command line words in asubfiles, like this:

    function asubfiles ()
	setopt localoptions extendedglob nocshnullglob nullglob
	case $1$2 in
	*/*) reply=( ${1}*${2}(D/) );;
	*)  reply=( $asub/*~*/(README*|files.html|index) )
	    reply=( $reply:t );;
    compctl -K asubfiles mva

The $1$2 and ${1}*${2} stuff are to handle completeinword, in case you
have that option set.

The drawback to this is that the completion system doesn't "know" (as
it does with -x ... -g) that the strings returned in $reply in the */*
case are directories; so it won't append a trailing slash and place the
cursor where you can continue completing subdirectories.  Maybe that's
actually the behavior you want, though.

One of the new completion gizmos in the latest 3.1.5 patches is the
ability to tell the completion system that you're returning directory
names, so that it will do the right thing with the trailing slash and
the cursor position.

Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

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