Yet Another vimrc post

Posted on septembre 15, 2017 in Development

Hello,

The question is a classic on r/vim and comes occasionally on #vim on freenode : is my vimrc "good" and what should I do to make it "better" ? I am by no means a vim expert and I don't really know what a "good" vimrc should be. So anything that I do here is not necessarily good ; I just want to explain why I made some decisions for my configuration.

For the context, I'm using vim as a text editor for C family code (including one big C++98 project)

Like a lot of people before me, I started by using a lot of plugins in vim, and keeping them up-to-date and installing them was something I deemed non-important that I left to plugin managers. After encountering my first plugin issue (how to properly handle out-of-source compilation databases using YCM), I thought that all that time spent looking into the behaviour of this plugin could be spent trying to understand how vim works and how I could use as few plugins as possible to avoid going through this again.

My current vimrc is always on Github, but this is not always streamlined so there is a little explanation for each of the big parts. Also, for a lot of plugins there is a fold for its specific options, and I decided not to talk about these, since it's really detailed in their documentation. The point of this post is to explain some plugin choices.

Auto-source vimrc

augroup VimrcAutoSource
    autocmd!
    autocmd BufWritePost $MYVIMRC nested source $MYVIMRC
augroup END

This small snippet automatically sources my vimrc file when I write it to disk. Nothing much to say here, it's just a convenience when I'm trying new settings in a split.

Plugin Manager

I'm still using a plugin manager today because, even though knowing how vim loads plugins is interesting, updating the plugins can be a chore. I chose to use Plug as a plugin manager because it also allows conditionnal loading, but I'm not using it yet. Since the loading command for plugins is mostly a github address, it'll also be easier for you to check them out if you want to.

Plugins

I am currently loading 18 plugins each time I start up vim, and a few of them could certainly only be loaded for certain filetypes (namely Python and C-family). I'll go quickly through each one.

Snippets

Plug 'SirVer/ultisnips'
Plug 'honza/vim-snippets'

I'm using Ultisnips because it looked like it was easier to create our own snippets. We are using a custom markup languauge at work which can be tedious at times, and having a handful of snippets makes editing files in this language a lot easier. honza/vim-snippets is a repository full of "default" snippets, that I still did not use, but it's light and it's good to know it's here for when I don't want to write the same boilerplate over and over.

Testing

Plug 'junegunn/vader.vim'

I installed this vimscript test framework when I submitted a pull request for another plugin I'm using (ale). Not much else to say, it does what it does and I will surely remove it as I don't plan on needing it anytime soon.

Linting

Plug 'w0rp/ale'
Plug 'rhysd/vim-clang-format'
Plug 'tell-k/vim-autopep8'

Clang-format and vim-autopep8 are C-family and Python linters that also modify the buffer whenever I want thanks to autocommands. It's a convenience to only concentrate on code.

The big linter I'm using is ALE, mostly for being an asynchronous :make wrapper that shows me mistakes before I try to compile. I used to use Syntastic but the async feature proved necessary quickly : I had issues with a project big enough so vim took 10 seconds to leave me in normal mode after opening a files. The main linters I use with ale are pylint, clang and clangcheck, vint and lacheck for latex files. Having a proper setting to use pylint or pylint-3 is the next step to enhance my experience with Python linting.

Completion plugins

Plug 'lifepillar/vim-mucomplete'
Plug 'Gagbo/clang_complete'
Plug 'lervag/vimtex'

I chose mucomplete for the completion engine because to me it seemed better integrated and easier to control than VCM.

This completion plugin works really well with clang_complete (currently forked because I want a better support for out-of-source builds), which uses libclang capabilities (around LibTooling) to propose proper omni completion for C and C++. I used the tags-powered OmniCppComplete after YCM because I wanted to use an "as bare as possible" approach, but when I saw the 2 Gb tags file for /usr/include, I thought that a python-powered approach was better, since I really wanted to have context-aware code completion. Similarly, vimtex proposes context-aware completion when editing LaTeX files, and a very nice continuous compilation feature (which updates the pdf file on write).

Miscellaneous

Plug 'romainl/Apprentice'
Plug 'tpope/vim-fugitive'
Plug 'tpope/vim-unimpaired'
Plug 'tpope/vim-surround'
Plug 'tpope/vim-commentary'
Plug 'romainl/vim-qf'
Plug 'tommcdo/vim-lion'
Plug 'vim-scripts/a.vim'
Plug 'romainl/vim-cool'

All of these plugins add a functionality that I did not want to implement myself (and, for the most part, that I can't implement myself). - Apprentice is a nice dark, low-contrast colourscheme - Fugitive is a git wrapper - Unimpaired adds a lot of [ ] bindings - Surround gives a mapping to surrounding text-objects - Commentary gives a mapping to comment motion/text-objects - qf enhances quickfix list - lion gives a mapping to arbitrarily align lines - a gives a mapping to switch between header and implementation files - cool handles search highlighting

Set Commands

These commands are my "basics" of vim. They should not depend on the plugins I choose, but the plugins I want should depend on the settings I am using in this block. For the most part, the comments should be enough, there won't be a lot of text.

Files loading

" Helper files loading {{{2
set exrc
set secure
set tags=tags;
set path=.,/usr/include,**,,build;
" 2}}}

These commands allow vim to use project local .vimrc configuration files, and also help find the right files for built-in commands.

Backups and undo files

" Backups and Undo File {{{2
if has('vms')
    set nobackup                        " do not keep a backup file, use versions instead
else
    set backup                          " keep a backup file (restore to previous version)
    set backupdir=./.backup,/tmp        " Hides the backup files if the folder is created
    set undofile                        " keep an undo file (undo changes after closing)
    set undodir=./.backup,/tmp          " Hides the backup files if the folder is created
endif
set wildignore+=~,*.o,*.obj,*.swp
" 2}}}

Editor panel

" Editor window options {{{2
if &t_Co > 2 || has('gui_running')
    syntax on
    " Also switch on highlighting the last used search pattern.
    set hlsearch
endif
set autoindent
set number
set ruler        " show the cursor position all the time
set scrolloff=5  " Start scrolling 5 lines from border
set incsearch    " do incremental searching

set diffopt=filler,vertical

set foldmethod=marker
set foldcolumn=3
set foldlevelstart=999
" 2}}}

Buffer options

" Buffer options {{{2
set hidden
highlight ColorColumn ctermbg=magenta
" call matchadd('ColorColumn', '\%81v', 100)
set switchbuf=useopen,usetab,split
set listchars=tab:»·,trail:·,nbsp:~
set list
" 2}}}

Statusline

" StatusLine options {{{2
set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:h\")})%)
set laststatus=2   "Always (=2) display a statusline
set statusline=%{fugitive#statusline()}%f%m%r%h%w\ %y%<%=%{ALEGetStatusLine()}[%{&ff}][%p%%][Line\ %04l/%04L,Col\ %v]
"                                      | | | | |   | | |                       |       |           |    |         |
"                                      | | | | |   | | |                       |       |           |    |         +-- current column
"                                      | | | | |   | | |                       |       |           |    +-- Number of lines
"                                      | | | | |   | | |                       |       |           +-- current line
"                                      | | | | |   | | |                       |       +-- current % into file
"                                      | | | | |   | | |                       +-- current fileformat
"                                      | | | | |   | | +-- Right align starting here
"                                      | | | | |   | +-- truncate here if too long
"                                      | | | | |   +-- current ft
"                                      | | | | +-- preview flag in square brackets
"                                      | | | +-- help flag in square brackets
"                                      | | +-- readonly flag in square brackets
"                                      | +-- modified flag in square brackets
"                                      +-- Path to the file in the buffer, as typed or relative to current directory.

" 2}}}

Command Window

" Command window options {{{2
set history=50     " keep 50 lines of command line history
set showcmd        " display incomplete commands
set wildmenu
set wildmode=longest:full,full
" 2}}}

Tabs, spaces and backspace

" Tabulations and Keystrokes behaviour{{{2
set mouse=a
set mousemodel=popup
set backspace=indent,eol,start

set shiftwidth=4
" Use sw value for sts
set softtabstop=-1
set smarttab
set expandtab
" 2}}}

Completion

" Completion behaviour{{{2
set completeopt+=menuone
set completeopt+=menu
set completeopt+=preview
set completeopt+=noinsert

" incl and tags are included as mucomplete chains so we can remove these from
" <C-N> / <C-P> completion
set complete-=i
set complete-=t

set shortmess+=c " less verbose vim during completion
set noinfercase
" 2}}}

Mappings and colour options

Those settings are mostly personal, is the ctags command to use with OmniCppComplete, and the myHelpers functions are copied from D. Conway and romainl

" Mapping {{{1
" Tag related {{{2
map <C-p> :tab split<CR>:exec("tag ".expand("<cword>"))<CR>
nnoremap gt <C-]>
nnoremap <F8> :!ctags -R --sort=yes --c++-kinds=+pl --fields=+iaS --extra=+q .<CR><CR>
" 2}}}

" Buffer navigation {{{2
nnoremap gb :ls<CR>:b<Space>
nnoremap <PageUp>   :bprevious<CR>
nnoremap <PageDown> :bnext<CR>
" 2}}}

" Window navigation {{{2
map <C-h> <C-w>h
map <C-j> <C-w>j
map <C-k> <C-w>k
map <C-l> <C-w>l

" 2}}}

" Search highlighting {{{2
nnoremap <silent> n n:call myHelpers#HLNext(0.2)<CR>
nnoremap <silent> N N:call myHelpers#HLNext(0.2)<CR>
"  2}}}

" US Keyboard keybinds {{{2
noremap ; :
noremap : ;
" 2}}}
" 1}}}

" Colorschemes {{{1
augroup MyColors
autocmd!
    autocmd ColorScheme * call myHelpers#MyHighlights()
augroup END

colorscheme apprentice
" 1}}}

" Gui Options {{{1
set guifont=Hack\ 11
set guioptions+=i
set guioptions-=T
" 1}}}

The End

I hope you enjoyed the ride ! The next post should be my coming back to nand2tetris, hopefully soon. Stay safe, Gerry