Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to interleave lines from within Vim?

Tags:

vim

Given a file with an even number of lines, how can one interleave the lines from the second half onto the first half? For example, from this:

a
b
c
1
2
3

To this:

a
1
b
2
c
3

One possible solution would be writing those halves to separated files and then use the paste utility.

:1,3w a | 4,6w b
:%!paste -d \\n a b

However, I'd like to find a short way of doing it within Vim — using native commands.

like image 335
sidyll Avatar asked Mar 05 '23 09:03

sidyll


1 Answers

The :g command is frequently used to iterate on lines and perform some command. In this case it could be used to iterate on the lines at the second half of the file, while moving lines from the first half to their appropriate relative locations with :m.

Considering we have the cursor on the first line at the second half, this line must be preceded by the first line from the first half, so we can move it there with :1 m -1 (move line 1 to position -1, in relation to cursor). After this, line 1 is now what should precede the second line from the second half. It is thus a matter of moving the cursor down and repeating this process, conveniently performed by :g. In short, first jump to the first line of the second half with 50% and then:

:,$g/^/1m-1

As a command which takes a range of the full block to be interlaced (both halves) or defaults to the entire file:

command! -range=% Interleave execute 'keeppatterns'
            \ (<line2>-<line1>+1)/2+<line1> ',' <line2>
            \ 'g/^/<line1> move -1'
:Interleave

Note: :Interleave uses :keeppatterns to prevent the search register and history from changing. :keeppatterns requires Vim 7.4.083+

like image 141
sidyll Avatar answered Mar 16 '23 19:03

sidyll