🐣 Make Zsh compinit suck less
This Zsh Plugin removes the complexity and "gotchas" from initializing the Zsh completion system (compinit).
🐣 Let's talk about compinit
...
The Zsh completion system works by loading any completion
functions in Zsh's "fpath". Completion functions are named with a leading underscore
(eg: "_foo"). In order to use compinit
correctly, your fpath needs to be fully populated prior to calling it. But, sometimes you need to use the completion functions
compinit
creates, like compdef
. Many Zsh plugins call compdef
, for example.
This creates a big chicken-and-egg problem 🐣. Do you call compinit
earlier so that its functions are available, or later so that you're sure you have
everything in your fpath
fully populated?
Then, once you've figured out how to initialize completions, you still have to figure
out how to display them. That happens with calls to zstyle
. Learning how to
properly configure your zstyles
to show completions how you want them is a whole other dark art in Zsh.
Add to that the fact that calls to compinit
are likely to be one of the slower parts
of your whole Zsh config, and you wind up quickly finding that compinit
is a pain to
use, especially for new users.
This plugin aims to fix all that. It handles the Zsh completion system complexity so you don't have to.
This plugin simply wraps compinit
and the functions it creates so that we can defer
completion initialization until after "fpath" is fully populated. This allows queueing
calls to compdef
, and hooking the real compinit
call to an event that runs at the
very end of your .zshrc
. That way you get all the benefits of calling compinit
early without any of the downsides. Neat!
It also packages some completion "zstyles" from other popular projects like:
To install with antidote, add the following to the top of antidote's
${ZDOTDIR:-$HOME}/.zsh_plugins.txt
file:
mattmc3/ez-compinit
To install with a different plugin manager, follow the guide for that plugin manager.
To install manually, do the following:
[[ -n "$ZPLUGIN_HOME" ]] || ZPLUGIN_HOME=${ZDOTDIR:-$HOME}/.zsh_plugins
if [[ ! -d $ZPLUGIN_HOME/ez-compinit ]]; then
git clone https://github.com/mattmc3/ez-compinit $ZPLUGIN_HOME
fi
source $ZPLUGIN_HOME/ez-compinit/ez-compinit.plugin.zsh
ez-compinit is pretty simple. Run this plugin near the top of your config before any
other plugins or scripts that might call compdef
.
It's also recommended to pick a completion style. You set a compstyle with the following zstyle statement:
# Available completion styles: gremlin, ohmy, prez, zshzoo
# You can add your own too. To see all available completion styles
# run 'compstyle -l'
zstyle ':plugin:ez-compinit' 'compstyle' 'zshzoo'
Yes, you can absolutely call compinit
yourself. Or, you can use a plugin that calls
compinit
. ez-compinit will gracefully unhook itself whenever compinit
is called.
But remember, once you do, your fpath
cannot be modified with additional directories
if you expect those to contain more completion functions.
Or, you could simply load this plugin and forget about it. ez-compinit will guarantee
compinit
is called for you with reasonable defaults. That's what makes it easy.
You no longer need to think about how Zsh completions work.
This plugin is not needed for regular Oh-My-Zsh users. But, if you happen to be using Oh-My-Zsh with the antidote plugin manager, I highly recommend using getantidote/use-omz instead, which is by the same plugin author (me!) and uses similar concepts, but is geared specifically towards antidote users of Oh-My-Zsh. You definitely don't need both plugins.
Absolutely. This plugin has nothing to do with antidote, which is why it's hosted on my personal GitHub and not at https://github.com/getantidote. It's a complete plugin on its own with no dependencies, and makes managing the Zsh completion system easy.
There are a few ways to customize ez-compinit behavior if you want to.
This plugin will place the completion dump file at the following location by default:
${XDG_CACHE_HOME:-$HOME/.cache}/zsh/zcompdump
. You can override this by setting
the ZSH_COMPDUMP
variable like so:
ZSH_COMPDUMP=/path/to/.zcompdump
This plugin can also cache the zcompdump file for a day for performance reasons. Caching
is disabled by default because it can cause you trouble if you add completions to your
fpath
and forget you have enabled caching. Then, you'll waste a hour trying to track
down why your compinit is broken. If you consider yourself an advanced user and think
you can navigate that issue, you can enable caching with the following zstyle
:
zstyle ':plugin:ez-compinit' 'use-cache' 'yes'
ez-compinit provides a run-compinit
function which includes performance enhancements
in addition to caching mentioned above. It will also zcompile
the completion file, and
will skip insecure directory checks. This is very similar to what Prezto does in its
completion module.
If you prefer to use compinit
differently, you can simply call it yourself at the very bottom of your .zshrc
. By loading ez-compinit at the top and calling compinit
yourself at the bottom, you still get all the benefits of queueing compdef
calls.
# .zshrc
# Load ez-compinit towards the top of your config
# Load it yourself, or with a plugin manager.
source /path/to/ez-compinit/ez-compinit.plugin.zsh
#
# .zshrc contents here...
#
autoload -Uz compinit
compinit -u -d /path/to/zcompdump
# end of .zshrc