How do I sort multiple blocks of text by the first line in each block in Vim?

I have multiple blocks of text, or in other words, multiple functions like this:

def ==(other)
  ...
end

def to_s(full=false)
  ...
end

def to_a
  ...
end

def to_hash
  ...
end

def inspect
  ...
end

I want to sort the functions alphabetically by the function signature. How can this most easily be done in Vim?


It's relatively simple (and, I believe, close to what Jason had in mind) :

  1. turn all your functions into one liners by replacing all newlines with some fancy character:

    :g/def/,/end/s/\n/§
    
  2. sort those one liners with:

    :%sort
    
  3. expand all your functions back to their initial individual state:

    :g/def/s/§/\r
    

I've written the AdvancedSorters plugin to simplify the three separate steps given in @romainl's answer into a single command:

:SortRangesByRange /^def\>/,/^end\>\_s*\zs$/

The pattern here is slightly more complex to also properly include the separating empty lines.


The best way I can think of doing this without writing a function that parses the definitions, would be to substitute the line delimiters not preceded by end for another unique delimiter (+EOL+?), and then :sort, and re-substitute the line delimiters. It could probably be recorded to a macro.

A function might be better though, in the case that you want to use visual selection.