Custom Zsh Completions
I've recently been writing a shared wrapper for the various package managers on my machines. Depending on the OS, my `.zshrc` sources one `pkg.zsh` of several containing identical shell functions. For example, `~/.config/zsh/os/arch/pkg.zsh` for Arch and `~/.config/zsh/os/debian/pkg.zsh` for Debian. Within these, I have functions with common signatures for updating, installing, and removing packages. These take the forms of pkg-update, pkg-install, and so on. Then, I have one master function, pkg, that takes an argument to carry out the desired behavior, for example, `pkg -u` that calls pkg-update.
This worked well for updating and listing installed packages, but it was subpar for installing and removing them. Being a custom function, `pkg` did not provide proper tab completions. This makes for a much worse experience, so I had to scrap the idea, or learn a little about how zsh handles completions. Attempting to learn this through trial and error was not the right way to go about it, but I eventually ended up with the following for my Arch-based installs:
function _pkg_all_pkgs_autocomp {
packages=( $(pacman -Sql) )
compadd "${packages[@]}"
}
function _pkg_local_pkgs_autocomp {
packages=( $(pacman -Qet) )
compadd "${packages[@]}"
}
- The first function provides completions for all available packages using `pacman -Sql` to get the underlying list. This is useful for the `--install` flag.
- The second function provides completions for the packages installed to the system using `pacman -Qq`, useful for the `--remove` flag.
The final snippet below shows how I combined these to enable completions for the `pkg` function.
function _pkg_completions {
local curcontext="$curcontext" state line
typeset -A opt_args
_arguments -C \
'-u[Upgrade all packages]' \
'--upgrade[Upgrade all packages]' \
'-l[List all packages]' \
'--list[List all packages]' \
'-i[Install one or more packages]:packages:_pkg_all_pkgs_autocomp' \
'--install[Install one or more packages]:packages:_pkg_all_pkgs_autocomp' \
'-r[Uninstall one or more packages]:packages:_pkg_local_pkgs_autocomp' \
'--remove[Uninstall one or more packages]:packages:_pkg_local_pkgs_autocomp' \
'*::arg:->args'
}
compdef _pkg_completions pkg
I've since changed and condensed things a little, but I left it in this form here as I felt it was easier to understand.
- Nate