1

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. :)

6
  • 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, 2018 at 20:21
  • github.com/zirrostig/vim-schlepp is another plugin
    – Mass
    Jun 20, 2018 at 21:30
  • 3
    Honestly in this case I would just spam join (J)
    – D. Ben Knoble
    Jun 21, 2018 at 0:11
  • @D.BenKnoble Coud you elaborate? Jun 21, 2018 at 6:04
  • @Mass vim-schlepp seems very promising, I'll have a look. :) Jun 21, 2018 at 6:06

2 Answers 2

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.

4
  • What kind of motion is G? I can not find it in the documentation. Jun 22, 2018 at 19:11
  • 1
    :help G or search *G* in that document link. goes to the last line
    – Mass
    Jun 22, 2018 at 19:18
  • The procedure works as a charm. :) How does 1v work? What does the 1 stand for? Jun 22, 2018 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, 2018 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 and acknowledge you have read our privacy policy.

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