I'm writing a ZSH completion file for a command which is a wrapper around another command that already has ZSH completion support. I'd like to use "private" helper functions defined in the other command's completion, but the naive approach isn't working. Here's what I am trying so far:

#compdef wrapper

_arguments ':action:(foo bar baz)' ':target:_other_command_helper_func'

when I try to do completion at the command line, I get

_arguments:450: command not found: _other_command_helper_func

Is it possible to do what I want to do here?

1 Answer 1


There are no private functions, so it'll work if _other_command_helper_func is already loaded. Since completion functions are normally autoloaded, that means that, with this approach, the completion for wrapper will only work if completion of the original command has already been attempted.

One solution is to force the loading of the original command's completion function file, but this is not straightforward. You can use autoload -X +U to load the completer for the original command, but what this in fact does is to create a function _other_command (assuming that's the name of the original command) whose definition is the content of the _other_command file, consisting of the definition of auxiliary functions and other initialization followed by a call to the main function.

_other_command () {
        _other_command_helper_func () {

        _other_command () {

        _other_command "$@"

You could try to parse that. If the definition is under your control, you can make some assumptions regarding the initialization code. If it comes from a third party, that's more risky. Most complex completion function definition files follow the model of having initialization followed by a last line of the form _main_function "$@", so this will usually work:

if ((!$+functions[_other_command_helper_func])); then
  autoload +X +U _other_command

If you get weird errors, this may be due to options that affect the parser (I had this problem loading _git in this way). This worked for me:

load_helper_functions () {
  emulate -LR zsh
  if ((!$+functions[$1])) || [[ $functions[$1] = 'builtin autoload'* ]]; then
    autoload +X +U $1
load_helper_functions _git

Alternatively, you can just run the completion function in your .zshrc and let it choke silently because it wasn't run in a completion context. For example, I had this precise problem with CVS; I put _cvs 2>/dev/null in my .zshrc.

If the definition of the original is under your control, then there are better solutions. You could use the same completion function for the original command and for the wrapper (check $service to see what command's arguments are being completed). Or you could define the auxiliary function in a separate file.

  • Ah, so the whole contents of the _other_command file in the completions dir becomes a single function, then? I think that's what I was missing. I'll poke at this some more and report back with any findings, etc. Thanks!
    – dcrosta
    Nov 13, 2017 at 14:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .