How to achieve the “paste -d '␣'” behavior out of the box in Vim?
First, let us consider a somewhat different but closely related problem: appending one range of lines to another range immediately preceding it. After solving it, we will return to the original problem in the second part of the answer, and will show how the original problem can be reduced to the suggested one.
1. Without restricting the generality, we assume that the first block of lines (the one to append the second one to) starts on the first line of the buffer, and that the cursor is located on the last line of that first block. In this case, the lines can be joined using the following short and efficient Ex command:
:1,g/^/''+m.|-j!
This :global
command runs over the range of lines from the first to
the current one, sequentially executing two Ex commands: ''+m.
and
-j!
. The former, :move
command, deletes the line next to that
where the cursor has been positioned, and inserts it just below the
one currently being processed by the :global
command. The latter,
:join
command, appends the just moved line to the one above (without
adding or removing whitespace between them, because of the !
modifier).
The construction of these commands takes advantage of two implicit
facts. First, before the command specified in a :global
is executed
on yet another line, the cursor is positioned at the first column of
that line. It means that the address referenced as .
corresponds to
the latest line on which the command is currently being run. Second,
the cursor position before sending a :global
command to execution is
added to the jump list. Therefore, that location can be addressed in
ranges through the '
pseudo-mark (see :help :range
).
If it is needed to put a separator in between joined lines, one can
add a substitution command inserting it before :join
is executed:
:1,g/^/''+m.|s/^/\t/|-j!
There is an option of the default Vim sentence separation behavior
that is used when the :join
command is run without the !
modifier:
:1,g/^/''+m.|-j
For details about that space-separation behavior, see :help J
,
:help :join
, and especially the paragraph that can be found by
:helpg These commands, except "gJ"
.
2. The technique is easily applicable to the problem in question, since the initial situation can be narrowed down to the one we have considered above. In order to do that, go to the buffer containing the lines to append and copy them,
:%y
Then, switch to the target buffer containing the text to append to, and paste the copied lines below the current contents of the buffer,
:$pu|'[-
The above command combines two actions:
- Pasting the contents of the unnamed register below the last line, moving the cursor to the last line of the pasted text.
- Moving the cursor to the line that was the last one before pasting.
Upon that, one of the :global
commands proposed earlier can be used
immediately. Of course, it is possible to issue both pasting and
transforming in a single run:
:$pu|'[-|1,g/^/''+m.|s/^/\t/|-j!
My UnconditionalPaste plugin has (among others) the gdp
and gdP
mappings that paste the contents of a register as the minimal fitting (i.e., non-rectangular) block with a queried separator, just like paste -d {sep}
would do.
Like in @ib.'s excellent answer, this would first require yanking the source buffer into a register.
Demo: