My ~/.vim/ directory has evolved over many years and it works well enough for my day-to-day development and admin tasks, but I feel there is some cruft in there that isn’t necessary anymore and some settings that could be improved or organized a little better.
The impetus for taking on this project was the ALE plugin. I’ve always used pathogen for managing package installation, but if you have Vim 8 or NeoVim, ALE recommends using Vim native package management to install the plugin. I heard that Vim added package management into the core, but had never looked into it. So I read this and decided to replace pathogen. One thing led to another and I ended up doing a little yak shaving and here we are😃
Seriously though, I’ve never taken the time to really dive in to become an “expert” in Vim configuration, and I strongly believe there is a lot of advantage in deeply understanding the tools I use. This series of posts are an attempt at getting a little closer to that “expert” status.
Debian Default Config
Debian is my Linux distro of choice, so the first thing I want to understand is what do the default settings look like right after
sudo apt install vim-gtk3 (I use vim-gtk3 instead of vim or vim-nox because I need system clipboard integration for copying and pasting from a web browser, etc.) A lot of thought has presumably gone into these default configs, so they should make a good starting point. At a minimum, understanding the defaults will at least let me make informed decisions when my settings contradict them.
The first config file that gets processed is /etc/vim/vimrc. Besides a bunch of comments (which are a good read), it just loads $VIMRUNTIME/debian.vim and then /etc/vim/vimrc.local (if it exists). The comments also explain that $VIMRUNTIME/defaults.vim is loaded afterwards if the user does not have a vimrc file.
Most of the commented out suggestions are covered in debian.vim or defaults.vim below, but a few are worth noting here:
set background=dark. This is the default in non-gui mode, but it might be worth setting explicitly if I want dark background for gui also.
set showmatch. This is useful to show the matching bracket.
set ignorecase, and
set smartcase. This can be useful when searching, but it can also be counter productive in code when searching for just an all-lowercase variable.
set autowrite. This is handy for autosaving when running
set hidden. Not sure of the value of this. Need to investigate.
" /etc/vim/vimrc " All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by " the call to :runtime you can find below. If you wish to change any of those " settings, you should do it in this file (/etc/vim/vimrc), since debian.vim " will be overwritten every time an upgrade of the vim packages is performed. " It is recommended to make changes after sourcing debian.vim since it alters " the value of the 'compatible' option. " This line should not be removed as it ensures that various options are " properly set to work with the Vim-related packages available in Debian. runtime! debian.vim " Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc. " This happens after /etc/vim/vimrc(.local) are loaded, so it will override " any settings in these files. " If you don't want that to happen, uncomment the below line to prevent " defaults.vim from being loaded. " let g:skip_defaults_vim = 1 " Uncomment the next line to make Vim more Vi-compatible " NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous " options, so any other options should be set AFTER setting 'compatible'. "set compatible " Vim5 and later versions support syntax highlighting. Uncommenting the next " line enables syntax highlighting by default. "syntax on " If using a dark background within the editing area and syntax highlighting " turn on this option as well "set background=dark " Uncomment the following to have Vim jump to the last position when " reopening a file "if has("autocmd") " au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif "endif " Uncomment the following to have Vim load indentation rules and plugins " according to the detected filetype. "if has("autocmd") " filetype plugin indent on "endif " The following are commented out as they cause vim to behave a lot " differently from regular Vi. They are highly recommended though. "set showcmd " Show (partial) command in status line. "set showmatch " Show matching brackets. "set ignorecase " Do case insensitive matching "set smartcase " Do smart case matching "set incsearch " Incremental search "set autowrite " Automatically save before commands like :next and :make "set hidden " Hide buffers when they are abandoned "set mouse=a " Enable mouse usage (all modes) " Source a global configuration file if available if filereadable("/etc/vim/vimrc.local") source /etc/vim/vimrc.local endif
Next, lets look at $VIMRUNTIME/debian.vim first, but where is $VIMRUNTIME? To find out, open vim and type:
On my machine, it prints
A quick summary of what this file does:
- Sets all directories where Vim should look for setting files.
set nocompatible. Enables Vim extensions (breaking compatibility with standard Vi).
set backspace=indent,eol,start. Makes backspace delete indents, line endings, etc. (It is really annoying to use Vim without this!)
set history=50Extends command history to 50.
set ruler. Enables the ruler (shows cursor position on the bottom line, etc.)
set nomodeline. Disables modelines (vim config settings within the file being edited).
- Sets which file suffixes to ignore (de-prioritize) when doing tab completion.
- Sets the number of terminal colors and the ANSI escape code patterns for setting the forground and background color. This reminds me: I need to do a post on ANSI escape codes. t_Co sets the number of colors. t_Sf sets the foreground color, and t_Sb sets the background color. The escape code for foreground color starts with an escape character (hex 0x1b, shows up as `^[` in Vim) then a “[” then a number 30 thru 37 and ends with “m”. Example to change foreground to red: `^[[31m`. Instead of the second digit, when setting t_Sf we use the format specifier `%d` to indicate “one decimal digit”, so the result is `t_Sf=^[[3%dm` (remember, in the actual debian.vim file, the `^[` is the actual single byte escape character. Background color is similar, but the colors are in range 40 thru 47 so the result is `t_Sb=^[[4%dm`.
- Makes shift-insert paste in gui mode like it does in xterm.
- sets the paper size from debian config.
" /usr/share/vim/vim80/debian.vim " Debian system-wide default configuration Vim set runtimepath=~/.vim,/var/lib/vim/addons,/usr/share/vim/vimfiles,/usr/share/vim/vim80,/usr/share/vim/vimfiles/after,/var/lib/vim/addons/after,~/.vim/after " Normally we use vim-extensions. If you want true vi-compatibility " remove change the following statements set nocompatible " Use Vim defaults instead of 100% vi compatibility set backspace=indent,eol,start " more powerful backspacing " Now we set some defaults for the editor set history=50 " keep 50 lines of command line history set ruler " show the cursor position all the time " modelines have historically been a source of security/resource " vulnerabilities -- disable by default, even when 'nocompatible' is set set nomodeline " Suffixes that get lower priority when doing tab completion for filenames. " These are files we are not likely to want to edit or read. set suffixes=.bak,~,.swp,.o,.info,.aux,.log,.dvi,.bbl,.blg,.brf,.cb,.ind,.idx,.ilg,.inx,.out,.toc " We know xterm-debian is a color terminal if &term =~ "xterm-debian" || &term =~ "xterm-xfree86" set t_Co=16 set t_Sf=[3%dm set t_Sb=[4%dm endif " Some Debian-specific things if has("autocmd") if has('gui') " Make shift-insert work like in Xterm autocmd GUIEnter * if empty(maparg("
", "nvso")) | execute "map " | endif autocmd GUIEnter * if empty(maparg(" ", "ic")) | execute "map! " | endif endif endif " Set paper size from /etc/papersize if available (Debian-specific) if filereadable("/etc/papersize") let s:papersize = matchstr(readfile('/etc/papersize', '', 1), '\p*') if strlen(s:papersize) exe "set printoptions+=paper:" . s:papersize endif endif
Next up is the Vim defaults. If you have a custom vimrc file, these settings are not loaded, but they are worth looking at because they make a sane starting point for a custom vimrc.
Briefly, this file (skipping stuff already described in debian.vim):
- Does some checks to make sure it should be applied.
- Increases history a little more than debian.vim.
set showcmd: Shows the command you just typed in the bottom line. e.g., if in normal mode you type
f+after you type
fit will show
fin the last line. Also shows number of lines selected in visual mode, etc.
set wildmenu: Shows command completions.
set ttimeoutlen=100: The purpose of this is a little confusing. Key codes such as
<Esc>can be mapped with other keys to perform commands, so if you have any of these mappings such as
map <Esc>w :w<CR>whenever you press
<Esc>, Vim has to wait to see if you are going to press
<Esc>is so heavily used by itself, you don’t want to wait the default timeout (1000ms) that is used for other mappings (e.g.,
gqso this setting lets you have a shorter timeout for
set display=truncate: Puts a
@@@on the last line of the screen when one line won’t fit on the entire screen to indicate that the line is truncated.
set scrolloff=5. Makes a few lines show at the bottom of the screen below the cursor when scroll down (or top of the screen when scrolling up).
set incsearch. Makes
?searches go to results as you type instead of waiting until you hit enter.
set nrformats-=octal: Removes octal from nrformats. This is another confusing one. If you put your cursor over a number, then type a number and press
<C-A>, it increments the number under the cursor by that amount. For example, if you move the cursor over the number 7, then type
<C-A>, the 7 changes to 10. Without removing octal from nrformats, if you move your cursor over 007 then type
<C-A>, it will interpret the 007 as an octal number and increment it to 012 instead of 010. (012 in octal is 10 in decimal). This probably isn’t what most people want so it does make sense to remove octal.
set guioptions-=t: Eliminates some menu entries in gui mode. I do use my vimrc on windows as well as Linux and OSX and I like a stripped down interface, so this is useful.
map Q gq: For formatting. I’m used to using
gq, so this is not very useful to me.
inoremap <C-U> <C-G>u<C-U>. I’m not quite sure what problem this solves…
set mouse=a. Enables the use of a mouse for all modes.
syntax on: Enables syntax highlighting.
let c_comment_strings=1: Highlights strings inside C comments.
filetype plugin indent on: Enables filetype detection, plugins and indention.
- Adds an autocmd to jump to the last known cursor position when returning to a file.
- Adds a command
:DiffOrigto diff the buffer with the original file. Could be useful.
- Disables langremap. Not sure of the problem this solves, but not applicable to me.
" /usr/share/vim/vim80/defaults.vim " The default vimrc file. " " Maintainer: Bram Moolenaar <Bram@vim.org> " Last change: 2016 Sep 02 " " This is loaded if no vimrc file was found. " Except when Vim is run with "-u NONE" or "-C". " Individual settings can be reverted with ":set option&". " Other commands can be reverted as mentioned below. " When started as "evim", evim.vim will already have done these settings. if v:progname =~? "evim" finish endif " Bail out if something that ran earlier, e.g. a system wide vimrc, does not " want Vim to use these default values. if exists('skip_defaults_vim') finish endif " Use Vim settings, rather than Vi settings (much better!). " This must be first, because it changes other options as a side effect. set nocompatible " Allow backspacing over everything in insert mode. set backspace=indent,eol,start set history=200 " keep 200 lines of command line history set ruler " show the cursor position all the time set showcmd " display incomplete commands set wildmenu " display completion matches in a status line set ttimeout " time out for key codes set ttimeoutlen=100 " wait up to 100ms after Esc for special key " Show @@@ in the last line if it is truncated. set display=truncate " Show a few lines of context around the cursor. Note that this makes the " text scroll if you mouse-click near the start or end of the window. set scrolloff=5 " Do incremental searching when it's possible to timeout. if has('reltime') set incsearch endif " Do not recognize octal numbers for Ctrl-A and Ctrl-X, most users find it " confusing. set nrformats-=octal " For Win32 GUI: remove 't' flag from 'guioptions': no tearoff menu entries. if has('win32') set guioptions-=t endif " Don't use Ex mode, use Q for formatting. " Revert with ":unmap Q". map Q gq " CTRL-U in insert mode deletes a lot. Use CTRL-G u to first break undo, " so that you can undo CTRL-U after inserting a line break. " Revert with ":iunmap <C-U>". inoremap <C-U> <C-G>u<C-U> " In many terminal emulators the mouse works just fine. By enabling it you " can position the cursor, Visually select and scroll with the mouse. if has('mouse') set mouse=a endif " Switch syntax highlighting on when the terminal has colors or when using the " GUI (which always has colors). if &t_Co > 2 || has("gui_running") " Revert with ":syntax off". syntax on " I like highlighting strings inside C comments. " Revert with ":unlet c_comment_strings". let c_comment_strings=1 endif " Only do this part when compiled with support for autocommands. if has("autocmd") " Enable file type detection. " Use the default filetype settings, so that mail gets 'tw' set to 72, " 'cindent' is on in C files, etc. " Also load indent files, to automatically do language-dependent indenting. " Revert with ":filetype off". filetype plugin indent on " Put these in an autocmd group, so that you can revert them with: " ":augroup vimStartup | au! | augroup END" augroup vimStartup au! " When editing a file, always jump to the last known cursor position. " Don't do it when the position is invalid or when inside an event handler " (happens when dropping a file on gvim). autocmd BufReadPost * \ if line("'\"") >= 1 && line("'\"") <= line("$") | \ exe "normal! g`\"" | \ endif augroup END endif " has("autocmd") " Convenient command to see the difference between the current buffer and the " file it was loaded from, thus the changes you made. " Only define it when not defined already. " Revert with: ":delcommand DiffOrig". if !exists(":DiffOrig") command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_ | diffthis \ | wincmd p | diffthis endif if has('langmap') && exists('+langremap') " Prevent that the langmap option applies to characters that result from a " mapping. If set (default), this may break plugins (but it's backward " compatible). set nolangremap endif
I now have a solid understanding of all of the default settings in play when I install Vim so I’m prepared to distill those defaults down to a good base .vimrc file. In a future post, I’ll show the result.