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

Re: namespace completions ?

On Feb 15, 11:16am, Marc Chantreux wrote:
} > _expand_command() { _expand_word || _autocd }
} > compdef _expand_command -command-
} > zstyle :completion:expand-word:expand:-command-:: tag-order all-expansions
} > zstyle :completion:expand-word:expand:-command-:: suffix false 
} as always when it comes to completions: 
} http://www.quickmeme.com/img/d6/d6a1143f571184db25f94613edd43b40af6d3a629221aba00d9efdcfef5efd84.jpg

Let's break it down then ...

The compdef function accepts a completion function name and a context
name.  Normally the context is a command, but it may also be one of a
number of special contexts, which for stream-of-consciousness reasons
are described in the manual in the "Autoloaded files" section under
"Completion System".  One of those contexts is "-command-" which means
you're completing the command name itself (so you can't use that name
to look up a completion for its arguments).

As it happens, the default completion function for -command- context
is _autocd.  It'd be nice if "compdef" had an option to display this
but in the meantime you have to know to examine $_comps[-command-] to
find this out.

We know that what we want is to expand a $var reference in the command
context, but _autocd won't do that.  Fortunately there is a provided
function _expand_word that can do it.  So we create a new function:

    _expand_command() { _expand_word || _autocd }

This just says that if _expand_word doesn't work, try the original
default of _autocd.  And then we replace the function for -command-
with our new one:

    compdef _expand_command -command-

This is cheating a little; the _expand_word function is supposed to be
bound to a widget, but it happens to work to call recursively into the
completion system at this point.  This won't work with all such widget
functions, I guessed that this one would and was rewarded.

The _expand_word function sets up its own zstyle context that has
the substring "expand-word" (again this is supposed to be so that you
can tell it was a different widget, but we cheat a little).  It also
call the _expand completer which sets the "expand" substring.  So you
end up with a context that looks like:


(Aside: If all you do is add the _expand completer to your completers
zstyle, the context is never more specific than :completion::expand:::
so you can't restrict this behavior to the -command- context.)

So we need to tell completion that in that context we want parameters
to expand everywhere.  The name of the style controlling that is
"suffix" which really means "peform expansion only in the suffix,
not in any prefix".  So to get expansion to happen in the prefix:

    zstyle :completion:expand-word:expand:-command-:: suffix false

However, that will return two completions, the expansion of $var and
the original unexpanded string.  In this particular case we don't
want to enter menu completion on those two options, we just want to
fail if there is no expansion.  That's controlled by the tag-order
style, which controls both the ordering and the inclusion of tags.
"Tags" are what the completion system calls the various categories
into which the possible completions may be divided.

This example has two useful tags, "all-expansions" and "original".
(There is also an "expansions" tag, but it doesn't do anything if
the all-expansions tag is omitted.)  If we exclude "original" by
leaving it out of the tag-order zstyle, _expand_word returns with a
single completion that is the expansion of $var OR a failure that
falls through to the _autocd default.

    zstyle :completion:expand-word:expand:-command-:: tag-order \

I skipped over how you find out what the tags are.  Normally you'd
just put the cursor in the command word and type ctrl+x h to run
_complete_help.  In this case, though, that sails past _expand_word
and gives only the tags for _autocd.  To actually see the tags for
_expand_word you have to start by clearing the completer style (see
my aside, above) and adding:

    zstyle \* suffix false

Otherwise _expand aborts early, without generating any of its tags
for _complete_help to find.  (This is a case where NOBODY has any
idea what they're doing, I sort of rediscovered it by accident and
then only showed you the answer.)  Anyway, ctrl+x h now says:

    tags in context :completion:expand-word:expand:-command-::
        all-expansions expansions original  (_expand)

Ahh, better; now we know both the specific style to use to replace
the \* and also what tags to use in tag-order.  And we're done.

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