This is my .vimrc file.
There are many like it, but this one is mine.
Outline
Introduction
I've used vim as my primary editor/IDE for the past 10 years. Back then I was writing data-analysis code over an ssh session to hosts in the SLAC computing center in California while sitting several thousand miles away in front of a terminal in the UK and a friendly post-doc showed me this nifty looking editor that he was using...
Since then I've been tempted away by a few shiny IDEs but always give up and come back to the venerable editor (one exception to this is intellij as it's a wonderful refactoring-engine for Java. By comparison Pycharm is rubbish IMHO).
And so I thought it might be useful to post about my .vimrc
file explaining what the various plugins and configuration options do. Since I've been writing a lot of python over the past year there's a bias here.
This scope of this post creeped up but it is mainly:
- a walk-through of my
.vimrc
file (anything not explained is hopefully obvious from the comments) - a litany of the useful vim-plugins therein and how/why to use them
- some general vim tips
Installation
If you want to skip to the goods you can clone my dot-files repo and run vim.sh to download and install all of the plugins below.
Updating to a more recent version of vim is usually trivial though, for Debian/Ubuntu you can do:
sudo add-apt-repository ppa:jonathonf/vim
sudo apt update
sudo apt install vim
If you don't have vim-8 installed all the plugins except ALE will work anyway.
Plugins
Vundle
Let's start with Vundle: a plugin manager for vim that also fetches plugins straight from Github. We start by setting the runtime-path (where Vundle will download the plugins files).
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'gmarik/Vundle.vim'
Navigating the local filesystem
NERDTree
NERDTree is for exploring the file-system and is sometimes useful for jumping between files in your current project. Personally I don't like this being open on-startup.
Plugin 'scrooloose/nerdtree'
" Open/close NERDTree Tabs with
let NERDTreeDirArrows=0
" To have NERDTree not open on startup
let g:nerdtree_tabs_open_on_console_startup = 0
A few highlights:
- to open a new NERDTree tab use
:NERDTree
- to open a file under the cursor in a v-split pane hit
s
. - closes like a normal vim tab
ctrlp
ctrlp is the most useful way to navigate between files while working on a project IMHO.
Plugin 'ctrlp/ctrlp.vim'
" search ctrlp with regex by default
let g:ctrlp_regexp_search = 1
let g:ctrlp_clear_cache_on_exit = 0
Quite simply, press Ctrl+p
while in normal mode to open a buffer that will match to filenames in the directory you're in (and recursively in it's sub-directories). The options I've set will:
- allow you to use regex to match filenamese
- cache the directory index (
F5
to refresh). This is useful if like me you ever have to work with a shared NFS mounts on which the indexing operation can be sluggish
Version control with Git
vim-fugitive
The vim-fugitive repo says it better than I could:
I'm not going to lie to you; fugitive.vim may very well be the best Git wrapper of all time
As someone that uses vim-fugitive to interface with git every day I don't consider this an understatement. This is a large topic but my top highlights are:
:GCommit, :Gpush, :Gpull
wrapgit {commit|push|pull}
:Gblame
: opens a vertical-split window with git-blame info, and you can then open a commit and see the diff in another bugger:Gdiff
: see diff output for the current file.- You can pass any command directly to git by starting a command with
:Git
, for example add the current file to the change-set with:Git add path/to/current/file
or just:Git add %
- we're using fugitive to display the git branch in the status line with the lightline plugin (see below).
Plugin 'tpope/vim-fugitive'
vim-gitgutter
vim-gitgutter complements fugitive by displaying the git sign for lines that have added/removed/updated in the current file (using the output git diff
)
Plugin 'airblade/vim-gitgutter'
Bonus: configure git to use vimdiff
vimdiff
is a diff-tool that opens a vertical-split window in vim. I find it much easier to see what's changed than when using git's in-built diff tool. Here we jump to my .gitconfig
:
[diff]
tool = vimdiff
[difftool]
prompt = false
[alias]
d = difftool
We can now look at the output of git diff
in vimdiff
. For example, to diff the curreent index with two commits ago you can do
git d HEAD~2
Highlights of this method is that when navigating the file in either window:
- the files can be edited as if they were normally opened files in vim
- "dp" will put the change under the current cursor to the other file
- "do" with obtain the change from the other file and apply it to the cursor position in the current file
Status Bar
lightline
lightline allows you to configure a snazzy status bar (at the bottom of the window). The snippet below will show:
- a color-scheme named
wombat
for the status-bar itself - the vim-mode (
INSERT
/NORMAL
/VISUAL
) - the git-branch if the file in the current buffer is part of a git repo (more on this later)
- the python-virtualenv in use (more on this later).
Plugin 'itchyny/lightline.vim'
" set lightline to include git-branch
let g:lightline = {
\ 'colorscheme': 'wombat',
\ 'active': {
\ 'left': [ [ 'mode', 'paste' ],
\ [ 'gitbranch', 'readonly', 'filename', 'modified' ] ,
\ [ 'venv', 'readonly'] ]
\ },
\ 'component_function': {
\ 'gitbranch': 'fugitive#head',
\ 'venv': 'virtualenv#statusline'
\ },
\ }
" Always show statusbar
set laststatus=2
This produces the following status bar:
Linting and syntax highlighting
Many people use syntastic for syntax highlighting in vim. It has one drawback which is that it runs synchonously in the main UI thread. ALE (Asynchronous Lint Engine) is arguably an asynchronous successor.
ale
ALE let's you specify specific linters for different languages. Below I've specified flake8
for linting and autopep8
for fixing syntax "errors".
Plugin 'w0rp/ale'
" pip install flake8
let g:ale_linters = {'python': ['flake8']}
let g:ale_fixers = {'python': ['remove_trailing_lines', 'trim_whitespace', 'autopep8']}
Note:
- this assumes flake8 and autopep8 are already installed
- any config for either in
~/.config/pep8
or~/.config/flake8
will be respected. - the linting is done asynchronously
- to apply the fixer (in this case
autopep8
) use the command:ALEFix
This produces:
Python
Here are a few plugins that are great for python specifically.
jedi-vim
jedi is probably the best auto-completion library for Python that I've ever used (including Pycharm). jedi-vim requires that your vim binary was compiled with the python
/python3
option but that's pretty much guaranteed unless you're compiling vim yourself.
" ------ jedi-python ------"
Plugin 'davidhalter/jedi-vim'
let g:jedi#popup_on_dot = 0
map <Leader>b Oimport pdb; pdb.set_trace() # BREAKPOINT<C-c>
Anyway, this is another large topic but here are a few highlights:
- autocomplete (
C-x-o
) - jump-to variable/method/function/class definition (
leader+g
)- this works with defined on
PYTHONPATH
(including in your virtual-env) but not egg files weirdly)
- this works with defined on
- find-usages (
leader+f
) - jump-to method/class/function/variable declaration (
leader+d
) - rename (
leader+r
) - show docstring with
K
- As a bonus:
leader+b
is remapped to add a pdb-breakpoint.
Below shows a few of these in action:
vim-virtualenv
vim-virtualenv allows you to set the python-virtualenv used in vim (and by extension jedi-vim
). You can set/unset it with :VirtualEnvActivate virtual_env_name
or :VirtualEnvDeactivate
.
tagbar
Personally I find tags of limited use, but they're handy for exploring a new or otherwise un-familiar codebase. Here we use tagbar.
" --- C-tags integration --- "
Plugin 'majutsushi/tagbar'
Note, this requires ctags
or similar to be installed, so for Debian/Ubuntu:
sudo apt-get install ctags
Then we can toggle the tagbar window with :Tagbar
and navigate code at a higher level of abstraction, as shown below.
Other useful plugins
Honourary mention to vim-go
and rust.vim
which provide great integration for those languages too.
Also, for keeping a work-log or wiki I can't recommend vimwiki enough: it is like an even-better org-mode ;-)
persistent-undo
This isn't a plugin but something I find useful for essentially caching the list of updates to a file such that if you close and re-open a file you can undo the last few edits (note, most vim distros in the wild will be compiled with the persistent_undo
")
" Keep undo history across sessions by storing it in a file
if has('persistent_undo')
let undo_dir = expand('$HOME/.vim/undo_dir')
if !isdirectory(undo_dir)
call mkdir(undo_dir, "", 0700)
endif
set undodir=$HOME/.vim/undo_dir
set undofile
endif
Colours
It's possible to set the colour-scheme directly in vim but these days most terminals (terminator for linux and iTerm2 for mac) have solarized colour schemes baked in. Once set, vim will use these and the job is done.
tmux
On a different note, tmux is a wonderful way to multiplex teminal sessions and I find it complements vim very nicely.
I could probably fill an equally lengthy post about tmux.
vim miscellany
Again, this is a much larger topic but here are a few tricks I find useful:
:sp
and:vs
will split the current window horizontally/verticallygg=G
will auto-indent the entire filee#
navigates to the previously opened file in the current buffer- vim macros are pretty rad
- you can use
%
as a shortcut for the current file-path in any command in command mode e.g. get it's md5-hash:! md5sum %
- you can read from stdin via a UNIX pipe with
vim -
, e.g.
>> curl example.com | vim -
Motivation
Warning: this section is opinionated.
You might ask: why bother with all this? Surely [insert GUI-based IDE + whatever else] is good enough?
Well, it may be good enough. But often when working on some data-analysis or building some service what matters far more than the length of time spent working is how long I can spend in a state of flow. This usually means being focussing on one thing; being un-distracted. Using this editor is a great way of staying focussed and minimising the operational overheads of software engineering.
Things I find good for staying focussed:
- Keeping my eyes fixed on one application
- Having things like auto-complete and linters
- Using as few keystrokes as possible for common tasks (eg. VCS commands, running tests)
Conversely, these have the opposite effect:
- Navigating menus
- Using a mouse at all
- Switching to another terminal window or (much) worse a web-GUI
So in a way these plugins and hotkeys are a way of making it easier to stay in the flow.
vim-8 is awesome
Most package managers will distribute binary versions of vim 7.4.XXXX which is fine. There are many reasons to update to vim version 8.X is but perhaps the biggest is that it allows tasks to be performed outside the main UI thread. All of the plugins we'll discuss will work fine with either version except for the ALE plugin that requires version 8+. Also, certain commonly-enabled compilation flags (python
and persistent_undo
are assumed).
Wrapping up
Putting it altogether, what I focus on while working usually looks something like this.
If you've made it this far I hope found it useful.
Go Top