-
Notifications
You must be signed in to change notification settings - Fork 25
Zsh completion for cligen commands (with colored help output)
Zsh includes a large selection of parsers to support auto completion for a variety of commands. Common GNU tools with a 'standardized' -h/--help
interface normally use the _gnu_generic
completion module.
Unfortunately, when cligen
's help output includes ANSI SGR color escape sequences, it breaks _gnu_generic
's --help parser. At least as of Zsh version 5.9 this can be easily worked around by disabling the cligen
color escape sequences in the context of the help parsing.
To do this, we must define a custom completer. For the sake of explanation, assume your Zsh setup contains a ~/.zsh
directory with a ~/.zsh/completions.zsh
customization file (this assumes this file is sourced from e.g ~/.zshrc
of course). Create a directory for the location of any additional custom completers, ~/.zsh/completers/
, in which we place the following file named _cligen
:
# For cligen commands (which follow the GNU -h/--help style), disable color output in the context
# of `_gnu_generic`:
NO_COLOR=1 _gnu_generic
We make use of setting the NO_COLOR environment variable (supported by cligen
) to disable the color escape sequences only in the context of the _gnu_generic
call.
Then, in ~/.zsh/completions.zsh
all we need to do, is to autoload
this file and add the _cligen
completer to our default completions. A basic ~/.zsh/completions.zsh
file might look like:
autoload -U compinit && compinit
# load the custom completer
autoload -Uz ~/.zsh/completers/_cligen
## list of completers to use, extend by custom `_cligen` completer
zstyle ':completion:*::::' completer _expand _complete _cligen
With this done and Zsh restarted, you should get a nice list of possible completions when typing dups -<TAB>
, with dups.nim
from examples/
:
dups -
--brief -b -- bool false do NOT print sets of dups
--cmp -c -- bool false compare; do not trust hash
--delim -d -- char 'n' input file delimiter; 0 -> NUL
--Deref -D -- bool false dereference symlinks
--endOut -e -- string "n" output record terminator
--file -f -- string "" optional input ( "-" | !tty = stdin )
--follow -F -- bool false follow symlinks to dirs in recursion
--Hash -H -- Digest wy hash function (size|wy|nim|SHA)
--jobs -j -- int 1 Use this much parallelism
--log -l -- set(Lg) osErr >stderr{ osErr, summ }
--minLen -m -- int 1 minimum file size to consider
--outDlm -o -- string "t" output internal delimiter
--recurse -r -- 1 recurse n-levels on dirs; 0- unlimited
--slice -s -- string "" file slice (float|%-frac; <0-tailRel)
--time -t -- string "" sort each set by file time- {-}(bamcv).*
--xdev -x -- bool false block cross-device recursion
Completion of individual options should work as expected, including filtering to remaining matching (e.g. for multiple options starting with --f*
typing --f<TAB>
only lists the remaining, in this case --file
& --follow
.
Arguably it would be better to upstream something to Zsh using the NO_COLOR convention cligen
apps honor by default. Then if any other CLI toolkit/framework supports colorized help, it can honor the same convention and Zsh can just work. Let me know if you do that. :-) The bash complete -F _longopt
does not seem to require any of this, and shells do like to compete with each other. Color in terminals is also pretty popular. So, chances are high that a change like this would be accepted by Zsh maintainers, especially as a new name like _gnu_generic_no_color
.