Vim Learning Curve

Posted by James Mead Sat, 12 Jul 2008 22:52:35 GMT

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.

Tags , , , , , , , , ,  | 4 comments

Prefer Commit Notes over Comments

Posted by James Mead Sat, 29 Mar 2008 19:05:00 GMT

My colleague, Chris, recently posted about what makes a good commit note. His main point is that a good commit note should explain why the changeset exists rather than what it contains (which should be more self-evident). I agree with this and (as Chris mentions) it’s of particular benefit when you have to do some software archeology. I’d go a step further and say that, for me, the best commit notes express the business reason for the changeset. If as a developer you are struggling to explain the business case for a particular change, (imho) you should try to find out before committing – otherwise how do you know the changeset is delivering value to the business?

In a previous post about preferring tests over comments, I expressed similar sentiments about using comments and tests to explain why rather than what. Chris’ post prompted me to re-read that old post and I noticed that it didn’t explain why I prefer tests over comments. The reason is that comments have a nasty habit of becoming out-of-date and getting left lying around to confuse the unwary, whereas you are forced to keep tests up-to-date (assuming they are part of a continuous integration build). For similar reasons I also think that commit notes are better than code comments, because they are forever associated with a snapshot of the code at the time they were written – leaving less scope for confusion.

Tags , , , , , , , , ,  | 2 comments

Trac Secret

Posted by James Mead Thu, 11 Oct 2007 13:31:00 GMT

We’ve been using Trac at Reevoo since I joined the company over 2 years ago. In the main, I’ve been pretty happy with it – it’s not fancy, but it does basic stuff tolerably well. However, I’ve always found it annoying that I couldn’t easily find a file/directory which I know used to be in our Subversion repository, but has been deleted.

I’m sure most people already know about the following feature of Trac, but just in case it’s useful to somebody else…

A couple of days ago, I had a small “aha” moment, when I decided to actually read an error page that Trac produces if you try to hack the “browse” url to navigate to your deleted file…

http://wiki/trac/browser/mocha/trunk

You see something like the following…

TracInternalError


My attention has always been drawn to the line of highlighted text, which indicates that the file has not been found, but the line underneath includes a link to “search in the repository history to see if that path existed but was later removed”. If I click that link, lo and behold…

TracLogSearch


I can now see the directory I was looking for and its history, including the changeset in which it was deleted. What’s more, it has a nice hackable url…

http://wiki/trac/log/mocha/trunk?rev=7034&mode=path_history

The moral of the story is that you should always read error messages carefully!

Tags , , , , , ,  | no comments

Rails Plugin Versioning

Posted by James Mead Sat, 02 Dec 2006 09:36:00 GMT

A while ago Jay Fields described a number of ways to share Ruby code between projects and focussed on a useful technique which involves using RubyGems and unpacking them into your vendor directory. He also mentions the difficulties of versioning with Rails plugins.

We use a number of Rails plugins at Reevoo. Initially we used Subversion externals to include them in our projects, but for a while now we’ve been successfully using François Beausoleil’s Piston which is effectively an extension to Subversion. You end up with a copy of the plugin code in your own repository with the relevant revision number from the remote repository stored in your own Subversion metadata. Piston prevents you getting new versions of the plugin code every time you update (as you would with an svn:external) which can lead to unexpected changes, but makes it straightforward to update to a newer version of a plugin when you want.

You can find Piston here.

Tags , , , , , , ,  | 1 comment