Search code examples
shellzshzsh-completion

zsh completion according to a parameter


I am a quite a happy zsh user and especially appreciate its completion subsystem. Recently I am trying to enhance some completion commands especially those I use often (ex. rm). In zsh the following command:

rm <TAB>

makes zsh complete with the current directory's files as expected. What I am trying to do is make zsh complete the following variant:

rm -r <TAB>

with only directories.

Any zsh Guru that knows how to parameter completion so that it takes in consideration the (-r) parameter?


Solution

  • This can be achieved by editing the zsh completion function for rm to the desired behaviour.

    The Z-shell completion functions are all defined somewhere on your system. On OSX, it's under /usr/local/zsh/5.0.2/share/zsh/functions. Linux probably has it somewhere similar.

    The completion function for rm is defined in a file called _rm. It's rather small. (If you're interested, the completion for rmdir is defined in _directories).

    To set the completion for rm -r, we need to modify the line that looks similar to this:

    '(-r -R --recursive)'{-r,-R,--recursive}'[remove directories and their contents recursively]'
    

    We add to the end of this line, inside the quote:

    :*:file:_directories
    

    I'm pretty sure that this informs zsh that the completion when the -r argument is given should consist of files, and the way we obtain those files is by using the _directories function (which only returns directories).

    (I'm not 100% sure, because zsh is a beast I'm still wrapping my little mind around).

    Here's a sample usage:

    enter image description here


    Here's a diff of the changes, to make it extra clear :)

    <   '(-r -R --recursive)'{-r,-R,--recursive}'[remove directories and their contents recursively]:*:file:_directories'
    ---
    >   '(-r -R --recursive)'{-r,-R,--recursive}'[remove directories and their contents recursively]'