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

Re: java class names completion widget



Konstantin Sobolev wrote:
> kos@kos ~/work/jrs/src $ fcl SHMa
> ./org/kos/jrs/SoftHashMap.java
> 
> Now I want to convert it into a completion widget. What is the easiest way to
> do it?

(I'm going to assume you're already using the new completion system,
which seems to be the case.)

You can actually do the case matching element within zsh without any new
code; the difficult bit is the combination of completion and finding
files, but that's difficult to hook in to completion regardless of
whether the expansion is done inside or outside the shell.  Here's how
you do the basic completion (given the problems this probably isn't what
you want, so I'll look at another method later).  The following adds the
smash case completion to the context after javac:

zstyle ':completion:*:javac:*' matcher 'r:|[A-Z]=* r:|=*'

This means roughly "allow all capital letters on the command line to be
followed immediately on the right by any pattern in trial completions,
and allow the end of the string on the command line to be followed by
any pattern in trial completions".  More complicated variants are
possible and are described for this very case in the zshcompwid manual
page (under MATCHING CONTROL).

You can also change the context where this is applied; this is described
under COMPLETION SYSTEM CONFIGURATION in the zshcompsys manual page.

This allows "javac SHMa" to complete to "javac SoftHashMap.java", but it
doesn't handle path searching.  You can, however, do

javac ./o/k/j/SHMa<TAB>

since path elements are completed, but you can't do a general search
that I know of.


So let's concentrate on the search element.  This is more difficult,
because zsh usually separates expansion and completion.  So if you have
the _expand completer in use,

javac **/*.java

would expand to all .java files in subdirectories, but

javac **/SHMa

wouldn't do anything, because the matching control isn't applied to
expansions.


So instead let's hijack the _expand completer and provide a front end.
The trouble with making this the normal contextual completer in place of
_java is that you'll lose all the features of that and need to merge
together what you want.  Hence what I suggest you do is use a separate
completion when you want the special behaviour.  Then you'll have to
remember to type a different key sequence for this, say C-x j.

Here's the full code; put it in a file (say _expand_java_path) in your
function path:

#compdef -k complete-word ^xj
local MATCH MBEGIN MEND
# Turn the start of the string on the line into **/ followed
# by the original prefix with upper case letters followed
# by [^[:upper:]]# which matches any number of consecutive
# non-upper-case characters.  This relies on the fact that
# the completion system uses the EXTENDED_GLOB option.
PREFIX="**/${PREFIX//(#m)[[:upper:]]/${MATCH}[^[:upper:]]#}"
# Replace the end of the string similarly, adding *.java to
# the pattern
SUFFIX="${SUFFIX//(#m)[[:upper:]]/${MATCH}[^[:upper:]]#}*.java"
# Now we've got a zsh recursive matching pattern; for example
#   SHMa
# has turned into
#   **/S[^[:upper:]]#H[^[:upper:]]#M[^[:upper:]]#a*.java
# Let the normal _expand completer get to work.
_expand "$@"

(Four lines of active code for the whole thing!)

Those are the basics; there are many, many possible bells and whistles
since all the features of the completion system are available for
offering you matches, and actually the _expand completer does a bit to
much work for us; we just want the globbing effect.

In particular, the behaviour with ambiguous expansions could be better
configured.  _expand turns on menu completion when inserting.  Currently
it will cycle through possible expansions, then all expansions, then the
original pattern (though it's not the original, it's the hacked version
from _expand_java_path so isn't much use).  You can use the tag-order
style to help.

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php



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