1

If I have two 'sets' of lines, each consisting of X number of lines (but the lines differing in their individual lengths), can I yank one set and insert (or append) it to the other?

To illustrate, can one yank the lines of 'Set 2' and somehow put them in front of the lines in 'Set 1', to achieve 'Result' (or even better, 'Better Result')?

(There is no magic in the pipe symbol in Set 1, i'm just using it to help delineate the joint that I hope to achieve in 'Result' or 'Better Result' in this example).

Set 1:

|of lines.
|different lengths.
|now together.

Set 2:

My blocks
All have
But are

Result:

My blocks|of lines.
All have|different lengths.
But are|now together.

Better Result:

My blocks |of lines.
All have |different lengths.
But are |now together.

What I Tried:

  • I have tried stuffing about with Visual, Visual linewise and Visual blockwise, but can't seem to achieve it, best I did was putting all of Set 2 in front of line 1 in Set 1.
  • I also tried making a basic macro (@q) that would 'dd' a single line from Set 2 and insert in front of each line in Set 1, but this fails because if you call it multiple times (5@q), the distance between the relevant lines that need to be matched up changes ('collapses') as the macro is called each time.
3

If you are okay with a relative recent Vim, you can do it the following way:

  1. Add spaces in front of your first block/set. Position your cursor on the beginning of the first line (at the o of of lines). So type:

    • Ctrl-V, 2, j (to visually select the beginning of the block)
    • I (you should be in insert mode now)
    • Space (adds a space at the beginning of the first block)
    • Esc (this returns you to normal mode and copies the space to the rest of the block).
  2. Now copy the second block using visual block mode. Again put your cursor at the beginning of the second block (at the M of My blocks). So type:

    • Ctrl-V, 2, j (to visually select the beginning of the block)
    • $ (to select all of the block, until the last character)
    • y (to copy/yank the block)
  3. Now move your cursor back to the space at the beginning of block 1 (the space at of lines):

    • zp This will paste the block, without adding padding for those lines that are shorter than the longest line in block 2.

As said, this requires a relative recent Vim (Patch 8.2.2914) which was just created for a similar case mentioned here.

If you do not have the zp command available yet, I would simply use the p command and manually remove the trailing spaces after pasting.

5
  • Well, that's significantly simpler. Thanks, wasn't aware of the zp operation.
    – Chris
    Jun 10 at 9:38
  • Man, Christian, I really need to figure out that mystery from a couple weeks ago ... vi.stackexchange.com/a/31379/11054 ... because this is another case where I can accomplish the task with simply ^V2j$y then P (with pre-zp Vim). Crazy things are afoot. :)
    – B Layer
    Jun 10 at 18:32
  • It's gotta be a plugin...just need to find some time to investigate.
    – B Layer
    Jun 10 at 18:40
  • @BLayer :) possibly :set clipboard=unnamed? That "feature" has just been fixed Jun 10 at 19:36
  • Ah, well I'll explore that angle, then. Thanks for the tip!
    – B Layer
    Jun 10 at 20:08
1

To get to 'Result' with 'Set 1' and 'Set 2', it isn't just pretty key strokes. That said, I suspect it could be by using a plugin (or perhaps your own function). Such a plugin might be UnconditionalPaste (https://github.com/inkarkat/vim-UnconditionalPaste)

I found this answer, which was helpful and got me going on my solutions: https://vi.stackexchange.com/a/10608/30981

How to get to 'Result':

  • Move cursor to line 1 in Set 2, then:
  • ^v2jg_"py
  • That moves to start of the line, uses visual mode, selects an additional two lines, selects to the end of each line (but not the newline), and yanks to register 'p' (p being an arbitrary choice).
  • If you inspect register p, you will see the type is 'c', meaning characterise.
  • :reg p
  • This can be converted to blockwise before pasting by manipulation with the setreg() command:
  • :call setreg('p','','ab')
  • What that does is for register p, append an empty string, and convert the contents to blockwise (basically just converts it to blockwise, you just have to append something to do the operation).
  • Now move to the start of Line 1 in Set 1, and paste/prepend before it using 'P'
  • P

That should achieve 'Result'.

To get 'Better Result':

  1. The easiest way is to first do a blockwise insert (Ctrl-V I) for the 3 lines of Set 1 to prepend a space before them, then do the steps above.
  2. One can also eventually get to it without inserting the blockwise space. This is done using a substitute command, an actual append command to put a space on the last line in the 'p' register, and then do the setreg() conversion to blockwise.

For those that are interested, on the latter approach...For clarity, I'm assigning the output to the 't' register, but you could do all these operations just on 'p' register by altering the commands.

NOTE: the '^J' that you (at least I see) when inspecting a register, actually appears as '^@' when one has finished typing the input sequence into a command, and that input sequence is actually typed literally as Ctrl-v Ctrl-j.

The process:

  • Once you have yanked Set 2 into register p (as per first part of this solution to get to 'Result'), then:
  • :let @t = substitute(@p, 'C-v C-j', ' C-v C-j', 'g')
  • Which will end up looking like:
  • :let @t = substitute(@p,'^@',' ^@','g')
  • Then, append the space to the last line in the register
  • :call setreg('t',' ','ac')
  • Then, convert it all to blockwise:
  • :call setreg('t','','ab')
  • You can then do the 'P' put, to prepend in front of Set 1 in order to get 'Better Result'.

Final Note:

I'm using Neovim 0.5 nightly on Windows 10, your mileage may vary in relation to the whole ^J, ^@, Ctrl-v Ctrl-j thing based on version, OS, language....I don't know. All I can say is see this and then experiment a bit: :h NL-used-for-Nul

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.