Cory Klein
Cory Klein

Reputation: 55720

How do you sort a range of lines by length?

Often I just want to sort all my #include's at the top of my source and header files by their length.

vim allows me to sort alphanumerically in a similar manner with :{range} sort u.

In vim, how do you sort a range of lines by the length of the line? Such that shorter lines are followed by longer lines.

Searching the internet, I found this:

:% s/.*/\=printf("%03d", len(submatch(0)))."|".submatch(0)/ | sor n | %s/..../

But that only works to sort the entire file, and is black magic to me anyway. I'm trying to figure out how to do that same sort with a range such as from line 4 to 18, as in :4,18 s/... Do you have any ideas?

Upvotes: 43

Views: 11186

Answers (3)

Ingo Karkat
Ingo Karkat

Reputation: 172648

I've written the AdvancedSorters plugin to deal with these complex sorting requirements.

Like in @Birei's answer, this plugin offers extension commands that evaluate an expression per line, put that number in front of the line, do a numerical sort, and then remove the temporary number again. Specializations handle the common sort by number of characters and by the line's display width, so you could just use:

:SortByWidth

Upvotes: 8

Birei
Birei

Reputation: 36272

One way, neither elegant nor efficient, but it works:

Add following function to your vimrc file. It inserts at the beginning of each line its number of characters, sort them numerically and deletes the numbers.

function! SortLines() range
    execute a:firstline . "," . a:lastline . 's/^\(.*\)$/\=strdisplaywidth( submatch(0) ) . " " . submatch(0)/'
    execute a:firstline . "," . a:lastline . 'sort n'
    execute a:firstline . "," . a:lastline . 's/^\d\+\s//'
endfunction

Call it with a range of numbers, like

:4,18call SortLines()

or in Visual mode using V, like:

:'<,'>call SortLines()

EDIT: Ops, now I realised that this solution is very similar to yours. It was fine, only that % means the complete buffer instead :4,18 or :'<,:'> that selects specific lines.

Upvotes: 8

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84393

Filter Visual Selection with Awk

One way to do this in vim is by filtering the visual selection with awk's length() function before sorting. For example:

:'<,'> ! awk '{ print length(), $0 | "sort -n | cut -d\\  -f2-" }'

Upvotes: 44

Related Questions