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

Re: Menu completion on empty line



Amazing, thank you. I will try it out.

On Sat, Nov 05, 2016 at 07:01:50PM -0700, Bart Schaefer wrote:
> On Nov 3,  7:17am, ml@xxxxxxxx wrote:
> }
> } If I press the tab key on an empty line and I am in a build directory,
> } which can be detected by a presence of, let's say the makefile file,
> } it would be useful to get a menu with items: clean build rebuild. I
> } could use the tab key to move around these items. If I choose one, it
> } would expand to a particular command, like 'make clean'.
> 
> As a prelude, there are two problems with this.
> 
> (1) Completion is VERY single-word-oriented.  Anything that completes to
> something with spaces in it is going to be quoted by default, so you have
> to jump through even more hoops than usual to make it work.
> 
> I would recommend avoiding this by creating three aliases
>     alias clean='make clean'
>     alias build='make all'
>     alias rebuild='clean;build'
> and then use the menu to select those aliases.
> 
> (2) By default TAB doesn't do anything on an empty command line except
> insert itself.  To fix that, you need:
> 
>     zstyle ':completion::*' insert-tab 'pending=1'
> 
> With that out of the way ...
> 
> There are two approaches here:  Change the widget invoked by the TAB
> key, or change the handling for the context of an empty line.  The
> former would let you do the hoop-jumping to insert multiple words as
> the completion, but the latter is probably what you want to do.
> 
> To get started, note that with compinit loaded you can always type
> control-x h to get a description of the current context.  If you do
> that on a blank line, you get:
> 
> tags in context :completion::complete:-command-::
>     commands builtins functions aliases suffix-aliases reserved-words jobs parameters  (_command_names _autocd) 
>     commands
> 	(_path_commands _command_names _autocd) 
>     jobs
> 	(_jobs _command_names _autocd) 
>     parameters
> 	(_parameters _command_names _autocd)
> 
> This is telling you that:
> * the start of an empty line is the special "-command-" context;
> * there are eight tags recognized in this context; 
> * there are five completion functions that may supply candidate
>   completions for these tags, and which functions use which tags.
> 
> The important thing in this case is that you would want to change the
> handling of the -command- context.  Here again you have two choices:
> Replace the default completion function for -command-, or augment
> one of the existing tags.
> 
> I'll note at this point that your three aliases show up in the "aliases"
> tag automatically, and if that were good enough we just stop here.  But
> you want special handling if there's a makefile, so on we go.
> 
> There is an example in the documentation of supplementing a context.
> It's found under the fake-always style and discusses the context of the
> "cd" command.  We need to change it to the context we care about.
> 
>     # Create a preferred aliases-make tag for build commands
>     zstyle ':completion::*:-command-::' \
> 	tag-order 'aliases:-make:"build\ commands"' '*'
> 
> The "*" there in place of "complete" makes this work for other completers,
> though that's not strictly necessary.  The additional '*' in the style
> definition means that if there is something on the line and it does not
> match one of those three aliases, you'll get normal completion.  Next:
> 
>     # Ignore everything but our three aliases for make
>     zstyle ':completion::*:-command-:*:aliases-make' \
> 	ignored-patterns '*~(clean|build|rebuild)'
> 
> Now if you press TAB on an empty line, you'll see only your three
> aliases.
> 
> To limit it so this happens only when there is a makefile present, we
> need to use "zstyle -e":
> 
>     # Create a preferred aliases-make tag for build commands
>     # but do so only when there is a makefile in this directory
>     zstyle -e ':completion::*:-command-::' \
> 	tag-order '[[ -f makefile || -f Makefile ]] && 
>                    reply=("aliases:-make:build\ commands" "*")'
> 
> And there you have it.
> 
> 
> 
> -- 
> Barton E. Schaefer



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