The Valuable Dev

What's The Vim Runtime? A Guide With Examples

The Vim runtime can be very fast

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.

Learning to play vim
If you like this series, I’m currently writing an ambitious book about Vim with many more tips!

Take your headlamp and a good rope, we’ll go exploring today many paths in our filesystems.

Vim’s Startup

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.

Startup’s Order

Here’s what Vim will do when you run it:

  1. Set the shell options (useful for the command :!, and for Vim’s terminal).
  2. Process the arguments given to the CLI. Buffers are created for all files given as arguments.
  3. The value of the environment variable $VIMINIT (an Ex command) is executed.
  4. Source the user’s vimrc file.
  5. The value of the environment variable $EXINIT (an Ex command) is executed.
  6. 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.
  7. Source filetypes, filetype plugins, and indent plugins. We’ll see them below.
  8. Source syntax highligting scripts.
  9. Source plugin’s scripts.
  10. Load runtime’s and plugin’s scripts from the “after” folder.
  11. Source the shada file (for Neovim) or the viminfo file (for Vim).
  12. 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 $HOME/.vimrc).
    • In Lua or Vimscript for Neovim (located in $HOME/.config/nvim/init.vim, or $XDG_CONFIG_HOME/nvim/init.vim if $XDG_CONFIG_HOME is set).
  • Setting the option exrc can 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 -c or +. 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 <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.

Vim help
  • :help startup
  • :help slow-start
  • :help 'shell'
  • :help $VIM
  • :help $VIMRUNTIME

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 :set runtimepath?.

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 $HOME/.config/nvim.

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:

For Vim:

  • $HOME/.vim
  • $VIM/vimfiles
  • $VIM/vimfiles/after
  • $HOME/.vim/after

For Neovim:

  • $XDG_CONFIG_HOME/nvim (or ~/.config/nvim if $XDG_CONFIG_HOME is not set)
  • $XDG_CONFIG_HOME/nvim/after

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.

ftplugin

The subdirectory ftplugin (for filetype 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:

  1. Open a markdown file and verify that the filetype is indeed markdown, by running the command :set filetype?.
  2. Create the file markdown.vim in $HOME/.vim/ftplugin for Vim, or $XDG_CONFIG_HOME/nvim/ftplugin for Neovim.
  3. Add options and mappings only for markdown files in there. For example: setlocal spell will 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 :au!).
  • Every mapping you’re creating have the special argument <buffer>, for example map <buffer> <leader>h echo "hello".
  • You’re using setlocal instead of set to set options.
  • You’re using the -buffer argument 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.

autoload

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 :call general#MyFunction.

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.

syntax

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.

colors

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 :color <my_color_scheme>.

ftdetect

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:

  1. Create the file ftdetect/new.vim
  2. Write au BufRead,BufNewFile *.new set filetype=new in 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:

  1. Created the file ftdetect/yaml.dist.vim
  2. Written autocmd BufNewFile,BufRead *.yml.dist set filetype=yaml in it.

compiler

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 :runtime colors/**/*.vim.

You can also use :runtime! (with a bang !) to source everything.

Vim help
  • :help 'runtimepath'
  • :help autoload
  • :help ftplugin
  • :help syntax
  • :help new-filetype
  • :help after-directory

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 -V or --startuptime to get more details regarding Vim’s startup.
  • The environment variable $VIM and $VIMRUNTIME are 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 :runtime allows 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.

Share Your Knowledge