Ever get the urge to update a ton of files? I know I do. For example, I recently changed multiple hundred coffeescript files from the syntax of
MyGreatClass = Backbone.Model.extend(
defaults:
awesome: true
)
to
class @MyGreatClass extends Backbone.Model
defaults:
awesome: true
How long did it take me? A couple of minutes. Here’s how.
Ack (or Grep)
I like ack. To find all the files I need to edit, I’d write something like this:
ack '^[^\s].*\=.*\.extend\($' app/assets/javascripts -l
This finds everything that doesn’t start with a space, has an equals sign, and
has .extend(
at the end of the line.
Opening a list of files in vim
After looking over the results of ack and ensuring that everything that matched is what I want to edit, I’ll open those files in vim.
vim $(ack '^[^\s].*\=.*\.extend\($' app/assets/javascripts -l)
Vim Macros
If you’ve been using vim and haven’t taken advantage of macros (especially if
you’re editing a lot of files in a similar fashion), you’re missing out. Open up
vim and type :help q
to get the nitty-gritty; I’ll summarize here.
To start recording a macro, press (in normal mode) q and then a letter or number. This will record a macro to whatever register you chose (via the letter or number).
Once you’re recording a macro, anything you type will be recorded to that macro so that it can be replayed. What I would type to change these files to the new format would be:
qqgg0iclass @<esc>f=cwextends<esc>2f.DGdd:wnq
Whoa, brain overload. Let’s break it down:
qq # records the macro to the q buffer
gg # first line in file
0 # first character in line
iclass @<esc> # inserts class @ at the cursor and returns to normal mode
f= # finds the first equal after the cursor
cwextends<esc> # changes the word (=) and moves to insert mode, adds extends, and returns to normal mode
2f. # finds the second period after the cursor
D # deletes the remainder of the line
G # moves to the end of the file
dd # deletes the line
:wn # writes the file and moves to the next file in the list
q # stops recording
This should be fairly straightforward; the only thing I really want to point out
is the :wn
. The n
in that command moves to the next file in the list of
files you opened with vim. This is one half of what makes editing all these
files really fast.
Replaying a Macro
Now that you have your macro, it’s time to replay it. To replay a macro, press
(in normal mode) @q
(assuming you stored your macro into the q
register). If
you were to run that macro, it’ll run it against the current file, write the
file, and move to the next. Since vim supports prefixing many commands with a
number (for the number of times to repeat the command), running 100@q
will run
that macro on the first one hundred open files that I’ve opened with vim.
Typically, this should be all you need to batch-edit, but if there are more
files, just run that command again (or start with a higher number). If there are
no more files to edit, vim will let you know.
Ben also mentioned recursive macros (my mind was blown) by adding @q
right
before the last q (which will run the q
macro before stopping recording). Just
make sure your q register is empty! This would allow you to run your macro once,
without specifying the number of times to run it, because vim will run the macro
until it’s out of files. Fancy!
Vim for fun and profit
Want to kick ass at vim? Pick up a copy of Vim for Rails Developers and become blazing-fast! If you want to hang out with fellow vim users to swap awesome tips like this, be sure to head to the Boston Vim Meetup!