Adding support for fish, zsh, tcsh in shcompgen

I’ve recently added support for the other three shells (fish, zsh, tcsh) in shcompgen. shcompgen is basically a utility to write those shell commands “complete -C foo foo” or “complete -c foo -l longopt1 –description ‘Add a thing to foo'” for you. It recognizes scripts written using Getopt::Long::Complete, Perinci::CmdLine, and a few others so that you can enable shell tab completion for your scripts.

fish. Enabling tab completion for a command in fish is relatively simple. For each short/long option of a command, you can define a separate “complete” command, e.g.:

complete -c man -s k --description "Show apropos information"
complete -rc man -s C --description "Configuration file"
complete -xc man -a 1 --description "Program section"
complete -xc man -a 2 --description "Syscall section"
complete -xc man -a 3 --description "Library section"
...

Doing this has the advantage of fish knowing about the each program option and its description, so you can get a prettier/more informative completion. It is not possible to just say like in bash “complete -F somefunc cmd; # delegate completion to a function” or “complete -C somecmd cmd ; # delegate completion to an external command”. It’s also possible to just delegate to the program entirely a la bash’s “complete -C”:

complete -c somecmd -a '(begin; set -lx COMP_SHELL fish; set -lx COMP_LINE (commandline); set -lx COMP_POINT (commandline -C); shcompgen; end)'

zsh. Completion in zsh is complex and complicated with lots and lots of options, if not featureful. You can, in theory, use “complete” or “compgen” command like in bash because zsh has “bashcompinit” that (partially) simulates those two bash commands. This enables you to reuse your bash completion definitions in zsh. I tried to do that but didn’t succeed though.

#compdef pmman
autoload bashcompinit
bashcompinit
# this is bash-style
complete -C pmman pmman

The commands I type will sometimes complete, but at other times won’t. So I use “compadd” instead, which is the standard way to add completion results in zsh. For example:

#compdef pmman
_pmman() {
 si=$IFS
 compadd -- $(COM_SHELL=zsh COMP_LINE=$BUFFER COMP_POINT=$CURSOR pmman)
 IFS=$si
}
_pmman "$@"

tcsh. tcsh lacks a fallback or autoload mechanism (like “complete -D” in bash or similar mechanism in fish and zsh), so activating or deactivating completion for a command requires you to explicitly re-source a definition script or logout + login again.

Tab completion now works in zsh, fish, and tcsh but since I don’t use those shells daily and am not familiar enough with them, there are still known issues (documented in the shcompgen’s POD) like with escaping of special characters like whitespace. I hope that Perl programmers that use one of those shells can give inputs on how to resolve the issues.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s