Developer
San Francisco, CA
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.
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:
vim
├── ftdetect
│ └── markdown.vim
├── ftplugin
│ └── gitcommit.vim
├── options.vim
├── plugins.vim
├── rcplugins
│ └── ctrlp.vim
tag-tmux
└── 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:
~/.vim
├── 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: https://github.com/thoughtbot/dotfiles/pull/471
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:
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.
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.
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.