Guidelines for sculpting your very own
Unlike the many so-called "distributions", "templates" or "awesome
vimrc" you can find on the web, this is NOT meant to provide you with a working config, or help you bootstrap your config with opinionated "defaults", or tell you what to put in your config. Therefore, don't copy it to your
$HOME and expect it to do anything.
The purpose of this project is to document battle-tested best practices regarding Vim configuration. Use it as a reference, not as a starting point.
vimrc is something personal, that grows, shrinks and evolves over time, as you increase your Vim-fu and your needs change. While looking at other people's
vimrc can certainly be an interesting exercise, one should refrain from looking for solutions to non-existing problems.
Remember, kids... Pandajail is where pandas are sent when you use someone else's
vimrc. Don't be the vimmer responsible for this:
TABLE OF CONTENTS
- Files and directories
- Miscellaneous advice
- Custom commands
- Custom functions
- Suggested minimal settings for programming
FILES AND DIRECTORIES
Unless you really know what you are doing (hint: if you learn anything from this document, it means that you are not there yet), whatever you do to customize Vim should NEVER happen outside of your "home" directory, hereby referred to as
- on Linux, BSD, and Cygwin,
- on Mac OS X,
- on Windows,
If in doubt, open Vim and ask it:
Customizing Vim usually involves editing your own configuration file, called
vimrc, and moving files around your own runtime directory, called
The canonical location for your
vimrc file and
vimfiles directory is at the root of the
$HOME directory mentioned above:
Since Vim 7.4 it is possible to keep your lovely
vimrc INSIDE your
vimfiles. It is really a good idea, if only because it makes it easier to move your config from one machine to another.
The following gives you a neat self-contained setup from 7.4 up:
Here are a few things to keep in mind if you decide to move your
vimrc into your
.vimrcloses its dot and
_vimrcloses its underscore to be come
- Symbolic links can mess things up in all kinds of ways so make sure your
_vimrcis not already linked and that you actually move it rather than copying it.
For the sake of simplicity,
$HOME will be used in the rest of the document.
Using short names like
aimakes sense when you type them in the command-line but it is useless in your
vimrc, where it hinders readability while providing nothing in return. Don't.
Learning how to use Vim's fantastic documentation is the most useful thing a Vim newcomer could do:
:help :command :help function() :help 'option' :help i_ctrl-a :helpgrep foo :help get<C-d> Press <C-]> (Ctrl+]) on a highlighted tag to jump to the corresponding entry Press <C-t> (Ctrl+t) to come back
Always refer to the relevant
:helpbefore adding anything to your
vimrc, even from this document.
You don't need
set nocompatibleif you have a custom
vimrcat the expected location (see above).
set background=darkdoesn't do what you think it does.
set t_Co=256is a bad idea. Vim sets it on its own depending on
$TERMso set your terminal emulator up properly instead.
set pastehas a lot of nasty side effects, don't put it in your
vimrcbefore carefully reading
If you have many autocommands for many filetype-specific settings, consider moving those settings to proper filetype plugins:
If you have many custom functions, consider moving them to the
$HOME/.vim/autoload/myfunctions.vim call myfunctions#foo()
Vim already gives you the ability to browse local and remote file systems, integrate
rg, navigate, complete and compile your code, step through errors, run syntax checkers, read documentation, filter text through external commands, etc. Make sure you have exhausted Vim's features before installing a plugin. Any plugin.
Vim's spartan defaults having been a contentious topic for a very long time, it has been decided between the releases of Vim 7.4 and Vim 8.0 to provide newcomers with a more user-friendly base setup. The scheme that was devised is to silently source a specific runtime file,
defaults.vim if no
vimrc is found at the usual locations (see above). And indeed, it works as intended: simply starting Vim without a custom config truly provides a slightly more comfortable experience than previously.
One of the many troubles with that scheme is that embarking on the life-long journey of mastering Vim implies creating one's own
vimrc, which effectively disables
defaults.vim. This puts the new user in an even worse position than before: with the spartan defaults everyone likes to hate and no idea whatsoever about how to get back the admittedly useful things they got used to because
defaults.vim is pretty much a black box. Good job!
In case you happen to struggle with that particular problem, two quick and dirty solutions are offered under
:help defaults.vim. The first is to source that file in your
unlet! skip_defaults_vim source $VIMRUNTIME/defaults.vim
The second one is to copy its content in your
vimrc, which you can do like this:
:help :source and
NOTE: the author doesn't find any of those solutions particularly satisfying and recommends instead to try to understand what that file does and, eventually, to copy the most useful bits over to one's
There are three kinds of options:
- boolean options,
- string options,
- number options.
Checking the value of an option:
:set option?to check the value of an option,
:verbose set option?to also see where it was last set.
Getting help for an option:
:help 'optionname' :help 'optionname :help optionname'
Setting boolean options (
booloption is not a real option):
set booloption " Set booloption. set nobooloption " Unset booloption. set booloption! " Toggle booloption. set booloption& " Reset booloption to its default value.
Setting string options (
stroption is not a real option):
set stroption=baz " baz set stroption+=buzz " baz,buzz set stroption^=fizz " fizz,baz,buzz set stroption-=baz " fizz,buzz set stroption= " Unset stroption. set stroption& " Reset stroption to its default value.
Setting number options (
numoption is not a real option):
set numoption=1 " 1 set numoption+=2 " 1 + 2 = 3 set numoption-=1 " 3 - 1 = 2 set numoption^=8 " 2 * 8 = 16 set numoption& " Reset numoption to its default value.
- Don't put comments after mappings, it won't work.
:map <F6>to see what is mapped to
<F6>and in which mode.
:verbose map <F6>to also see where it was last mapped.
:map!cover too many modes. Use
:nmapfor normal mode recursive mappings,
:imapfor insert mode,
:xmapfor visual mode, etc.
- Unless they are provided by some built-in plugin like Netrw, Vim itself doesn't define any mapping. You do.
Use non-recursive mappings if you intend to ONLY use default commands in your mappings, which is almost always what you want:
nnoremap <key> yyp
Use recursive mappings ONLY if you intend to use other mappings in your mappings:
nnoremap b B nmap <key> db
Executing a command from a mapping:
nnoremap <key> :MyCommand<CR>
Executing multiple commands from a mapping:
nnoremap <key> :MyCommand <bar> MyOtherCommand <bar> SomeCommand<CR>
Calling a function from a mapping:
nnoremap <key> :call SomeFunction()<CR>
NOTE: since 8.2.1978, the recommended way to call Ex commands from a mapping is with
nnoremap <key> <Cmd>MyCommand<CR> nnoremap <key> <Cmd>MyCommand <bar> MyOtherCommand <bar> SomeCommand<CR> nnoremap <key> <Cmd>call SomeFunction()<CR>
The right-hand-side of a mapping is a macro, a series of keystrokes, everything there is typed for you so be careful with spaces and such. For example, the two mappings below don't do the same thing at all:
nnoremap <key> w i foo <Esc> nnoremap <key> wifoo<Esc>
Like most scripting languages, vimscript has variables.
One can define a variable with
let variable = value
Inspect its value with
And delete it with
Variables can be scoped by prepending a single letter and a colon to their name. Plugin authors use that feature to mimic options:
let g:plugin_variable = 1
or to keep variables "private":
let s:script_variable = 'foo'
Read up on the subject in
- Don't forget the bang to allow Vim to overwrite that command next time you reload your
- Custom commands must start with an uppercase character.
command! MyCommand call SomeFunction() command! MyOtherCommand command | Command | command
- Don't forget the bang to allow Vim to overwrite that function next time you reload your
- Don't forget the
abortto let your function abort early in case of errors.
- Custom functions must start with an uppercase character.
- As mentioned above, keeping one's custom functions under
$HOME/.vim/autoload/can be a good idea.
function! MyFunction(foo, bar) abort return a:foo . a:bar endfunction
- Autocommand groups are good for organization but they can be useful for debugging too. Think of them as small namespaces that you can enable/disable at will.
augroup MyGroup " Clear the autocommands of the current group to prevent them from piling " up each time you reload your vimrc. autocmd! " This autocmd calls the fictitious `MyFunction()` everytime Vim tries to " create/edit a buffer tied to a file in /`path/to/project/**/`. autocmd BufNew,BufEnter /path/to/project/**/* call MyFunction() augroup END
" Put an empty, self-clearing group somewhere near the top of your vimrc augroup MyGroup autocmd! augroup END " Add autocommands to that group from anywhere autocmd MyGroup BufNew,BufEnter /path/to/project/**/* call MyFunction()
Do something if Vim is the right version:
if v:version >= 704 " see :help v:version endif
Do something if Vim has the right patch-level:
if has('patch666') " see :help has-patch endif
Do something if Vim is built with
if has('feature') " see :help feature-list endif
Do something on Wednesdays:
if strftime("%u") == 3 " see :help time-functions endif
- GUI Vim (
gvim, GVim, or the MacVim GUI) can display millions of colors and thus provides the most flexibility.
- TUI Vim (
vimrunning in your terminal) is limited by the capabilities of your terminal emulator.
- GUI-specific colorschemes can't be expected to work in TUI Vim.
- TUI-specific colorschemes can't be expected to work in GUI Vim.
- To determine if a pretty colorscheme is right for your environment, look for the following clues:
guifgmeans GUI support and, probably, "true colors" support as well,
ctermfgmeans TUI support,
if &t_Co >= 256is a test to see if your terminal emulator supports 256 colors, which probably means that the scenario is supported to some extent,
if &t_Co >= 16is a test to see if your terminal emulator supports 16 colors, which probably means that the scenario is supported to some extent.
- Feature detection is not exactly a solved problem in Vim, so it is best not to assume anything.
The standard location for a standalone colorscheme is:
You can make it the current one with:
And persist that choice by adding this line to your
NOTE: most colorschemes these days are provided as "plugins". Read on to see how these work.
Vim does a lot but we can count on its thriving plugin ecosystem for when the built-in features are not enough. Look for plugins that:
- follow Vim's philosophy,
- don't duplicate built-in features,
- let you (re)define their mappings,
- don't have crazy requirements.
Vim plugins are to be installed in your
vimfiles directory and NOWHERE else.
Properly designed plugins usually follow Vim's own runtime directory's structure:
filetype-specific scripts are named after their filetype and go into
filetype-specific indent scripts are named after their filetype and go into
filetype-specific syntax scripts are named after their filetype and go into
autoloaded scripts go into
plugin scripts go into
plugin documentation goes into
Historically, the normal method for installing plugins was to put each file in its corresponding directory under one's
vimfiles, as above. It was messy and the more plugins you added the messier your
vimfiles would get.
To solve that problem, a number of what people call "plugin managers" appeared, all more or less built around the same logic: each plugin is kept in its own directory under a common parent directory and Vim is told where to find those plugins via
Note that using a plugin manager is not an absolute requirement. After all, the traditional way was messy but workable, but if you think you need one, make sure you read and understand its
README.md before using it.
Vim 8's "package" feature
Vim 8 introduced a new scheme called package that lets you organise your plugins in so-called "packages" and decide whether they are to be enabled at startup or manually:
||Plugins in this directory are enabled automatically at startup|
||Plugins in this directory are enabled manually|
For example, here is my setup:
$HOME/.vim/pack/bundle/start/is where I put all my "quality of life" plugins,
$HOME/.vim/pack/lang/start/is where I put all my "language support" plugins.
While that feature is a clear improvement, it is still not an actual plugin manager and you may still have to use one if you need one.
SUGGESTED MINIMAL SETTINGS FOR PROGRAMMING
How you customise your tools is entirely dependant on a) what you use them for and b) how well you know them, so YMMV. In that spirit, the settings below are only suggestions, based on what the author would do if he had to work on a new machine for a couple of hours and didn't feel like installing his full config.
" Enabling filetype support provides filetype-specific indenting, " syntax highlighting, omni-completion and other useful settings. filetype plugin indent on syntax on " `matchit.vim` is built-in so let's enable it! " Hit `%` on `if` to jump to `else`. runtime macros/matchit.vim " various settings set autoindent " Minimal automatic indenting for any filetype. set backspace=indent,eol,start " Intuitive backspace behavior. set hidden " Possibility to have more than one unsaved buffers. set incsearch " Incremental search, hit `<CR>` to stop. set ruler " Shows the current line number at the bottom-right " of the screen. set wildmenu " Great command-line completion, use `<Tab>` to move " around and `<CR>` to validate.