Vim Learning Curve

Because I’ve been doing a lot of remote pair programming using vim and screen, I’ve been making a real effort to improve my vim skills in order to be more productive and feel like I’ve made some progress. Chris has rightly suggested that the only way to really improve is to make vim your editor of choice even when not remote pairing, so that’s what I’ve been trying to do. I’ve come across a few useful but random bits and pieces which I thought I’d record in case they were useful to anyone else…

Textile

I’m using a vim syntax file for Textile written by Kornelius Kalnbach to write this article.

svn blame

I’ve found Tammer Saleh’s key mapping for svn blame useful…

vmap gl :<C-U>!svn blame <C-R>=expand("%:p") <CR> \| sed -n <C-R>=line("'<") <CR>,<C-R>=line("'>") <CR>p <CR>

I decided to invest a bit of time understanding how it worked and broke it down as follows…

# key mapping for visual mode
vmap gl

# remove all characters between the cursor position and the beginning of the line
:<C-U>

# current file with full path
<C-R>=expand("%:p") <CR>

# pipe std out to sed which only outputs line N to line M
\| sed -n N,M

# line number of first line of selection
<C-R>=line("'<") <CR>

# line number of last line of selection
<C-R>=line("'>") <CR>

# print output
p <CR>

Search & Replace

At the end of last week, Chris & I found out from Ibrahim Ahmed’s blog how to search and replace across multiple files

# select file on which to operate
:args path/with/wildcards

# find pattern, replace with replacement, and save file
:argdo %s/pattern/replacement/ge | update

vimdiff

vimdiff seems like a nice tool, but unfortunately it doesn’t immediately play well with svn diff and its --diff-cmd option. There seem to be a couple of alternatives: (a) write a wrapper script for vimdiff which works with --diff-cmd; or (b) write a script which uses svn cat and then calls vimdiff.

Test::Unit

One of the things I really want to be able to do, is run Ruby Test::Unit tests and view the output, so I can jump to the line where an assertion failed. I haven’t managed to find anything suitable on the web, so here’s my first attempt…

function! Ruby_run_tests()
  let results = tempname()
  set splitbelow
  silent execute ":! ruby % > " . results . " 2>&1 "
  silent execute ":10 sview " . results
endfunction
map <silent> <F7> :call Ruby_run_tests()<cr>
imap <silent> <F7> <ESC><F7>

I’m sure this isn’t the best way of doing it, but when you put this in your vimrc file, pressing the F7 key runs the current file using Ruby and pipes the results to a temporary file. This temporary file is opened in a read-only window 10 lines high at the bottom of the screen. By moving the cursor onto the relevant line of any stack trace, you can then use “goto file” key sequence gf to goto the failing assertion. Although for some reason this only seems to work the first time round for me.

Ideally I’d like to be able to do the equivalent of “run focussed test” in TextMate, which should be quite straightforward, but that’ll have to wait for another day.

In the meantime, I’d love to hear from anyone else who has useful vim tricks for Ruby development. I’ll be bookmarking any useful links I find on del.icio.us.