The illusion of fast startup times in vim2021-08-22 | 5 min read | Leer en español
With an emphasis on the word "Illusion". What I'm going to show you is not a "magic trick" that will make vim go faster. Don't get your hopes up. The only thing we'll do here is delay the inevitable.
What do we want to achieve?
I want to load my optional plugins after vim interface is fully loaded and ready to go.
Because when I open vim there is a little timeframe of maybe 2 or 3 seconds where my mind goes from "what was I going to do?" to "Yeah, that thing". That's when I want to load the plugins. This way we only the deal with necessary stuff at startup, and then rest of the "nice to have" can happen in this timeframe where I am not doing anything in the editor.
Let's get to it
In vim we have an event called
VimEnter, it gets emitted when is done executing all the initial scripts and plugins. In theory this should be enough, but not for me, I really want to be sure. So what I'd like to do is wait 20 miliseconds after this event is dispatched, it should be enough time for vim to load the interface, and then load the plugins.
For this we will need an autocommand and the
timer_start function. So let's make a test.We'll print a message 5 seconds after vim has started. We'll put this in our
function! s:load_plugins(t) abort echom "vim is ready" endfunction augroup user_cmds autocmd! autocmd VimEnter * call timer_start(5000, function('s:load_plugins')) augroup END
Next time we open vim we should see the message
vim is ready, after a few seconds. If you missed it you can check with command
Now we know it works. Change the delay time from
20. And in
s:load_plugins put all the necessary commands to load your plugins.
This next part will depend a lot on how you manage your plugins. I'm going to use a built-in feature known as packages. Some plugins managers don't use it, so make sure it does by reading the docs.
The last piece of the puzzle is the
packadd command, is what we'll use to load all our "optional plugins". So our function should be something like this.
function! s:load_plugins(t) abort " list of plugins packadd vim-surround packadd vim-obsession "(optional) run all the scripts in the `after` folder runtime! OPT after/plugin/*.vim "(optional) emit a user 'event' " so we can call other autocommands in this moment doautocmd User PluginsLoaded endfunction augroup user_cmds autocmd! autocmd VimEnter * call timer_start(20, function('s:load_plugins')) augroup END
That's it. But I'm not done.
What about lua?
Neovim (version 0.5) makes it possible to write our config file entirely in lua, and a lot of people are doing just that. It's possible to write this in your lua config, but the current limitations of the API will force you to write a lot of vimscript.
Here is what you'll need to do in lua.
function load_plugins() vim.cmd [[ packadd vim-surround packadd vim-obsession runtime! OPT after/plugin/*.vim doautocmd User PluginsLoaded ]] end vim.cmd [[ augroup user_cmds autocmd! autocmd VimEnter * lua vim.defer_fn(load_plugins, 20) augroup END ]]
I'm using a global function just because is the easiest way to write it. In general I advice against it. If you know how to create and use a lua module, use that instead.
You should consider what plugins you're going to load using this method.
NERDTree (a file manager) as an example. If you open up a folder in the terminal, something like
NERDTree can show you the files in the folder automatically. But that specific feature will not work if you load it after
Syntax plugins can also be affected by this. If you load them late in the process you might actually see when the default colors change to the ones declared by the plugin. Is not a nice experience.
We learned about
VimEnter, an event that vim emits when the startup process is done. We learned about
vim.defer_fn, how we can use them to execute a function at a later time. Finally, we pieced together all of this to load all optional plugins in a specific moment when we as users are not interacting with the editor.
But we should also be careful with this. Loading a plugin outside the startup process can have unexpected side effects. So we should first decide what plugins can be optional.
Thank you for reading. If you find this article useful and want to support my efforts, buy me a coffee ☕