[vim/vim] Reversing a visual selection (#2550)

26 views
Skip to first unread message

ForTheReallys

unread,
Jan 13, 2018, 10:52:14 PM1/13/18
to vim/vim, Subscribed

I recently ran into a situation where I needed to reverse some lines in a visual selection and found a solution on stackoverflow. However, when I tried to add a keybinding for this, I ran into some trouble. When I ran
:'<,'>g/^/m <actual line number>
it worked. However, when I try to do this using
It does not include the top line in the selection. And when I use
:'<,'>g/^/m '<-1
It moves the top line to the bottom of the selection and nothing
more.

Here's an example:

Original Text:
1
2
3
4

Expected Result:
4
3
2
1

When I run :'<,'>g/^/m '<
1
4
3
2

When I run :'<,'>g/^/m '<-1
2
3
4
1


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub

Tony Mechelynck

unread,
Jan 14, 2018, 2:46:41 AM1/14/18
to vim/vim, Subscribed

I think this is due (in the last example) to how mark '< moves when you move the first line in the range, and (in the previous example) to the fact that "moving the first line to after itself" is a no-operation.

Try adding the following (untested) to your vimrc:

function SwitchLines() range
    let whereto = a:firstline - 1
    exe a:firstline . ',' . a:lastline . 'm' whereto
endfunction

(with no dot between 'm' and whereto); then when you're ready, use

:'<,'>call SwitchLines()

(the '<,'> will, like before, be inserted when you hit : in Visual mode, and the :exe statement will construct an ex-command by evaluating the values of its arguments, then execute it — with the numbers of the concerned lines in it).

For more explanations about how this function works, see the first 50 lines of help starting at :help E124. BTW, the lack of a :returnstatement is not an error, the :endfunction statement implies :return 0.

Best regards,
Tony.

ForTheReallys

unread,
Jan 14, 2018, 11:10:36 AM1/14/18
to vim/vim, Subscribed

Thanks for the help! It didn't work initially, but when I changed
exe a:firstline . ',' . a:lastline . 'm' whereto to exe a:firstline . ',' . a:lastline . 'g/^/m' whereto
It worked. But just to be clear, if moving marks to the line after themselves were not a nop inside the source code, my first solution would work?

Christian Brabandt

unread,
May 23, 2018, 4:32:04 PM5/23/18
to vim/vim, Subscribed

It worked. But just to be clear, if moving marks to the line after themselves were not a nop inside the source code, my first solution would work?

No, Consider what is happening for :g/^/m '< (lets ignore the initial address range for the :global command).

  1. Move line 1 below line 1, Buffer looks like this:

     1
     2
     3
     4
    
  2. Move line 2 below line 1, Buffer looks like this:

      1
      2
      3
      4
    
  3. Move line 3 below line 1, Buffer looks like this:

      1
      3
      2
      4
    
  4. Move line 4 below line 1, Buffer looks like this:

      1
      4
      3
      2
    

Note, you can alternatively use the :lockmarks command modifier, e.g. '<,'>g/^/lock m '<- should have also worked.

Closing

Christian Brabandt

unread,
May 23, 2018, 4:32:05 PM5/23/18
to vim/vim, Subscribed

Closed #2550.

Reply all
Reply to author
Forward
0 new messages