Chapter 4: The mysteries of completion

4.1: What is completion?

`Completion' is where you hit a particular command key (TAB is the standard one) and the shell tries to guess the word you are typing and finish it for you --- a godsend for long file names, in particular, but in zsh there are many, many more possibilities than that.

There is also a related process, `expansion', where the shell sees you have typed something which would be turned by the shell into something else, such as a variable turning into its value ($PWD becomes /home/users/mydir) or a history reference (!! becomes everything on the last command line). In zsh, when you hit TAB it will look to see if there is an expansion to be done; if there is, it does that, otherwise it tries to perform completion. (You can see if the word would be expanded --- not completed --- by TAB by typing \C-x g, which lists expansions.) Expansion is generally fairly intuitive and not under user control; for the rest of the chapter I will discuss completion only.

An elegant completion system appeared in version 4, replacing the old compctl command. This is based on functions called automatically for completion in particular contexts (for example, there is a function called _cd to handle completion for the cd command) and is installed automatically with the shell, so all you need to do, in principal, is to arrange for this to be loaded. Putting `autoload -U compinit; compinit' in your .zshrc should be enough if the system is installed properly.

4.2: What sorts of things can be completed?

The simplest sort is filename completion, mentioned above. Unless you have made special arrangements, as described below, then after you type a command name, anything else you type is assumed by the completion system to be a filename. If you type part of a word and hit TAB, zsh will see if it matches the first part a filename and if it does it will automatically insert the rest.

The other simple type is command completion, which applies (naturally) to the first word on the line. In this case, zsh assumes the word is some command to be executed lying in your $PATH (or something else you can execute, like a builtin command, a function or an alias) and tries to complete that.

However, the new completion system is highly sensitive to context and comes with completions for many UNIX commands. These are automatically loaded when you run compinit as described above. So the real answer to the question `what can be completed?' is `anything where an automated guess is possible'. Just hit TAB and see if the shell manages to guess correctly.

4.3: How does zsh deal with ambiguous completions?

Often there will be more than one possible completion: two files start with the same characters, for example. Zsh has a lot of flexibility for what it does here via its options. The default is for it to beep and completion to stop until you type another character. You can type \C-D to see all the possible completions. (That's assuming you're at the end of the line, otherwise \C-D will delete the next character and you have to use ESC-\C-D.) This can be changed by the following options, among others:

Combinations of these are possible; for example, AUTO_LIST and AUTO_MENU together give an intuitive combination. Note that from version 3.1 LIST_AMBIGUOUS is set by default; if you use autolist, you may well want to `unsetopt listambiguous'.

4.4: How do I complete in the middle of words / just what's before the cursor?

Sometimes you have a word on the command-line which is incomplete in the middle. Normally if you hit tab in zsh, it will simply go to the end of the word and try to complete there. However, there are two ways of changing this.

First, there is the option COMPLETE_IN_WORD. This tries to fill in the word at the point of the cursor. For example, if the current directory contains foobar, then with the option set, you can complete fbar to foobar by moving the cursor to the b and hitting tab.

To complete just what's before the cursor, ignoring anything after, you need the function expand-or-complete-prefix: it works mostly like the usual function bound to tab, but it ignores anything on the right of the cursor. If you always want this behaviour (some other shells do this), bind it to tab; otherwise put another binding, e.g. ^X TAB in ~/.zshrc:

    bindkey "^X^I" expand-or-complete-prefix

The completion system's handling of filenames allows you to complete multiple segments of a path in one go, so for example /u/l/b can expand to /usr/local/bin or anything else that matches. This saves you having to expand the middle part of the path separately.

4.5: How do I get started with programmable completion?

The main resource is the zshcompsys manual page. It's complicated, I'm afraid, far too much to go into here. See also the user guide referred to above, or copy one of the very many existing functions. For a professionally produced guide, see the book `From Bash to Z Shell: Conquering the Command Line' by Oliver Kiddle, Jerry Peek and Peter Stephenson (me), published by Apress, ISBN 1-59059-376-6. Chapter 10 tells you how to configure the completion system and chapter 15 how to write your own completion functions.

4.6: Suppose I want to complete all files during a special completion?

If you're using the completion system the shell will decide what to complete when you hit TAB. That's usually the right thing for the context, but sometimes you just want to complete files, like TAB used to do in the old days. You can set up this up as follows:

    zle -C complete-file complete-word _generic
    zstyle ':completion:complete-file::::' completer _files
    bindkey '^xF' complete-file
This turns the key \C-x F into a command complete-file which goes straight to the completion system's file completion command, ignoring the normal context. Change the binding how you like.

Note the way the form of completion to use is specified by picking a `completer' called `_files'. You can define any completion to be bound to a keystroke by putting the appropriate completion function at that point. Then change all occurrences of `complete-file' to a name of your own.

If you simply want to try filename completion as a default when other completions fail, add it to the `completer' style for normal completion, for example:

    zstyle ':completion:*' completer _complete _ignored _files
This adds filename completion to the end of the default types of completion. Your actual completer style may include other actions, such as expansion or approximate completion.