Search code examples
zshzsh-completion

Make zsh complete arguments from a file


zsh is great but its completion system is very diverse. And the documentation lacks good examples. Is there a template for completing for a specific application. The completion would get its match data from a file, separated by newlines?

I tried modifying an older example of mine that takes match data "live":

~ % cat .zsh/completers/_jazzup 
#compdef jazz_up
_arguments "2: :(`mpc lsplaylists|sed -e 's# #\\\\ #g'`)"

I could supply cat my_file there instead of mpc invocation and so on but would there be a more elegant way to do this simple task? And that completion there is placement-specific: can you provide an example where zsh would attempt to complete at any point after the program name is recognized?

The match data will have whitespaces and so on, the completion should escape the WS. Example of that:

Foo bar
Barbaric
Get it (42)

Now if that completion would be configured for a command Say, we should get this kind of behaviour out of zsh:

$ Say Fo<TAB>
$ Say Foo\ bar
$ Say Ge<TAB>
$ Say Get\ it\ \(42\)

Solution

  • Simple completion needs are better addressed with _describe, it pairs an array holding completion options and a description for them (you can use multiple array/description pairs, check the manual).

    (_arguments is great but too complex.)

    [...]

    First create a file

    echo "foo\nbar\nbaz\nwith spac e s\noh:noes\noh\:yes" >! ~/simple-complete
    

    Then create a file _simple somewhere in your $fpath:

    #compdef simple
    
    # you may wish to modify the expansion options here
    # PS: 'f' is the flag making one entry per line
    cmds=( ${(uf)"$(< ~/simple-complete)"} ) 
    
    # main advantage here is that it is easy to understand, see alternative below
    _describe 'a description of the completion options' cmds
    
    # this is the equivalent _arguments command... too complex for what it does
    ## _arguments '*:foo:(${cmds})'
    

    then

    function simple() { echo $* }
    autoload _simple # do not forget BEFORE the next cmd! 
    compdef _simple simple # binds the completion function to a command
    
    simple [TAB]
    

    it works. Just make sure the completion file _simple is placed somewhere in your fpath.

    Notice that : in the option list is supposed to be used for separating an option from their (individual) description (oh:noes). So that won't work with _describe unless you quote it (oh\:yes). The commented out _arguments example will not use the : as a separator.