I'm new to vim (8.2) and have been learning how to set it up on my computer (Ubuntu 18) for the past few days.

I'd like to configure VIM so that when I open code in different programming languages, different settings load. Eg. indentation, color-theme, plugins etc.

I found ftplugin to be the recommended way to achieve this setup. Let's assume I want to setup VIM for python and markdown. I've installed the plugins (NERDTree, ale etc.) using VIM's native package manager. I've put some plugins like NERDTree in the /start folder while some like ALE in the /opt folder. This is because I want NERDTree to always load when I open any file using VIM while I want to conditionally load ALE when I only open a python file (and not markdown).

From what I've read in other answers and blogposts, we need to do the following -

  1. Add filetype plugin indent on at the start of the main ~/.vimrc.
  2. Create folders ~/.vim/ftplugin/python.vim and ~/.vim/ftplugin/markdown.vim.
"file => ~/.vim/ftplugin/python.vim
setlocal number
setlocal autoindent
setlocal shiftwidth=4
packadd! ale
"file => ~/.vim/ftplugin/markdown.vim
setlocal number
setlocal autoindent
setlocal shiftwidth=2

Will this setup work? Any mistakes/gotchas in this?

  • 1
    Welcome to Vi and Vim! It sounds like you’ve already got a good handle on some confusing concepts, and I would love to write an answer to help you figure out the rest. However, we really prefer not to have multiple distinct questions in one post. Would you please edit your question to scope it to one question? Feel free to ask the other questions as separate questions! For example: « What is the difference between ftplugin and after/ftplugin » and « What is b:undo_ftplugin used for » sound like good titles to me!
    – D. Ben Knoble
    Jun 23, 2020 at 11:32
  • 1
    Once "refactored", I wonder if we don't already have Q/A's that address the atomic questions. Jun 23, 2020 at 11:41
  • 1
    @D.BenKnoble I've refactored the question. Is this okay? Jun 23, 2020 at 12:03
  • @LucHermitte most "atomic" questions here don't have answers with this context. As in they tell you what /after/, for instance, does but not how will that affect the following setup. That answer is probably helpful to experienced users but leave beginners like me kinda confused. Jun 23, 2020 at 12:05

1 Answer 1


Add filetype plugin indent on at the start of the main ~/.vimrc

Note that filetype plugin indent on is the default for Neovim; also it's in Vim's defaults.vim, so if you already have runtime defaults.vim (or vimrc is missing) you don't need it either. If you're unsure you can check the current setting by typing :filetype without any other parameters. If it's not yet here then add that line to your vimrc.

To elaborate on what it's really doing:

filetype on enables :h 'filetype' auto-detection by catching BufRead/BufNew events (within augroup filetypedetect) and analyzing buffer contents, or more often simply file extension. Note that setting :h 'filetype' also triggers FileType event for that buffer.

filetype plugin on enables filetype-based settings (mostly various buffer-local options) by catching FileType event (within augroup filetypeplugin). As FileType event is normally triggered by auto-detection routine, filetype plugin on also switches filetype on to save a few keystrokes.

filetype indent on is almost the same but it catches FileType event (within augroup filetypeindent) to install some custom indent-calculation procedure (typically by :h 'indentexpr'). As calculating indent on-the-fly is rather sophisticated procedure it was moved into a dedicated subplugin of its own and can be switched on or off independently of ftplugin thing.

Finally, filetype plugin indent on is a 3-in-1 command which enables all that ingredients.

Also, you might want to switch syntax highlighting on, so you'll probably need syntax on too. BTW. Although the syntax stuff has a command of its own, but ultimately it also depends on FileType event, and so syntax on also switches filetype on automatically.

Create folders ~/.vim/ftplugin/python.vim and ~/.vim/ftplugin/markdown.vim.

When the code in $VIMRUNTIME/ftplugin.vim receives FileType event it doesn't do anything there, but, for maximum flexibility, it sources all appropriate scripts to change the settings. Therefore, the effect depends on the order those scripts are sourced. It's all in :set rtp? - normally your ~/.vim precedes $VIMRUNTIME, which in turn precedes ~/.vim/after. And so if your settings are in ~/.vim/ftplugin/python.vim they may be (and will be) overwritten by $VIMRUNTIME/ftplugin/python.vim (in principle, you can add let b:did_ftplugin=1 and skip all that standard "python" stuff altogether, but usually it's not recommended). For this reason you normally want ~/.vim/after/ftplugin and not ~/.vim/ftplugin.

Any mistakes/gotchas in this?

Note that this code will be executed each time any buffer's 'filetype' is set to "python" (or "markdown"). Hence, you'd better do only buffer-local initialization. A thing like :packadd is hardly suitable here.

Having said this, almost all plugins have guards against multiple initialization, and so it should not really matter; but, anyway, it looks ugly to me. So I'd rather do:

if !exists('g:loaded_ale')
    packadd ale

This should at least save us from extra reading and parsing plugin/ale.vim. Also note that you misuse the "bang" in :packadd - read :h :packadd carefully.

  • Thank you so much for the detailed answer! It's cleared up a lot of vim-black-magic for me! :) I have a follow-up question about the last part. What do you mean when you say almost all plugins have guards against multiple initialization? For instance, let's say I want NERDTree to be active when I open a python file, but not for a markdown file. Because I've installed NERDTree in /opt, I need to manually load it (either from inside VIM or vimrc). If :packadd pkgname is not suitable to be used in a ftplugin, then how do I go about loading NERDTree when required? Jun 23, 2020 at 13:16
  • @theairbend3r Just put all plugins into /start, except ones used from time to time. Normally plugins are designed with autoload (i.e. "lazy-load") support. Don't overthink the things. Your best optimization is to remove the stuff you never use.
    – Matt
    Jun 23, 2020 at 14:44
  • This simplifies things a lot. So, all plugins in /start is the way to go. ftplugin will contain different .vim files for each language which will contain general stuff (no packadds). Jun 23, 2020 at 15:22
  • @theairbend3r the only thinks I packadd are language plugins where I don’t have the language installed on all the machines I use with those dotfiles (and even then, it doesn’t hurt to let those be in start). Another example would be if you have a plugin for a tool; you could packadd it only if the tool is installed. But again, that’s more complex than usually necessary.
    – D. Ben Knoble
    Jun 23, 2020 at 16:19
  • @D.BenKnoble I see. Thanks for the examples! :) Jun 24, 2020 at 7:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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