Search code examples
vimtexttext-editorvim-plugin

Moving multiple lines in vim visual mode


After pressing v and entering visual mode in , I would like to move those lines up a few rows. The solution discussed here does not suit me as I would like to move lines visually, i.e. I don't want to be typing m:+n as I don't know the value of n. Is there are keyboard shortcut that would allow me to move the selected lines in visual mode one line at time down or up by pressing the key sequence?

Sample with selected lines


Solution

  • There's no built-in command for that but you could build one with :help :move.

    First iteration

    " move selected lines up one line
    xnoremap <somekey>  :m-2<CR>
    
    " move selected lines down one line
    xnoremap <otherkey> :m'>+<CR>
    

    Move line up

    What we want is to move the selection between the line above the current one and the second line above the current one:

                 current line - 2 > aaa
                 current line - 1 > aaa
                     current line > bbb <
                                    bbb < visual selection
                                    bbb <
                                    ccc
                                    ccc
    

    The right ex command is thus :m-2.

    Move line down

    The current line is not a good starting point because it's the first line in our selection but we can use the '> mark (end of visual selection):

                                    aaa
                                    aaa
                     current line > bbb <
                                    bbb < visual selection
          end of visual selection > bbb <
      end of visual selection + 1 > ccc
                                    ccc
    

    The right ex command is thus :m'>+1.

    But we lost our selection so we have to do gv to get it back before moving the selection again. Not good.

    Second iteration

    " move selected lines up one line
    xnoremap <somekey>  :m-2<CR>gv
    
    " move selected lines down one line
    xnoremap <otherkey> :m'>+<CR>gv
    

    Where we simply append gv to the end of our previous mapping. Neat. But what about fixing indentation as we go?

    Third and last iteration

    " move selected lines up one line
    xnoremap <somekey>  :m-2<CR>gv=gv
    
    " move selected lines down one line
    xnoremap <otherkey> :m'>+<CR>gv=gv
    

    Where appending =gv to our mappings fixes the indentation (:help v_=) and reselects our lines.

    demo

    Bonus normal mode mappings

    " move current line up one line
    nnoremap <somekey>  :<C-u>m-2<CR>==
    
    " move current line down one line
    nnoremap <otherkey> :<C-u>m+<CR>==