Here is an example buffer in vim:
fooooo
bar
pippy
one
two
three
And here is what I would like to produce:
foooooone
bartwo
pippythree
Ideally by specifying the two ranges of line numbers, but a sequence of commands would also be great.
Here is an example buffer in vim:
fooooo
bar
pippy
one
two
three
And here is what I would like to produce:
foooooone
bartwo
pippythree
Ideally by specifying the two ranges of line numbers, but a sequence of commands would also be great.
In such cases, I usually record a macro like this: qq4j^y$4k$pjq
. Here is what it does: starting at an item of the first list, it goes down to the second list, copies an item, goes back, then pastes the item at the end of the line. Lastly, it moves to the second item of the first list. Executing this macro three times (3@q
) yields the desired result.
Vim's registers have a mode associated with them: characterwise, linewise, and blockwise. This affects how the content of the register is put into the buffer when pasting the contents of a register. You can use this to your advantage for this problem.
Place your cursor at the start of the one
line and select those lines using visual block mode:
Ctrl+v$jj
Delete the block:
x
Move your cursor to the end of the foo
line and paste what you just deleted:
p
Since your first group all have the same line length, you could use block selection with <C>-v
. Starting with the first character of your second block selected,
<C>-v } $ d { $ p
So you select the whole bottom section in "block" mode, move to the end of the line of the beginning of the first block, and paste.
Ok, so start by yanking or removing the three lines you want to place at the end (e.g. 5G3dd
). Then:
:let lines=split(@","\n")
This puts all those lines in a list of strings (e.g. ['one', 'two', 'three']
).
Now select the lines you want to append to (e.g. 1GV2j
). Then
:'<,'>s/$/\=remove(lines,0)
This replaces the end of each line (/$/
) in the selected range ('<,'>
) with the the next line unshifted off the front of the list of lines (\=remove(lines,0)
).
If you find yourself doing this a lot, you may want to bind the above commands into a single command.
Here's a vim script solution:
fun MergeLines(start1, start2, length)
let end1 = a:start1 + a:length - 1
let end2 = a:start2 + a:length - 1
let starting_lines = getline(a:start1, end1)
let ending_lines = getline(a:start2, end2)
" Append each line in ending_lines to starting_lines.
let i = 0
while i < linecount
let starting_lines[i] .= ending_lines[i]
let i += 1
endw
" Set the new lines.
call setline(a:start1, starting_lines)
" Delete the old ones (there should be a function for this...).
exe a:start2 . ',' . end2 . 'del'
endf
So to accomplish your example:
:call MergeLines(1, 4, 3)