So here is a little experiment: with a clean config (i.e., no previous ~/.vimrc or ~/.vim/), do:

$ mkdir -p ~/.vim/plugin/
$ vim ~/.vim/plugin/foo.vim

And in that file, enter the following, save & exit:

echom "loaded."

Now open some file "a":

$ vim a

And inside vim, do:

:edit b

Where b is some other file. Now if you do :messages, it will show the "loaded." message, but only once!!

So global plugin files seem to be loaded only once. This behaviour surprised me when I stumbled upon it earlier today, but when I got to think about it, I guess it does make some sense: if it is a global plugin, it is not supposed to change on a per buffer basis, or whatever...

Nevertheless, I was unable to find more information about this, either vim's docs, or in the internet at large (i.e. google), so I thought to ask here: can anyone shed some more light onto this behaviour regarding vim's global plugins?

Thanks in advance.

  • 3
    I’m voting to close this question because I think it is too broad for this website. You should try to make it more clear what you are looking for exactly because for now it looks like you want to understand how the whole plugin system works. To get this kind of answer you probably want to read :h plugin and learn vimscript the hard way to better understand the plugin system. – statox May 4 at 11:27
  • As well as :h ftplugin for filetype specific plugins which are run for each buffers. – statox May 4 at 11:27
  • Well, I also don't know what to add. It all seems quite logical to me. "Plugin" = "Script"; the scripts are sourced in a course of init-sequence, or because of some commands (including auto-commands and other scripts) executed, such as :source, :runtime, :packadd, :colorscheme, :syntax on/off etc.etc. "Re-sourcing" all plugin/**/*.vim is not normally bound to any existing (auto-)command except :packloadall!, so Vim does this only during startup. – Matt May 4 at 12:52
  • @statox You are right, the question did turn up a bit off-topic. However, I posted it because I ended up really confused after trying the same experiment with a filetype plugin: in this case, the plugin IS RESOURCED after :edit'ng another file... – wmnorth May 5 at 13:42

It's described in :h startup:h load-plugins. You'll see that indeed plugin files are loaded only once.

Yet, most plugin files have guards. They mainly serve to permit end-user to not load an installed plugin file. This was particularly useful in the old days when we didn't have 'runtimepath' managers (aka plugin managers), nor vim 8 packages, or when different version of a same plugin files were installed in different places ($VIMRUNTIME, $HOME/.vim, and so on).

Given my knowledge of C and the anti-reinclusion guard in header files, the usual g:loaded_{pluginname} name used for guards, I was also assuming that a plugin file may be loaded several times, that it makes sense. Historically, we did not have autoloaded plugin files in vim 5.x and vim 6.x. This meant that collection of functions needed to be regrouped in plugin/ files. And if another plugin file needed to use one of these functions in their global part, we had to make sure either the plugin file was already loaded, or to load it unconditionally and manually. Hence the guard that really acted as an anti-RE-inclusion guard. Unless we need to use a command defined in another plugin files, this scenario should not happen anymore since vim 7 -- thanks to autoload plugin (files).

Also, runtimepath/plugin managers often have an option to load a new "plugin", which may trigger the loading of plugin files, outside of the sequence described in :h starting.

  • Thank you for your answer. But as I understand it, anti-recinclusion guards are there to prevent a (filetype?) plugin from being re-loaded, which seems to indicate that without them, said ftplugin would indeed be reloaded on :edit, etc. -- as I found out to indeed be the case; cf. my comment to the original question above. – wmnorth May 5 at 13:44
  • The guards are here to prevent a plugin file from being loaded. Global guards are used for global plugins. In the common scenario, they'll prevent the plugin from being loaded if we want (from the .vimrc) prevent it. In atypical scenarios (vim 6.x pre autoload plugins ; or bad written plugins ; or plugins that need a command defined in the global plugin), they'll prevent the plugin from being loaded multiple times with a :runtime plugin/theplugin.vim. – Luc Hermitte May 5 at 15:47
  • Regarding ftplugins, they usually have a buffer-local guard. That can prevent the ftplugin files to be loaded once (normal, but very complex scenario to get right), or multiple times (improbable scenario) per buffer. In all cases if we want a ftplugin to be useful we need to load it on every buffer where it applies. All standard ftplugin files shiped with vim use a b:did_ftplugin guard. I recommend to not use it with custom ftplugins we define ourselves as it could prevent multiple ftplugin scripts from being used with a same buffer. – Luc Hermitte May 5 at 15:52
  • See for instance all my ftplugins: github.com/LucHermitte/lh-cpp/blob/gotoimpl_with_libclang/… (I have many, many more there and in lh-misc, lh-brackets...) – Luc Hermitte May 5 at 15:52
  • BTW we can have a global zone in an ftplugin where we define global things like functions. But this is bad style (pre vim7). From vim7 onward, these functions should be defined in autoload plugins. This is the case of the ftplugin in the previous link: it's old and I haven't completely updated it to Vim7. – Luc Hermitte May 5 at 15:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.