Dan Lowe

Thoughts on life, the universe, and everything.

Indenting Ruby in Vim

Whenever possible, I code in TextMate. TextMate is good at a lot of things; one of them is remembering that in Ruby I want a tab stop of two, not four like in most other languages.

But frequently, it’s easier for me to code in Vim on my servers, over an SSH connection. Here’s where I run into trouble. My .vimrc file has the general coding defaults I prefer:

1
2
3
4
5
set autoindent
set expandtab
set tabstop=4
set shiftwidth=4
set textwidth=0

I have mappings to easily swap syntaxes in-buffer, such as these.

1
2
3
4
let mapleader=","
map <Leader>spe :set syntax=perl   ai et ts=4 sw=4 tw=0<CR>
map <Leader>spy :set syntax=python ai et ts=4 sw=4 tw=0<CR>
map <Leader>sr  :set syntax=ruby   ai et ts=2 sw=2 tw=0<CR>

I have autocommands based on filenames (for cases where the syntax isn’t autodetected).

1
2
3
4
" .t is generally a perl test script
au BufEnter *.t   set syntax=perl ai et ts=4 sw=4 tw=0
" .inc is generally PHP
au BufEnter *.inc set syntax=php  ai et ts=4 sw=4 tw=0

Yet I still have the issue where I edit a Ruby file, the syntax is autodetected, and I end up with shiftwidth=4 because that’s the default. I can tap ,sr but that’s inconvenient to do every time. I can’t use an autocommand because these files don’t end in a predictable extension.

It turns out that Vim has a way to let you define settings per syntax at buffer load time, using Vim scripts inside the ~/.vim directory. I added this to the global .bash_profile that I use everywhere. This Vim script is automatically created whenever I log in.

1
2
3
# Ruby-specific vim settings
mkdir -p $HOME/.vim/after/syntax
echo "set ai et ts=2 sw=2 tw=0" > $HOME/.vim/after/syntax/ruby.vim

Now, these settings are applied whenever Vim detects I’ve entered a file with Ruby syntax, regardless of filename. Works like a charm.

You can use this trick to do anything you want using any supported Vim syntax; just name a file after the syntax in question (perl, php, m4, etc).