Generating zsh completion functions

August 05, 2014

When I switched from bash(1) to zsh(1), I was surprised to find how many standard programs lacked completion functions. Only few of the coreutils are supported in vanilla zsh(1).

Although there are user-contributed repositories like zsh-users/zsh-completions I still couldn't find completion functions for tools like cat, nl, df and others.

So I wrote some and I've found that I basically just copied the info from help text to the completion function. Boring. Something that even a machine could do. Well, kinda...

Almost every program with command line arguments implements also --help text, which already lists the options even with their description. So why not use that for generating the functions?

... Because every program uses slightly different format and it would be nightmare to cover all the cases, you say? Then you're exactly right. But then I though that I don't anything perfect, just something that mostly works.

Luckily, most programs do play nice. But help texts are still meant to be for humans so sometimes it borks...

Here's a zsh(1) plugin I wrote that does exactly that..

It parses short and long options and their descriptions from commands's help texts and then generates functions automatically. Read the README of the project for more info about usage.

Here follows a test file that demonstrates common patterns in help texts and the generated function:

Usage: imag [options] [target] ...
Imaginary command the sake of demonstration.

Options:
  -b, -m                      Few words of description.
  -B --always-make            Short and long variant.
  -C DIRECTORY, --directory=DIRECTORY
                              This description is on the next line.
  -d                          Short option only.
  --no-print-directory        Long option only.
  --debug[=FLAGS]             Print various types of debugging information.
  -f FILE, --file=FILE, --makefile=FILE
                              More variants of one option are supported.
  -h --help                   No comma.
  -j [N], --jobs[=N]          Short options can have arguments too!
  -k, --no-description
  -S, --no-keep-going, --stop
                              Same as --whatever.
  -W FILE, --what-if FILE, --new-file FILE, --assume-new FILE
                              Even more variants without equals.

Current caveats: (these cases fail or don't work properly)
  -t        Two column help text   -T     can be found in some programs.
  --only-one-space Between argument and description.
  -D <var>:<type>=<value>     Harder syntax right in the option.
  --help={target|optimizers|warnings|params|[^]{joined|separate|undocumented}}[,...]
                              This baby from gcc's help text.

This program built for x86_64-pc-linux-gnu
Report bugs to <bug@gnu.org>

$ gencomp imag

#compdef imag

# zsh completions for 'imag'
# automatically generated with http://github.com/RobSis/zsh-completion-generator
local arguments

arguments=(
    {-b,-m}'[Few words of description.]'
    {-B,--always-make}'[Short and long variant.]'
    {-C,--directory}'[This description is on the next line.]'
    '-d[Short option only.]'
    '--no-print-directory[Long option only.]'
    '--debug[Print various types of debugging information.]'
    {-f,--file,--makefile}'[More variants of one option are supported.]'
    {-h,--help}'[No comma.]'
    {-j,--jobs}'[Short options can have arguments too!]'
    {-k,--no-description}'[]'
    {-S,--no-keep-going,--stop}'[Same as --whatever.]'
    {-W,--what-if,--new-file,--assume-new}'[Even more variants without equals.]'
    '-t[Two column help text   -T     can be found in some programs.]'
    '--only-one-space[argument and description.]'
    '-D[<value>     Harder syntax right in the option.]'
    '--help[^\]{joined|separate|undocumented}}\[,...\]]'
    '*:filename:_files'
)

_arguments -s $arguments
Thank you for finding time to read my blog!
comments powered by Disqus