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:

  1. Pasting the contents of the unnamed register below the last line, moving the cursor to the last line of the pasted text.
  2. 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: Using UnconditionalPaste plugin to emulate the paste command

Tags:

Vim

Paste