Yesterday I had to refactor a very large ruby class. It had a lot of methods and, to make it cleaner, I decided to sort methods alphabetically.

Is there a way to do this in vim? Of course there is, and it’s quite tricky - so let’s see how we can do it.

The basic idea is taken from this post on, I just adapted it for ruby. All credits to this guy for his work :)

We’ll use the same approach of the original post: first we’ll collapse each ruby method on a single line, using a defined pattern to replace line terminators. We’ll proceed sorting the one-lined methods, and finally we’ll expand them back to multi-line.

These are the three commands, we’ll explain them in detail later:

      :'<,'>g/\vdef\ /,/\v^\s*end$/ s/$\n/@@@

Let’s do it step by step.

1. Collapsing on a single line

First, we visually select the methods we want to sort, and issue this command:

:'<,'>g/\vdef\ /,/\v^\s*end$/ s/$\n/@@@

This will apply a global command on every instance of a defined pattern inside our visual selection. Look at the documentation inside vim for global commands (:help :g):

    *:g* *:global* *E147* *E148*

    Execute the Ex command [cmd] (default ":p") on the
    lines within [range] where {pattern} matches.

So, our range is '<,'> (this means from < mark to > mark, in other words from the beginning of the visual selection to its end); our pattern is \vdef\ /,/\v^\s*end$/. This means everything from def\ (a def followed by a space) to \^\s*end$ (a line starting with any number of spaces, followed by end and the end of line).

/,/ is how range beginning and end are separated; the \v is used to toggle the very magic mode, which allows a less verbose regexp syntax (see :help \v for more info).

Finally, our Ex command cmd is s/$\n/@@@. It’s a simple substitution: replace each line ending with our defined pattern, @@@.

2. Sorting collapsed lines

This is easy. Just visually select the collapsed lines and issue


3. Expand lines back with line returns

Again, select the sorted lines (you can use gv to redo the last visual selection) and issue this command:


This is a simple substitution: it replaces our defined pattern, @@@, with a line return (\r).

I hope you’ve learnt something from this article, I love that even after many years of vim usage I’m still surprised by its powerfulness every day. Have a good day!

Andrea Schiavini

Andrea Schiavini is a Milan based ruby developer