Sententiae viri ex temporibus duobus

Bringing Code Into Compliance With Vim, :argdo, Ack Case Study: Upgrading to Ember 1.0-pre


It’s not often that many of my favorite tools intersect in an exciting way such that I find myself being saved tons of time, but it happened today and I thought I would share a powerful editing technique. The tools used were vim and ack. The payoff was to make 250 changes across dozens of files with three simple command-line operations.

The Setup

I’m a real fan of the EmberJS JavaScript MVC framework.

Today the Ember team announced the 1.0-pre release of this product and I was anxious to implement it with my work codebase.

After slotting the new version, on initial boot up of my app in Chrome reported 245 errors. My code base, apparently, had 220 uses of the getPath() method. As of 1.0-pre, this method is deprecated and warnings are bubbled from Ember into Chrome. The fix is simple, change from using the verbose getPath() and use the more generic get() method. So the task was to change all occurrences in all places across some 3 dozen files from getPath to get.

There are many ways to fix this, but since I just finished Drew Neil’s excellent Practical Vim, I knew of a way to tear through this problem using Vim’s argdo and ack.

  1. The first task was to find all the files that have getPath in them. The Ack tool is great at this: ack getPath public/javascripts/project/*.js -l. I ran this in the command line to verify that this is, indeed, the right collection of files.
  2. Copy that command to the clipboard (I did it using tmux, a great utility that I learned about thanks to Brian Hogan’s book on the topic)
  3. Enter Vim
  4. :args `ack getPath public/javascripts/project/*.js -l`
  5. This loaded up all those matches. In the first file that matched, I performed the following: qa:%s/getPath/get/gq. This recorded a macro called a that I could run to change getPath to get. It also made this change in the current file I was editing
  6. Hit u to undo the change I just effected upon the first buffer since I was about to run the command on a population of which this file was a member.
  7. :argdo normal @a
  8. Watch in awe as Vim ran through the argument list and executed the a macro’s action, a global substitution of get for getPath
  9. :wall to save all the changes
  10. Done and commit the work

Talk about a powerful set of tools there! With tmux, vim, and ack, I tore through 245 results in a matter of seconds. I hit reload in Chrome and I had 8 other, unrelated, warnings.

If your editor can’t batch regex replacements and allow you to beat files senseless like this, you might need to consider a change.

UPDATE: Via Twitter, Drew commented that :argdo %s/getPath/get/g would also work. Even fewer keystrokes!