I have zsh completion rules for my custom script h:

#compdef h

_arguments -S : \
    '-A+:' \
    '-B+:' \
    '-C+:' \
    '-i' \

My custom script takes the options shown above, and also one or more arbitrary strings. The completion works when no string is given:

h <TAB>
-A  -B  -C  -i  -w  

But once i provide the string, the completion no longer works:

h foo -<TAB>


How can I use completion even after I have provided one or more strings?


I have added '*:string:' as suggested by @Gilles

#compdef h

_arguments -S : \
    '*:string:' \
    '-A+:' \
    '-B+:' \
    '-C+:' \
    '-i' \
    '--color' \

But the completion behaves strangely. When I do:

h some text -<TAB>

it actually lists me available options, but does not complete them.

When I do:

h some text --co<TAB>

it shows available --color option, but does not complete the rest, even though the option is not ambiguous.

1 Answer 1


Somewhere in the depths of zshcompsys(1) one might find the -A option to _arguments

-A pat Do not complete options after the first non-option argument
       on the line. pat is a pattern matching all strings which are
       not to be taken as arguments. For example, to make _arguments
       stop completing options after the first normal argument, but
       ignoring all strings starting with a hyphen even if they are
       not described by one of the optspecs, the form is `-A "-*"'.

which is not helped by the negations. Anyways, the pattern * appears to mean that "everything is not taken as an argument" therefore the options should complete following a non-option argument:

#compdef h
local ret=1
_arguments -A "*" -S : \
    '-A+:' \
    '-B+:' \
    '-C+:' \
    '-i' \
    '-w' \
    && ret=0
return $ret

Usage, assuming the _h completion script is in ~/.zsh/functions:

% zsh -f
lion% print $fpath
lion% fpath=( ~/.zsh/functions $fpath )
lion% autoload -U compinit
lion% compinit
lion% h -w foo -
-A  -B  -C  -i

with the cursor right after the - ZSH completes the available options. Confirm that the completion script is up (after tabbing on the command) via:

lion% which _h
_h () {
        local ret=1
        _arguments -A "*" -S : '-A+:' '-B+:' '-C+:' '-i' '-w' && ret=0
        return $ret
  • thank you, but this change doe snot seem to help. It behaves same as before. Aug 1 at 3:37
  • does it work under a minimal shell configuration?
    – thrig
    Aug 1 at 3:47
  • I follow the steps exactly, but this still does not work. Aug 1 at 17:58
  • I think -A "*" should be equivalent to not using -A at all. Experimentally, I confirm that it doesn't seem to make a difference. What does make a difference @400theCat is adding completions for non-option arguments *:string:, but that also means that zsh won't automatically insert a - if you press TAB on an empty word, which is not necessarily desirable. Aug 2 at 20:44
  • @Gilles 'SO- stop being evil' - thank you, but when I add *:string: it behaves strangely. Please see my update. Aug 9 at 7:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.