Have you ever wonder what was The Beginning of All Things™?
In other words: have you ever wonder what Vim is doing when you start it? What files are sourced, why, and in what order? If you don’t really care, I encourage you to reconsider your position. Knowing what Vim is doing at startup lets you speed it up, overwrites some defaults from the plugins you’ve installed, or even creates your own filetypes. In short, it gives you even more power to customize Vim to your precise needs.
In this article, we’ll look at two main ideas:
- What happens during Vim’s startup.
- What are the runtime paths, what’s sourced from there, and when.
This article assumes that you have some advanced knowledge about Vim. If you don’t, you can read my series of article to learn Vim from the ground up. More specifically, a lot of knowledge in this article is built on Vim for Expert Users.
Take your headlamp and a good rope, we’ll go exploring today many paths in our filesystems.
When you start Vim, many things happen behind the curtain before your favorite cursor is displayed on the screen. I describe here a simplified version, trying to underline the most important steps.
Here’s what Vim will do when you run it:
- Set the shell options (useful for the command
:!, and for Vim’s terminal).
- Process the arguments given to the CLI. Buffers are created for all files given as arguments.
- The value of the environment variable
$VIMINIT(an Ex command) is executed.
- Source the user’s vimrc file.
- The value of the environment variable
$EXINIT(an Ex command) is executed.
- If the option “exrc” is set, Vim will try to find and load a vimrc in the working directory. Keep in mind however that setting “exrc” is not secure.
- Source filetypes, filetype plugins, and indent plugins. We’ll see them below.
- Source syntax highligting scripts.
- Source plugin’s scripts.
- Load runtime’s and plugin’s scripts from the “after” folder.
- Source the shada file (for Neovim) or the viminfo file (for Vim).
- Execute the options given to Vim affecting the startup.
Let’s add more precisions:
- If you want to run more than one command using
$VIMINIT, you can separate them with the symbol
- Your vimrc file can be:
- In Vimscript for Vim (located at
- In Lua or Vimscript for Neovim (located in
- In Vimscript for Vim (located at
- Setting the option
exrccan be dangerous: Vim can load potentially unsecure vimrc files you might have downloaded with other files.
- You can use the option
-u <another_vimrc>when you run Vim in your terminal, to load another vimrc file instead of the default one. You can also use of of these value instead of a vimrc for debug purposes:
NORC- Don’t load any vimrc but load your plugins.
NONE- Don’t load any vimrc nor plugins.
- You can run any command using the options
+. For example:
vim +"set shiftwidth=4|echo 'hello'"
Profiling Vim’s Startup
If Vim does terrible things at startup and you don’t understand how to fix it, you can use the option
-V to have more details about the startup process.
If you’re startup is too slow and you want to find the bottleneck, you can profile it with
vim --startuptime <file>. It will write every files loaded (with timestamps) in the file
Special Environment Variables
Two environment variables are only defined when Vim starts:
$VIM- Used to locate various user files.
$VIMRUNTIME- Used to locate various support files for Vim. We’ll speak more about the runtime below.
You can look at the value of these variable with the command
:echo $VIM for example. If you define these environment variables in your shell, Vim won’t overwrite them.
The Runtime Path
The runtime path is similar to the environment variable PATH in Unix-based systems. Vim will search in these paths to locate and source many different files during startup. To see all of these paths, you can look at the value of the option
runtimepath, by running the command
If you use Vim, it’s likely that you’ll see
$HOME/.vim as the first path of the list. If you’re a Neovim adept, it will be
The subdirectories of the runtime paths have different meanings according to their names. The Vimscript files inside these directories will be sourced at different times during startup, sometimes in different ways.
Important Runtime Paths
Here are some important runtime paths. Vim will parse them in this order:
$XDG_CONFIG_HOMEis not set)
Subdirectories of the Runtime Paths
As I was writing above, the configuration files in the runtime paths contains different things depending of the subdirectory they’re in. Here’s an overview of the most useful of these subdirectories, and how you can use them to customize Vim even further.
I encourage you to look at the default configuration files to understand the meaning of these subdirectories. They are in the directory set in the variable
$VIMRUNTIME. Don’t forget that you can only read the value of
$VIMRUNTIME after launching Vim.
You can also find examples in my own dotfiles.
The subdirectory ftplugin (for
plugin) allow you to load pieces of configuration each time you open a buffer with a specific filetype.
For example, let’s say that you need a couple of mappings only for markdown files. You can:
- Open a markdown file and verify that the filetype is indeed markdown, by running the command
- Create the file
$HOME/.vim/ftpluginfor Vim, or
- Add options and mappings only for markdown files in there. For example:
setlocal spellwill enable spelling each time you open a markdown file.
You need to keep in mind, however, that each time a buffer with the filetype
markdown is created, the file
ftplugin/markdown.vim will be sourced. As a result, you need to make sure that:
- You’re resetting any autocommand each time the file is sourced (using an autocommand group and
- Every mapping you’re creating have the special argument
<buffer>, for example
map <buffer> <leader>h echo "hello".
- You’re using
setto set options.
- You’re using the
-bufferargument for any user command.
If you don’t respect these rules, your pieces of configuration won’t only be loaded for the buffers with a precise filetype, but for every buffer, globally.
The subdirectory autoload is also very useful. It lets you load your custom functions when you call them, instead of loading them when Vim starts. As a result, it can significantly speed up Vim’s startup. These functions need to begin with the path of the file they’re written in, for Vim to know where to find them when you call them.
For example, you can create a new file
autoload/general.vim and use it to declare a new custom function
MyFunction. This function needs to be called
general#MyFunction, because it’s declared in the file
general.vim. To call it, you can run
You can also create subdirectories in the directory
autoload. For example, you can create the file
autoload/path/to/general.vim. In that case, you need to call your function
path#to#general#MyFunction, describing the location of the file itself.
I encourage you to put all your custom functions in the “autoload” subdirectory.
The subdirectory syntax lets you create your own syntax files. They’re used for code highlighting for example. You can first create a syntax group matching some regex, and then you link your syntax group to highlight groups. These highlight groups will decide of the text’s color displayed.
Vim supports many syntaxes by default (you can see them in the directory
$VIMRUNTIME/syntax), I never had to create my own syntax groups. It’s however good to know that you can do it in case you need it.
You can create highlight groups in the subdirectory colors. Each file represents a different color scheme. Again, you’ll find different examples in the directory
$VIMRUNTIME/colors. To change the color scheme of your highlighting, you can use the command
Have you ever dreamed to create your own filetypes? That’s great, because Vim is a dream machine. You can create your filetypes in the subdirectory “ftdetect”.
For example, if you have a bunch of file with the extension “new” and you want to create a filetype for them, you can:
- Create the file
au BufRead,BufNewFile *.new set filetype=newin it.
You can also link some filetypes with other ones. For example, I wanted the files with the extension
.yaml.dist to have the
yaml filetype. So I’ve:
- Created the file
autocmd BufNewFile,BufRead *.yml.dist set filetype=yamlin it.
In Vim, you can use the command
:make to run a specific compiler, depending of the filetype of your current buffer.
Under the hood, Vim will search a file named after the filetype of your current buffer, in the “compiler” directory. For example, if if you want to run the Golang compiler with precise options, you can create the file
compiler/go.vim and add whatever you need.
The Directory after
The subdirectory “after” is a special one. You can think of it as another runtime path in the runtime path, where you can add the same subdirectories we saw above.
Everything in the after directory will be loaded after everything else. You can also see it when you look at the order of the most important runtime path at the beginning of this section.
From there, you can override anything you want: indentation, filetype plugins, or even the external plugins you’ve installed. For example, I can override Lisp indentation by creating the file
after/indent/lisp.vim and setting whatever options or variables I want to modify.
I didn’t cover the subdirectory
indent by the way, but I’m sure you can figure out its purpose.
The Runtime Command
If you want to source manually some files from your runtime path, you can use the command
:runtime <file>. For example, if you want to load every files from the
colors subdirectory, you can run
You can also use
:runtime! (with a bang
!) to source everything.
Disabling Runtime Files
Finally, if you want to debug one of your runtime files, you can disable some of them by sourcing these specific files:
:source $VIMRUNTIME/ftoff.vim- Disable the detection of filetypes
:source $VIMRUNTIME/ftplugin.vim- Enable ftplugin
:source $VIMRUNTIME/ftplugof.vim- Disable ftplugin
:source $VIMRUNTIME/indent.vim- Enable indentation
:source $VIMRUNTIME/indoff.vim- Disable indentation
The Startup Has Been Revealed
Now that you know what Vim’s doing when it’s starting, you can add your pieces of configuration in the good runtime subdirectory for more flexibility. You can also try to speed up your startup if you find it too slow.
What did we see in this article?
- Vim load specific configuration files and environment variables at startup
- You can use the options
--startuptimeto get more details regarding Vim’s startup.
- The environment variable
$VIMRUNTIMEare set during startup.
- The subdirectories in the runtime path have a meaning, sometimes affecting directly how they’re loaded at startup, and when.
- The runtime path subdirectory “after” is a special one: it’s a runtime path too (accepting the same subdirectories), and you can overwrite every other loaded config files in there.
- The command
:runtimeallows you to manually load config files from your runtime paths.
I encourage you to experiment with all these configuration files to improve your config. Personally, I find the subdirectories “autoload” and “ftplugin” especially handy.