From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22925 invoked by alias); 15 Feb 2014 22:50:53 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 18464 Received: (qmail 18018 invoked from network); 15 Feb 2014 22:50:38 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 From: Bart Schaefer Message-id: <140215145044.ZM2126@torch.brasslantern.com> Date: Sat, 15 Feb 2014 14:50:44 -0800 In-reply-to: <20140215101647.GA17993@ramirez.u-strasbg.fr> Comments: In reply to Marc Chantreux "Re: namespace completions ?" (Feb 15, 11:16am) References: <20140213100333.GA24676@ramirez.u-strasbg.fr> <17317.1392422100@thecus.kiddle.eu> <140214182721.ZM10355@torch.brasslantern.com> <20140215101647.GA17993@ramirez.u-strasbg.fr> X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-users@zsh.org Subject: Re: namespace completions ? MIME-version: 1.0 Content-type: text/plain; charset=us-ascii 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: :completion:expand-word:expand:-command-:: (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 \ all-expansions 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.