ZSH Completion

zsh themes - all about z shell and oh-my-zsh themes All themes into Oh my themes for zsh (z shell) review and screenshoots

 

Completion of command arguments is something zsh is particularly good at. The simplest case is that you hit , and the shell guesses what has to go there and fills it in for you:

 % ls myfile theirfile yourfile % cat t 

expands the command line to

 % cat theirfile 

and you only had to type the initial letter, then TAB.

In the early days when this feature appeared in the C shell, only filenames could be completed; there were no clever tricks to help you if the name was ambiguous, it simply printed the unambiguous part and beeped so that you had to decide what to do next. You could also list possible completions; for some reason this became attached to the ^D key in csh, which in later shells with Emacs-like bindings also deletes the next character, so that history has endowed zsh, like other shells, with the slightly odd combined behaviour:

 % cat yx 

Now move the cursor back one character onto the x and hit ^D twice and you see: yourfile. That doesn't work if you use vi-like bindings, or, obviously, if you've rebound ^D.

Next, it became possible to complete other items such as names of users, commands or hosts. Then zsh weighed in with menu completion, so you could keep on blindly hitting  until the right answer appeared, and never had to type an extra character yourself.

The next development was tcsh's, and then zsh's, programmable completion system; you could give instructions to the shell that in certain contexts, only certain items should be completed; for example, after cd, you would only want directories. In tcsh, there was a command called complete; each 'complete ...' statement defined the completion for the arguments of a particular command, such as cd; the equivalent in zsh is compctl, which was inspired by complete but is different in virtually every significant detail. There is a perl script lete2ctl in the Misc directory of the shell distribution to help you convert from the tcsh to the zsh formats. You put a whole series of compctl commands into .zshrc, and everything else is done by the shell.

Zsh's system has become more and more sophisticated, and in version 3.1.6 a new completion system appeared which is supposed to do everything for you: you simply call a function, compinit, from an initialization file, after which zsh knows, for example, that gunzip should be followed by files ending in .gz. The new system is based on shell functions, an added bonus since they are extremely flexible and you already know the syntax. However, given the complexity it's quite difficult to get started writing your own completions now, and hard enough to know what to do to change the settings the way you like. The rest of the chapter should help.

I shall concentrate on the new completion system, which seems destined to take over completely from the old one eventually, now that the 3.1 release series has become the 4.0 production release. The old compctl command is still available, and old completion definitions will remain working in future versions of zsh --- in fact, on most operating systems which support dynamically linked libraries the old completion system is in a different file, which the shell loads when necessary, so there's very little overhead for this.

The big difference in the new system is that, instead of everything being set up once and for all when the shell starts, various bits of shell code are called after you hit , to generate the completions there and then. There's enough new in the shell that all those unmemorable options to compctl ('-f' for files '-v' for variables and so on) can be replaced by commands that produce the list of completions directly; the key command in this case is called 'compadd', which is passed this list and decides what to use to complete the word on the command line. So the simplest possible form of new completion looks roughly like this:

 # tell the shell that the function mycompletion can do completion # when called by the widget name my-completion-widget, and that # it behaves like the existing widget complete-word zle -C my-completion-widget .complete-word mycompletion # define a key that calls the completion widget bindkey '^x^i' my-completion-widget # define the function that will be called mycompletion() { # add a list of completions compadd alpha bravo charlie delta } 

That's very roughly what the completion system is doing, except that the function is called _main_complete and calls a lot of other functions to do its dirty work based on the context where completion was called (all the things that compctl used to do), and the widgets are just the old completion widgets ('expand-or-complete' etc.) redefined and still bound to all the original keys. But, in case you hadn't guessed, there's more to it than that.

Here's a plan for the sections of this chapter.

  1. A broad description of completion and expansion, applying equally to old and new completion.
  2. How to configure completion using shell options. Most of this section applies to old completion, too, although I won't explicitly flag up any differences. After this, I shall leave the compctl world behind.
  3. How to start up new completion.
  4. The basics of how the new completion system works.
  5. How to configure it using the new 'zstyle' builtin.
  6. Separate commands which do something other than the usual completion system, as well as some other editing widgets that have to do with completion.
  7. Matching control, a powerful way of deciding such things as whether to complete case-insensitively, to allow insertion of extra parts of words before punctuation characters, or to ignore certain characters in the word on the command line.
  8. How to write your own completion functions; you won't need to have too solid an understanding of all the foregoing just to do simple completions, but I will gradually introduce the full baroque splendour of how to make tags and styles work in your own functions, and how to make completion do the work of handling command arguments and options.
  9. Ends the chapter gracefully, on the old 'beginning, middle, end' principle.

6.1: Completion and expansion

More things than just completion happen when you hit tab. The first thing that zsh tries to do is expand the line. Expansion was covered in a previous chapter: basically all the things described there are possible candidates for expanding in-line by the editor. In other words, history substitutions with bangs, the various expansions using '$' or backquote, and filename generation (globbing) can all take place, with the result replacing what was there on the command line:

 % echo $PWD -> echo /home/pws/zsh/projects/zshguide % echo 'print $ZSH_VERSION' -> echo 3.1.7 % echo !! -> echo echo 3.1.7 % echo ~/.z* -> echo /home/pws/.zcompdump /home/pws/.zlogout /home/pws/.zshenv /home/pws/.zshrc 

Note that the '~' also gets expanded in this case.

This is often a good time to remember the 'undo' key, '^_' or '^Xu'; typing this will restore what was there before the expansion if you don't like the result. Many keyboards have a quirk that what's described as '^_' should be typed as control with slash, which you'd write '^/' except unfortunately that does something else; this is not zsh's fault. There's another half-exception, namely filename generation: paths like '~/file' don't get expanded, because you usually know what they refer to and it's usually convenient to leave them for use in completion. However, the '=cmdname' form does get expanded, unless you have NO_EQUALS set.

In fact, deciding whether expansion or completion takes place can sometimes be tricky, since things that would be expanded if they were complete, may need to be completed first; for example $PAT should probably be completed to $PATH, but it's quite possible there is a parameter $PAT too. You can decide which, if you prefer. First, the commands expand-word, bound to '^X*', and the corresponding command for listing what would be expanded, list-expand, bound to '^Xg', do expansion only --- all possible forms except alias expansion, including turning '~/file' into a full path.

From the other point of view, you can use commands other than expand-or-complete, the one bound by default to , to perform only completion. The basic command for this is complete-word, which is not bound by default. It is quite sensible to bind this to '^I' (i.e. ) if you are happy to use the separate commands for expansion, i.e.

 # Now tab does only completion, not expansion bindkey '^i' complete-word 

Furthermore, if you do this and use the new completion system, then as we shall see there is a way of making the completion system perform expansion --- see the description of the _expand completer below. In this case you have much more control over what forms of expansion are tried, and at what point, but you have to make sure you use complete-word, not expand-or-complete, else the standard expansion system will take over.

There's a close relative of expand-or-completeexpand-or-complete-prefix, not bound by default. The only difference is that it will ignore everything under and to the right of the cursor when completing. It's as if there was a space where the cursor was, with everything to be ignored shifted to the right (guess how it's implemented). Use this if you habitually type new words in the line before other words, and expect them to complete or expand on their own even before you've typed the space after them. Some other shells work this way all the time. To be more explicit:

 % ls filename1 % ls filex 

Move the cursor to the x and hit tab. With expand-or-complete nothing happens; it's trying to complete a file called 'filex' --- or, with the option COMPLETE_IN_WORD set, it's trying to find a file whose name starts with 'file' and ends with 'x'. If you do

 bindkey '^i' expand-or-complete-prefix 

and try the same experiment, you will find the whole thing is completed to 'filename1x', so that the 'x' was ignored, but not removed.

One possible trap is that the listing commands, both delete-char-or-list, bound by default to '^D' in emacs mode, and list-options, bound by default to '^D' in vi insert mode and the basic command for listing completions as it doesn't have the delete-character behaviour, do not show possible expansions, so with the default bindings you can use '^D' to list, then hit  and find that the line has been completely rewritten by some expansion. Using complete-word instead of expand-or-complete will of course fix this. If you know how to write new editor widgets (chapter 4), you can make up a function which tries list-expand, and if that fails tries list-options.

There are four completion commands I haven't mentioned yet: three are menu-completemenu-expand-or-complete and reverse-menu-complete, which perform menu completion, where you can cycle through all possible completions by hitting the same key. The first two correspond to complete-word and expand-or-complete respectively, while the third has no real equivalent as it takes you backwards through a completion list. The effect of the third can't be reached just by setting options for menu completion, so it's a useful one to bind separately. I have it bound to '\M-\C-i', i.e. tab with the Meta key pressed down, but it's not bound by default.

The fourth is menu-select, which performs an enhanced form of menu completion called 'menu selection' which I'll describe below when I talk about options. You have to make sure the zsh/complist module is loaded to use this zle command. If you use the style, zsh should be able to load this automatically when needed, as long as you have dynamic loading, which you probably do these days.

6.2: Configuring completion using shell options

There are two main ways of altering the behaviour of completion without writing or rewriting shell functions: shell options, as introduced in chapter 2, and styles, as introduced above. I shall first discuss the shell options, although as you will see some of these refer to the styles mechanism. Setting shell options affects every single completion, unless special care has been taken (using a corresponding style for the context, or setting an option locally) to avoid that.

In addition to the options which directly affect the completion system, completion is sensitive to various other options which describe shell behaviour. For example, if the option MAGIC_EQUAL_SUBST is set, so that arguments of all commands looking like 'foo=~/file' have the '~' expanded as if it was at the start of an argument, then the default completion for arguments of commands not specially handled will try to complete filenames after the '='.

Needless to say, if you write completion functions you will need to worry about a lot of other options which can affect shell syntax. The main starting point for completion chosen by context (everything except the commands for particular completions bound separately to keystrokes) is the function _main_complete, which includes the effect of the following lines to make sure that at least the basic options are set up within completion functions:

 setopt glob bareglobqual nullglob rcexpandparam extendedglob unset unsetopt markdirs globsubst shwordsplit shglob ksharrays cshnullglob unsetopt allexport aliases errexit octalzeroes 

but that by no means exhausts the possibilities. Actually, it doesn't include those lines: the options to set are stored in the array $_comp_options, with NO_ in front if they are to be turned off. You can modify this if you find you need to (and maybe tell the maintainers, too).

By the way, if you are wondering whether you can re-use the function _main_complete, by binding it to a different key with slightly different completion definitions, look instead at the description of the _generic command widget below. It's just a front-end to _main_complete which allows you to have a different set of styles in effect.

6.2.1: Ambiguous completions

The largest group of options deals with what happens when a completion is ambiguous, in other words there is more than one possible completion. The seven relevant options are as follows, as copied from the FAQ; many different combinations are possible:

  • with NO_BEEP set, that annoying beep goes away,
  • with NO_LIST_BEEP, beeping is only turned off for ambiguous completions,
  • with AUTO_LIST set, when the completion is ambiguous you get a list without having to type ^D,
  • with BASH_AUTO_LIST set, the list only happens the second time you hit tab on an ambiguous completion,
  • with LIST_AMBIGUOUS, this is modified so that nothing is listed if there is an unambiguous prefix or suffix to be inserted --- this can be combined with BASH_AUTO_LIST, so that where both are applicable you need to hit tab three times for a listing,
  • with REC_EXACT, if the string on the command line exactly matches one of the possible completions, it is accepted, even if there is another completion (i.e. that string with something else added) that also matches,
  • with MENU_COMPLETE set, one completion is always inserted completely, then when you hit TAB it changes to the next, and so on until you get back to where you started,
  • with AUTO_MENU, you only get the menu behaviour when you hit TAB again on the ambiguous completion.

6.2.2: ALWAYS_LAST_PROMPT

The option ALWAYS_LAST_PROMPT is set by default, and has been since an earlier 3.1 release of zsh; after listing a completion, the cursor is taken back to the line it was on before, instead of reprinting it underneath. The downside of this is that the listing will be obscured when you execute the command or produce a different listing, so you may want to unset the option. ALWAYS_LAST_PROMPT behaviour is required for menu selection to work, which is why I mention it now instead of in the ragbag below.

When you're writing your own editor functions which invoke completion, you can actually cancel the effect of this with the widget end-of-list, which you would call as zle end-of-list (it's a normal editing function, not a completion function). You can also bind it to a key to use to preserve the existing completion list. On the other hand, if you want to control the behaviour within a completion function, i.e. to decide whether completion will try to return to the prompt above the list, you can manipulate it with the last_prompt element of the $compstate associative array, so for example:

 compstate[last_prompt]='' 

will turn off the behaviour for the completion in progress. $compstate is the place to turn if you find yourself wanting to control completion behaviour in this much detail; see the zshcompwid manual page.

6.2.3: Menu completion and menu selection

The most significant matter decided by the options above is whether or not you are using menu completion. If you are not, you will need to type the next character explicitly when completion is ambiguous; if you are, you just need to keep hitting tab until the completion you want appears. In the second case, of course, this works best if there are not too many possibilities. Use of AUTO_MENU or binding the menu-complete widget to a separate key-stroke gives you something of both worlds.

A new variant of menu completion appeared in 3.1.6; in fact, it deserves the name menu completion rather more than the original form, but since that name was taken it is called 'menu selection'. This allows you to move the cursor around the list of completions to select one. It is implemented by a separate module, zsh/complist; you can make sure this is loaded by putting 'zmodload -i zsh/complist' in .zshrc, although it should be loaded automatically when the style menu is set as below. For it to be useful, you need two other things. The first is ALWAYS_LAST_PROMPT behaviour; this is suppressed if the whole completion list won't appear on the screen, since there's no line on the screen to go back to. However, menu selection does still work, by allowing you to scroll the list up and down. The second thing is that you need to start menu completion in any of the usual ways; menu selection is an addition to menu completion, not a replacement.

Now you should set the following style:

 zstyle ':completion:*' menu select= 

If an ambiguous completion produces at least  possibilities, menu selection is started. You can understand this best by trying it. One of the completions in the list, initially the top-leftmost, is highlighted and inserted into the line. By moving the cursor in the obvious directions (with wraparound at the edges), you change both the value highlighted and the value inserted into the line. When you have the value you want, hit return, which removes the list and leaves the inserted value. Hitting ^G (the editor function send-break) aborts menu selection, removes the list and restores the command line.

Internally, zsh actually uses the parameter $MENUSELECT to supply the number and hence start menu selection. However, this is always initialised from the style as defined above, so you shouldn't set $MENUSELECT directly (unless you are using compctl, which will happily use menu selection). As with other styles, you can specify different values for different contexts; the default tag is checked if the current context does not produce a value for the style with whatever the current tag is. Note that the menu style also allows you to control whether menu completion is started at all, with or without selection; in other words, it is a style corresponding to the MENU_COMPLETE option.

There is one other additional feature when using menu selection. The zle command accept-and-infer-next-history has a different meaning here; it accepts a completion, and then tries to complete again using menu selection. This is very useful with directory hierarchies, and in combination with undo gives you a simple file browser. You need to bind it in the special keymap menuselect; for example, I use

 bindkey -M menuselect '^o' accept-and-infer-next-history 

because the behaviour reminds me of what is usually bound to ^O in emacs modes, namely accept-line-and-down-history. Binding it like this has no effect on ^O in the normal keymaps. Try it out by entering menu selection on a set of files including directories, and typing ^O on one of the directories. You should immediately have the contents of that directory presented for the next selection, while undo is smart enough not only to remove that selection but return to completion on the parent directory.

You can choose the manner in which the currently selected value in the completion list is highlighted using exactly the same mechanism as for specifying colours for particular types of matches; see the description of the list-colors style below.

6.2.4: Other ways of changing completion behaviour

COMPLETE_ALIASES

If you set an alias such as

 alias pu=pushd 

then the alias 'pu' will be expanded when the completion system is looking for the name of the command, so that it will instead find the command name 'pushd'. This is quite useful to avoid having to define extra completions for all your aliases. However, it's possible you may want to define something different for the alias than for the command it expands to. In that case, you will need to set COMPLETE_ALIASES, and to make arrangements for completing after every alias which does not already match the name of a command. Hence 'alias zcat="myzcat -dc"' will work with the option set, even if you haven't told the system about 'myzcat', while 'alias myzcat="gzip -dc"' will not work unless you do define a completion for myzcat: here 'compdef _gzip myzcat' would probably be good enough. Without the option set, it would be the other way around: the first alias would not work without the extra compdef, but the second would.

AUTO_REMOVE_SLASH

This option is turned on by default. If you complete a directory name and a slash is added --- which it usually is, both to tell you that you have completed a directory and to allow you to complete files inside it without adding a '/' by hand --- and the next thing you type is not something which would insert or complete part of a file in that directory, then the slash is removed. Hence:

 % rmdir my -> rmdir mydir/ % rmdir mydir/ -> 'rmdir mydir' executed 

This example shows why this behaviour was added: some versions of 'rmdir' baulk at having the slash after the directory name. On the other hand, if you continued typing after the slash, or hit tab again to complete inside mydir, then the slash would remain.

This is at worst harmless under most circumstances. However, you can unset the option AUTO_REMOVE_SLASH if you don't like that behaviour. One thing that may cause slight confusion, although it is the same as with other suffixes (i.e. bits which get added automatically but aren't part of the value being completed), is that the slash is added straight away if the value is being inserted by menu completion. This might cause you to think wrongly that the completion is finished, and hence is unique when in fact it isn't.

Note that some forms of completion have this type of behaviour built in, not necessarily with a slash, when completing lists of arguments. For example, enter 'typeset ZSH_V' and you will see 'ZSH_VERSION=' appear, in case you want to assign something to the parameter; hitting space, which is not a possible value, makes the '=' disappear. This is not controlled by the AUTO_REMOVE_SLASH option, which applies only to directories inserted by the standard filename completion system.

AUTO_PARAM_SLASHAUTO_PARAM_KEYS

These options come into effect when completing expressions with parameter substitutions. If AUTO_PARAM_SLASH is set, then any parameter expression whose value is the name of a directory will have a slash appended when completed, just as if the value itself had been inserted by the completion system.

The behaviour for AUTO_PARAM_KEYS is a bit more complicated. Try this:

 print ${ZSH_V 

You will find that you get the complete word '${ZSH_VERSION}', with the closing brace and (assuming there are no other matching parameters) a space afterwards. However, often after you have completed a parameter in this fashion you want to type something immediately after it, such as a subscript. With AUTO_PARAM_KEYS, if you type something at this point which seems likely to have to go after the parameter name, it will immediately be put there without you having to delete the intervening characters --- try it with '[', for example. Note that this only happens if the parameter name and any extra bits were added by completion; if you type everything by hand, typing '[' will not have this magic effect.

COMPLETE_IN_WORD

If this is set, completion always takes place at the cursor position in the word. For example if you typed 'Mafile', went back over the 'f', and hit tab, the shell would complete 'Makefile', instead of its usual behaviour of going to the end of the word and trying to find a completion there, i.e. something matching 'Mafile*'. Some sorts of new completion (such as filename completion) seem to implement this behaviour regardless of the option setting; some other features (such as the '_prefix' completer described below) require it, so it's a good thing to set and get used to, unless you really need to complete only at the end of the word.

ALWAYS_TO_END

If this is set, the cursor is always moved to the end of the word after it is completed, even if completion took place in the middle. This also happens with menu completion.

6.2.5: Changing the way completions are displayed

LIST_TYPES

This is like the -F option to ls; files which appear in the completion listing have a trailing '/' for a directory, '*' for a regular file executable by the current process, '@' for a link, '|' for a named pipe, '%' for a character device and '#' for a block device. This option is on by default.

Note that the identifiers only appear if the completion system knows that the item is supposed to be a file. This is automatic if the usual filename completion commands are used. There is also an option -f to the builtin compadd if you write your own completion function and want to tell the shell that the values may be existing files to apply LIST_TYPES to (though no harm is caused if no such files exist).

LIST_PACKEDLIST_ROWS_FIRST

These affect the arrangement of the completion listing. With LIST_PACKED, completion lists are made as compact as possible by varying the widths of the columns, instead of formatting them into a completely regular grid. With LIST_ROWS_FIRST, the listing order is changed so that adjacent items appear along rows instead of down columns, rather like ls's -x option.

It is possible to alter both these for particular contexts using the styles list-packed and list-rows-first. The styles in such cases always override the option; the option setting is used if no corresponding style is found.

Note also the discussion of completion groups later on: it is possible to have different types of completion appear in separate lists, which may then be formatted differently using these tag-sensitive styles.

6.3: Getting started with new completion

Before I go into any detail about new completion, here's how to set it up so that you can try it out. As I said above, the basic objects that do completions are shell functions. These are all autoloaded, so the shell needs to know where to find them via the $fpath array. If the shell was installed properly, and nothing in the initialization files has removed the required bits from $fpath, this should happen automatically. It's even possible your system sets up completion for you (Mandrake Linux 6.1 is the first system known to do this out of the box), in which case type 'which compdef' and you should see a complete shell function --- actually the one which allows you to define additional completion functions. Then you can skip the next paragraph.

If you want to load completion, try this at the command line:

 autoload -U compinit compinit 

which should work silently. If not, you need to ask your system administrator what has happened to the completion functions or find them yourself, and then add all the required directories to your $fpath. Either they will all be in one big directory, or in a set of subdirectories with the names AIXBSDBaseDebianRedhatUnixX and Zsh; in the second case, all the directories need to be in $fpath. When this works, you can add the same lines, including any modification of $fpath you needed, to your .zshrc.

You can now see if it's actually working. Type 'cd ', then ^D, and you should be presented with a list of directories only, no regular files. If you have $cdpath set, you may see directories that don't appear with ls. As this suggests, the completion system is supplied with completions for many common (and some quite abstruse) commands. Indeed, the idea is that for most users completion just works without intervention most of the time. If you think it should when it doesn't, it may be a bug or an oversight, and you should report it.

Another example on the theme of 'it just works':

 tar xzf archive.tar.gz ^D 

will look inside the gzipped tar archive --- assuming the GNU version of tar, for which the 'z' in the first set of arguments reports that the archive has been compressed with gzip --- and give you a list of files or directories you can extract. This is done in a very similar way to normal file completion; although there are differences, you can do completion down to any directory depth within the archive. (At this point, you're supposed to be impressed.)

The completion system knows about more than just commands and their arguments, it also understands some of the shell syntax. For example, there's an associative array called $_comps which stores the names of commands as keys and the names of completion functions as the corresponding values. Try typing:

 print ${_comps[ 

and then ^D. You'll probably get a message asking if you really want to see all the possible completions, i.e. the keys for $_comps; if you say 'y' you'll see a list. If you insert any of those keys, then close the braces so you have e.g. '${_comps[mozilla]}' and hit return, you'll see the completion function which handles that command; in this case (at the time of writing) it's _webbrowser. This is one way of finding out what function is handling a particular command. If there is no entry --- i.e. the 'print ${_comps[mycmd]}' gives you a blank line --- then the command is not handled specially and will simply use whatever function is defined for the '-default-' context, usually _default. Usually this will just try to complete file names. You can customize _default, if you like.

Apart from -default-, some other of those keys for _comps also look like -this-: they are special contexts, places other than the arguments of a command. We were using the context called -subscript-; you'll find that the function in this case is called _subscript. Many completion functions have names which are simply an underscore followed by the command or context name, minus any hyphens. If you want a taster of how a completion function looks, try 'which _subscript'; you may well find there are a lot of other commands in there that you don't know yet.

It's important to remember that the function found in this way is at the root of how a completion is performed. No amount of fiddling with options or styles --- the stuff I'm going to be talking about for the next few sections --- will change that; if you want to change the basic completion, you will just have to write your own function.

By the way, you may have old-style completions you want to mix-in --- or maybe you specifically don't want to mix them in so that you can make sure everything is working with the new format. By default, the new completion system will first try to find a specific new-style completion, and if it can't it will try to find a compctl-defined completion for the command in question. If all that fails, it will try the usual new-style default completion, probably just filename completion. Note that specific new-style completions take precedence, which is fair enough, since if you've added them you almost certainly don't want to go back and use the old form. However, if you don't ever want to try old-style completion, you can put the following incantation in your .zshrc:

 zstyle ':completion:*' use-compctl false 

For now, that's just black magic, but later I will explain the 'style' mechanism in more detail and you will see that this fits in with the normal way of turning things off in new-style completion.

6.4: How the shell finds the right completions

6.4.1: Contexts

The examples above show that the completion system is highly context-sensitive, so it's important to know how these contexts are described. This system evolved gradually, but everything I say applies to all versions of zsh with the major version 4.

state we are at in completion, and is given as a sort of colon-separated path, starting with the least specific part. There's an easy way of finding out what context you are in: at the point where you want to complete something, instead type '^Xh', and it will tell you. In the case of the $_comps example, you will find,

 :completion::complete:-subscript-:: 

plus a list of so-called 'tags' and completion functions, which I'll talk about later. The full form is:

 :completion::::: 

where the elements may be missing if they are not set, but the colons will always be there to make pattern matching easier. Here's what the bits of the context mean after the :completion: part, which is common to the whole completion system.

is the name of a function from which completion is called --- this is blank if it was started from the standard completion system, and only appears in a few special cases, listed in section six of this chapter.
is called 'complete' in this case: this refers to the fact that the completion system can do more than just simple completion; for example, it can do a more controlled form of expansion (as I mentioned), spelling correction, and completing words with spelling mistakes. I'll introduce the other completers later; 'complete' is the simplest one, which just does basic completion.
is the name of a command or other similar context as described above, here '-subscript-'.
is most useful when  is the name of a real command; it describes where in the arguments to that command we are. You'll see how it works in a moment. Many of the simpler completions don't use this; only the ones with complicated option and argument combinations. You just have to find out with ^Xh if you need to know.
describes the type of a completion, essentially a way of discriminating between the different things which can be completed at the same point on the command line.

Now look at the context for a more normal command-argument completion, e.g. after cd; here you'll see the context ':completion::complete:cd::'. Here the command-name part of the context is a real command.

For something more complicated, try after 'cvs add' (it doesn't matter for this if you don't have the cvs command). You'll see a long and repetitive list of tags, for two possible contexts,

 :completion::complete:cvs:argument-rest: :completion::complete:cvs-add:argument-rest: 

The reason you have both is that the 'add' is not only an argument to cvs, as the first context would suggest, it's also a subcommand in its own right, with its own arguments, and that's what the second context is for. The first context implies there might be more subcommands after 'add' and its arguments which are completely separate from them --- though in fact CVS doesn't work that way, so that form won't give you any completions here.

In both, 'argument-rest' shows that completion is looking for another argument, the 'rest' indicating that it is the list of arguments at the end of the line; if position were important (see 'cvs import' for an example), the context would contain 'argument-1', or whatever. The 'cvs-add' shows how subcommands are handled, by separating with a hyphen instead of a colon, so as not to confuse the different bits of the context.

Apart from arguments to commands and subcommands, arguments to options are another frequent possibility; for an example of this, try typing ^Xh after 'dvips -o' and you will see the context ':completion::complete:dvips:option-o-1:'; this shows you are completing the first argument to dvips's -o option, (it only takes one argument) which happens to be the name of a file for output.

6.4.2: Tags

Now on to the other matter to do with contexts, tags. Let's go back and look at the output from the ^Xh help test after the cd command in full:

 tags in context :completion::complete:cd:: local-directories path-directories (_alternative _cd) 

Unlike the contexts considered so far, which tell you how completion arrived at the point it did, the tags describe the things it can complete here. In this case, there are three: directory-stack refers to entries such as '+1'; the directory stack is the set of directories defined by using the pushd command, which you can see by using the dirs command. Next, local-directories refers to subdirectories of the current working directory, while path-directories refers to any directories found by searching the $cdpath array. Each of the possible completions which the system offers belongs to one of those classes.

In parentheses, you see the names of the functions which were called to generate the completions; these are what you need to change or replace if you want to alter the basic completion behaviour. Calling functions appear on the right and called functions on the left, so that in this case the function '_cd' was the function first called to handle arguments for the cd command, fitting the usual convention. Some standard completion functions have been filtered out of this list --- it wouldn't help you to know it had been through _main_complete and _complete, for example.

Maybe it's already obvious that having the system treat different types of completion in different ways is useful, but here's an example, which gives you a preview of the 'styles' mechanism, discussed later. Styles are a sort of glorified shell parameter; they are defined with the zstyle command, using a style name and possible values which may be an array; you can always define a style as an array, but some styles may simply use it as a string, joining together the arguments you gave it with spaces. You can also use the zstyle command, with different arguments, to retrieve their value, which is what the completion system itself does; there's no actual overlap with parameters and their values, so they don't get in the way of normal shell programming.

Where styles differ from parameters is that they can take different values in different contexts. The first argument to the zstyle command gives a context; when you define a style, this argument is actually a pattern which will be matched against the current context to see if the style applies. The rule for finding out what applies is: exact string matches are preferred before patterns, and longer patterns are preferred before shorter patterns. Here's that example:

 zstyle ':completion:*:cd:*' tag-order local-directories \ path-directories 

From the discussion of contexts above, the pattern will match any time an argument to the cd command is being completed. The style being set is called tag-order, and the values are the two tags valid for directories in cd.

The tag-order style determines the order in which tags are tried. The value given above means that first local-directories will be completed; only if none can be completed will path-directories be tried. You can enter the command and try this; if you don't have $cdpath set up you can assign 'cdpath=(~)', which will allow 'cd foo' to change to a directory '~/foo' and allow completion of directories accordingly. Go to a directory other than ~; completion for cd will only show subdirectories of where you are, not those of ~, unless you type a string which is the prefix of a directory under ~ but not your current directory. For example,

 % cdpath=(~) % ls -F ~ foo/ bar/ % ls -F rod/ stick/ # Without that tag-order zstyle command, you would get... % cd ^D bar/ foo/ rod/ stick/ % zstyle ':completion:*:cd:*' tag-order local-directories \ path-directories # now you just get the local directories, if there are any... % cd ^D rod/ stick/ 

There's more you can do with the tag-order style: if you put the tags into the same word by quoting, for example "local-directories path-directories", then they would be tried at the same time, which in this case gives you the effect of the default. In fact, since it's too much work to know what tags are going to be available for every single possible completion, the default when there is no appropriate tag-order is simply to try all the tags available in the context at once; this was of course what was originally happening for completion after cd.

Even if there is a tag-order specification, any tags not specified will usually be tried all together at the end, so you could actually have missed out path-directories from the end of the original example and the effect would have been the same. If you don't want that to happen, you can specify a '-' somewhere in the list of tags, which is not used as a tag but tells completion that only the tags in the list should be tried, not any others that may be available. Also, if you don't want a particular tag to be shown you can include '!tagname' in the values, and all the others but this will be included. For example, you may have noticed that when completing in command position you are offered parameters to set as well as commands etc.:

 Completing external command tex texhash texi2pdf text2sf texconfig texi2dvi texindex textmode texdoc texi2dvi4a2ps texlinks texutil texexec texi2html texshow texview Completing parameter TEXINPUTS texinputs 

(I haven't told you how to produce those descriptions, or how to make the completions for different tags appear separately, but I will --- see the descriptions of the 'format' and 'group-name' styles below.) If you set

 zstyle ':completion:*:-command-:*' tag-order '!parameters' 

then the last two lines will disappear from the completion. Of course, your completion list probably looks completely different from mine anyway. By the way, one good thing about styles is that it doesn't matter whether they're defined before or after completion is loaded, since styles are stored and retrieved by another part of the shell.

To exclude more than one tag name, you need to include the names in the same word. For example, to exclude both parameters and reserved words the value would be '!parameters reserved-words', and not '!parameters' '!reserved-words', which would try completion once with parameters excluded, then again with reserved words excluded. Furthermore, tags can actually be patterns, or more precisely any word in one of the arguments to tag-order may contain a pattern, which will then be tried against all the valid tags to see if it matches. It's sometimes even useful to use '*' to match all tags, if you are specifying a special form of one of the tags --- maybe using a label, as described next --- in the same word. See the manual for all the tag names understood by the supplied functions.

The tag-order style allows you to give tags 'labels', which are a sort of alias, instructing the completion system to use a tag under a different name. You arrange this by giving the tag followed by a colon, followed by the label. The label can also have a hyphen in front, which means that the original tag name should be put in front when the label is looked up; this is really just a way of making the names look neater. The upshot is that by using contexts with the label name in, rather than the tag name, you can arrange for special behaviour. Furthermore, you can give an alternative description for the labelled tag; these show up with the format style which I'll describe below (and which I personally find very useful). You put the description after another colon, with any spaces quoted. It would look like this:

 zstyle ':completion:*:aliens:*' tag-order \ 'frooble:-funny:funny\ frooble' frooble 

which is used when you're completing for the command aliens, which presumably has completions tagged as 'frooble' (if not, you're very weird). Then completion will first look up styles for that tag under the name frooble-funny, and if it finds completions using those styles it will list them with a description (if you are using format) of 'funny frooble'. Otherwise, it will look up the styles for the tag under its usual name and try completion again. It's presumably obvious that if you don't have different styles for the two labels of the tag, you get the same completions each time.

Rather than overload you with information on tags by giving examples of how to use tag labels now, I'll reserve this for the description of the ignored-patterns style below, which is one neat use for labels. In fact, it's the one for which it was invented; there are probably lots of other ones we haven't thought of yet.

One important note about tag-order which I may not have made as explicit as I should have: it doesn't change which tags are actually valid in that completion. Just putting a tag name into the list doesn't mean that tag name will be used; that's determined entirely by the completion functions for a particular context. The tag-order style simply alters the order in which the tags which are valid are examined. Come back and read this paragraph again when you can't work out why tag-order isn't doing what you want.

Note that the rule for testing patterns means that you can always specify a catch-all worst case by 'zstyle "*" style ...', which will always be tried last --- not just in completion, in fact, since other parts of the shell use the styles mechanism, and without the ':completion:' at the start of the context this style definition will be picked up there, too.

Styles like tag-order are the most important case where tags are used on their own. In other cases, they can be added to the end of the context; this is useful for styles which can give different results for different sets of completions, in particular styles that determine how the list of completions is displayed, or how a completion is to be inserted into the command line. The tag is the final element, so is not followed by a colon. A full context then looks something like ':completion::complete:cd::path-directories'. Later, you'll see some styles which can usefully be different for different tag contexts. Remember, however, that the tags part of the context, like other parts, may be empty if the completion system hasn't figured out what it should be yet.

6.5: Configuring completion using styles

You now know how to define a style for a particular context, using

 zstyle