0

I was wondering if, out of the box, one can move an entire column up- and downwards.

Say, we have the following text:

1 a
    b
      c
2 d
    e
      f

My goal is to convert this into

1 a b c


2 d e f

This does not seem possible via visual block operations, since we need to operate on the column in the context of the rows above and below. In my case, I would need to overwrite the (empty) row values above the selected column.

Or do we need to resort to writing macros to accomplish this?

In the last case, I was thinking of a macro in the line of

1. <detect the first non-whitespace character> 
2. <delete up to the last non-whitespace character> 
3. <move up a row via insertion mode> 
4. <append the row with the deleted characters from the previous row>

This can be applied consequtively for each column in the format given above. Only, I'm not sure how to do step (1) and (2) yet. :)

  • I don't think vim can do this out of the box. There's a plugin that was developed for this purpose, but it's not maintained anymore and has some issues. – Tumbler41 Jun 20 '18 at 20:21
  • github.com/zirrostig/vim-schlepp is another plugin – Mass Jun 20 '18 at 21:30
  • 3
    Honestly in this case I would just spam join (J) – D. Ben Knoble Jun 21 '18 at 0:11
  • @D.BenKnoble Coud you elaborate? – Mussé Redi Jun 21 '18 at 6:04
  • @Mass vim-schlepp seems very promising, I'll have a look. :) – Mussé Redi Jun 21 '18 at 6:06
1

You can use visual block mode if you are careful about the boundaries.

First, type :set ve=all to turn on virtual edit mode. Then on the b, press ctrl-v to enter block visual mode, and type G to put the range to the bottom. Press y to yank this region.

1 a
    [b]
    [ ] c
2 d [ ]
    [e]
    [ ] f

Now, type k to go up one character. Since we're in virtual edit mode, the cursor goes to what is empty space. Press 1v which means re-enter visual block mode with the same width and height as the last operation. Press p to put. This overwrites the text without changing anything else.

1 a [b]
    [ ]
    [ ] c
2 d [e]
    [ ]
        f

Go to the c and type ctrl-v G y kk 1v p, similar to before

1 a b           1 a b [c] 
                      [ ] 
      [c]             [ ] 
2 d e [ ]  ->   2 d e [f] 
      [ ]              
      [f]              f

Note, this leaves an f which you can either delete afterwards or you could have originally extended your buffer a few blank lines down to grab extra whitespace to replace the f with.

To turn off virtual edit afterwards, use :set ve= or :set ve=block.

  • What kind of motion is G? I can not find it in the documentation. – Mussé Redi Jun 22 '18 at 19:11
  • 1
    :help G or search *G* in that document link. goes to the last line – Mass Jun 22 '18 at 19:18
  • The procedure works as a charm. :) How does 1v work? What does the 1 stand for? – Mussé Redi Jun 22 '18 at 19:21
  • 1
    the 1v stands for 'select the same number of characters or region as the previous visual operation' .. 2v would be select twice that. or quadruple, in block mode since in block mode both width and height are multipled – Mass Jun 22 '18 at 19:49
1

From vim helpdocs:

J           Join [count] lines, with a minimum of two lines.
            Remove the indent and insert up to two spaces (see
            below).  Fails when on the last line of the buffer.
            If [count] is too big it is reduce to the number of
            lines available.

For your specific purpose, I myself would prefer 3Jj3J, but you can do same with visual selection.

First visually select these first 3 lines.

1 a
    b
      c

Then, press J.

Then do the same for the next 3 lines.

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.