zsh-users
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: ml@kybu.org, Zsh Users <zsh-users@zsh.org>
Subject: Re: Menu completion on empty line
Date: Sat, 5 Nov 2016 19:01:50 -0700	[thread overview]
Message-ID: <161105190150.ZM1605@torch.brasslantern.com> (raw)
In-Reply-To: <20161103071706.GA24640@kybu.org>

On Nov 3,  7:17am, ml@kybu.org 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


  reply	other threads:[~2016-11-06  2:01 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-03  7:17 ml
2016-11-06  2:01 ` Bart Schaefer [this message]
2016-11-07  6:22   ` ml
     [not found] ` <161105190150.ZM1605__20581.2434120618$1478397817$gmane$org@torch.brasslantern.com>
2016-11-06  3:15   ` Daniel Shahaf
2016-11-06  3:41     ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=161105190150.ZM1605@torch.brasslantern.com \
    --to=schaefer@brasslantern.com \
    --cc=ml@kybu.org \
    --cc=zsh-users@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).