How I

Gabriel Berke-Williams


San Francisco, CA

Who are you and what do you use Vim for?

My name is Gabriel Berke-Williams and I am a developer at thoughtbot.

I started using Vim years and years ago, but didn’t read the :help enough and started using Textmate instead because I thought it had more features. Once I got to thoughtbot, I was surrounded by really great Vimmers and I switched back to Vim. I use Vim write all of my code (Ruby, and increasingly Haskell) and all of my blog posts. Sometimes I even use it to write long pull request comments. I love Vim because I can move almost faster than I can think. Typing anywhere except Vim feels slow without the modal bindings.

I use the latest Vim version available in Homebrew (currently 7.4.x), and I check for updates every few days. I use terminal vim because all of my workflow is terminal based, and a graphical editor like gvim would break that flow.

Introduce us to your Vim config.

I’ve spent a lot of time – probably too much time! – on my Vim config, and I’m adding bits and pieces constantly. It’s all public in my dotfiles repo. I’ve tried to make it visitor-friendly, with lots of comments and documentation. (Check it out and open an issue!)

My Vim configuration is very split up. It’s a little complex, so if you’re confused, or would like some help improving your own Vim configuration, let me know on Twitter.

I use rcm, which is a tool that symlinks files from a separate dotfiles directory (say, ~/.dotfiles) directly into your home directory. Any non-dot file or directory under the dotfiles directory will be installed as a dotfile. For example, .dotfiles/zshrc will be installed into ~/.zshrc.

rcm lets me split up my dotfiles into different tags, so I can have separate directories for tmux settings, git settings, etc. Each tool has its own extra Vim settings – if someone wants to use my dotfiles but doesn’t use tmux, then they can easily exclude tmux-specific Vim configuration with rcm since it’s in its own directory. I like being able to point people to specific settings, e.g. for tmux or Haskell.

Here’s a simplified diagram of my ~/.dotfiles directory, which rcm links into ~/.vim, ~/.zshrc, etc:

├── ftdetect
│   └── markdown.vim
├── ftplugin
│   └── gitcommit.vim
├── options.vim
├── plugins.vim
├── rcplugins
│   └── ctrlp.vim
└── vim
    ├── ftdetect
    │   └── tmux.vim
    ├── plugins
    │   └── tmux.vim
    ├── rcplugins
    │   └── vim-tmux-runner.vim
    └── tmux.vim

The rcplugins folder holds plugin-specific configuration, like ctrlp.vim-specific settings.

All of my Vim settings go in the vim/ directory. I have my “main” plugins in vim/plugins.vim, and tool-specific plugins in tag-PLUGIN_NAME/vim/plugins/PLUGIN_NAME.vim. That way people who don’t use a given tool (like tmux) don’t pull in tmux-specific Vim plugins. It also makes it easier for me to give advice to people who are setting up tmux (or whatever) for the first time, because all the plugins are in the same place.

You can see that the tag-tmux/vim structure mimics the vim/ structure – that’s because rcm will copy them both into the ~/.vim directory together, so the separation is invisible to Vim. That’s a little hard to visualize, so here’s the (simplified) output of tree ~/.vim, assuming the same structure as above:

├── autocommand.vim -> /Users/gabe/.dotfiles/vim/autocommand.vim
├── autoload
│   └── plug.vim -> /Users/gabe/.dotfiles/vim/autoload/plug.vim
├── ftdetect
│   ├── markdown.vim -> /Users/gabe/.dotfiles/vim/ftdetect/markdown.vim
│   └── tmux.vim -> /Users/gabe/.dotfiles/tag-tmux/vim/ftdetect/tmux.vim
├── ftplugin
│   └── gitcommit.vim -> /Users/gabe/.dotfiles/vim/ftplugin/gitcommit.vim
├── options.vim -> /Users/gabe/.dotfiles/vim/options.vim
├── plugins
│   └── tmux.vim -> /Users/gabe/.dotfiles/tag-tmux/vim/plugins/tmux.vim
├── plugins.vim -> /Users/gabe/.dotfiles/vim/plugins.vim
├── rcplugins
│   ├── ctrlp.vim -> /Users/gabe/.dotfiles/vim/rcplugins/ctrlp.vim
│   └── vim-tmux-runner.vim -> /Users/gabe/.dotfiles/tag-tmux/vim/rcplugins/vim-tmux-runner.vim
└── tmux.vim -> /Users/gabe/.dotfiles/tag-tmux/vim/tmux.vim

This structure lets me split up my configuration but still have it all in one place at the end for Vim to read.

Here are my base options:

set showcmd
set smarttab
set cursorline
set ignorecase
set incsearch
set smartcase
set relativenumber
set number
set autowrite
" Set leader to <Space>
set leader=" "

My leader is Space because it’s a big key that’s easy to hit, and I can type it with either hand.

And here are some options I like that are less common:

" When the type of shell script is /bin/sh, assume a POSIX-compatible shell for
" syntax highlighting purposes.
" More on why:
let g:is_posix = 1

" Open below and to the right, the same way you read a page
set splitbelow splitright

My most-surprising option is definitely set scrolloff=999. It keeps the cursor in the middle of the page while the text moves around it. I like it because it makes it easier to track where the cursor is. (Though it’s made some people a little dizzy when pairing!)

I use a lot of plugins, which I manage with junegunn’s excellent vim-plug. I used to use Vundle, but vim-plug is much more actively maintained and has support for parallel installation. My favorite plugins are all from Tim Pope and my coworker Chris Toomey:

I have a bunch of Ruby/Rails plugins, including vim-ruby, vim-rails, vim-rake (which is vim-rails, but for Ruby projects) and vim-spec-runner, which I wrote with Chris Toomey, which I use for running RSpec tests. It works really nicely with vim-tmux-runner.

I use ctrlp.vim for fuzzy finding. I’ve configured it to use ag under the hood, which is so fast that I don’t even need to cache:

let g:ctrlp_user_command = 'ag %s -l --hidden --nocolor -g ""'
let g:ctrlp_use_caching = 0

One holdover from my Textmate days is that I use <Leader>t to trigger ctrlp.vim, to mimic Cmd-t:

let g:ctrlp_map = '<Leader>t'

Here are some non-language-specific plugins I can’t live without:

What have been the most useful resources for you to learn Vim?

My coworkers Chris Toomey and Gordon Fontenot are Vim tinkerers like me, so we watch each other’s dotfiles on GitHub, comment on neat stuff, and copy what looks cool. All three of us have a lot of code with comments like “Thanks Gordon!” or “Stolen wholesale from christoomey”. Pairing with other people has been the best way for me to learn Vim. At some point during the pairing they’ll do something cool and I’ll ask about it, which always leads to me learning something new. Steve Losh’s Learn Vimscript the Hard Way was invaluable when I decided to write my first Vim plugin.

What’s the most recent thing you’ve learned about Vim?

I learned that there’s an autocommand for when Vim is resized. It’s really helpful because it gets triggered whenever I open a tmux split next to Vim. I use it to resize all of the Vim splits when Vim is resized:

autocmd VimResized * wincmd =

Chris Toomey also reminded me how great custom text objects and “verbs” are, and introduced me to some new ones. The most useful one recently is vim-textobj-entire, which when combined with Chris’s vim-system-copy plugin lets me do cpae to copy an entire file to the system clipboard for pasting in other places.

How did you get started writing Vim plugins?

I’d been using Vim for a while and wanted to get to know my editor more. I read Learn Vimscript the Hard Way, played around with it, then paired with Chris Toomey to write vim-spec-runner. We wrote vim-spec-runner for a couple of reasons:

After that I felt confident enough to write vim-rdio, which is a totally absurd plugin that uses Vim to run AppleScript to send commands to an Rdio tab in Chrome or Firefox. It was a neat technical challenge (I wrote about it) and worked well, until Rdio tragically shut down.