tags:

views:

2643

answers:

6

In Notepad++, I can use ctrl + shift + up/down to move the current line up and down. Is there a similar command to this in Vim? I have looked through endless guides, but have found nothing.

If there isn't, how could I bind the action to that key combination?

Edit: Mykola's answer works for all lines, apart from those at the beginning and end of the buffer. Moving the first line up or the bottom line down deletes the line, and when moving the bottom line up it jumps two spaces initially, like a pawn! Can anyone offer any refinements?

+8  A: 

in command mode:
ddp to put it below
ddP to put it above. Note that however in this case you then have to move the cursor up, otherwise it will just restore the line where it was.

or do you mean "bubbling" or "drowning" a line around ? Mykola answer is actually more akin to this behavior.

Stefano Borini
I think I do mean that - I'll try Mykola's solution as it sounds like the right combination
Sounds good. Is there a way to complete ddp directly with the dot (.) command. If I do ddp and then press . to move it another line down it duplicates the line because it seems to execute only p. ?
Alex
A: 

If I want to swap one line with the line above I usually do the following

ddP

Explanation

  • dd will delete the line and add it to the default register.
  • P will paste above the current line
JaredPar
+14  A: 

Put the following to your .vimrc to do the job

noremap <c-s-up> :call feedkeys( line('.')==1 ? '' : 'ddkP' )<CR>
noremap <c-s-down> ddp

Disappearing of the line looks like a Vim bug. I put a hack to avoid it. Probably there is some more accurate solution.

Update

There are a lot of unexplained difficulties with just using Vim combinations. These are line missing and extra line jumping.

So here is the scripting solution which can be placed either inside .vimrc or ~/.vim/plugin/swap_lines.vim

function! s:swap_lines(n1, n2)
    let line1 = getline(a:n1)
    let line2 = getline(a:n2)
    call setline(a:n1, line2)
    call setline(a:n2, line1)
endfunction

function! s:swap_up()
    let n = line('.')
    if n == 1
        return
    endif

    call s:swap_lines(n, n - 1)
    exec n - 1
endfunction

function! s:swap_down()
    let n = line('.')
    if n == line('$')
        return
    endif

    call s:swap_lines(n, n + 1)
    exec n + 1
endfunction

noremap <silent> <c-s-up> :call <SID>swap_up()<CR>
noremap <silent> <c-s-down> :call <SID>swap_down()<CR>
Mykola Golubyev
Thanks - This is almost right, but there are issues with moving the last line - I'll update the question with details.
I am still playing around. Please wait.
Mykola Golubyev
Had to change to <c-j> and <c-k> as there appears to be a clash with my setup, but fantastic answer! Thanks so much
It's actually nice to see both a "standard" way and a better way for when you have the ability to customize. Thanks for both answers!
Jerph
+3  A: 

This worked for me:

http://vim.wikia.com/wiki/Moving_lines_up_or_down_in_a_file

BTW, if you want to use ALT+some_key and your terminal (urxvt does this) refuses to comply, you should enter something like this in your .vimrc:

" For moving lines (^] is a special character; use <M-k> and <M-j> if it works)
nnoremap ^]k mz:m-2<CR>`z==
inoremap ^]j <Esc>:m+<CR>==gi
inoremap ^]k <Esc>:m-2<CR>==gi
vnoremap ^]j :m'>+<CR>gv=`<my`>mzgv`yo`z
nnoremap ^]j mz:m+<CR>`z==
vnoremap ^]k :m'<-2<CR>gv=`>my`<mzgv`yo`z

where ^] is a single character that represents the ALT key.

Here's a method to input this character in your .vimrc:

http://blog.syndrowm.com/2009/01/urxvt-meta-character-gotcha.html

Bascially, you can run

$ python -c 'print "\x1b"' >> ~/.vimrc

and then copy and paste it where you need it inside the file.

slack3r
This is good, using Vim's built-in command for moving a line. It's more likely to behave nicely in the face of undo or an error.
jleedev
A: 

Here's a simplified version, for MacVim, using the the Wikia article examples (cf. link from gun's comment).

" Move selection up/down (add =gv to reindent after move)
:vmap <D-S-Up> :m-2<CR>gv
:vmap <D-S-Down> :m'>+<CR>gv

I'm using only the block selection variant, because all it takes is Shift-V to select the current line, and optionally cursor up/down to select some more lines.

According to the shortcuts above, pressing Cmd-Shift-Up/Down will shift the block selection up/down. "D" is the Command key in MacVim, for Windows try "C" (Control), or "A" (Alt) (eg. <C-A-f> would be Control Alt f).

The Wikia article adds "=gv" to these, which has the effect to adjust the indentation of the block after the move, based on surrounding text. This is confusing so I removed it, and added shortcuts for quickly indenting the selection instead.

" Indent selection left/right (Cmd Shift Left/Right is used for Tab switching)
:vmap <D-A-Left> <gv
:vmap <D-A-Right> >gv

Mind, the same can be done with << and >> but the selection would be lost, so these shortcuts above allow to indent multiple times and still move the block around because the selection is maintained.

My MacVim is configured to switch Tabs with Cmd-Shift-Left/Right so I used Cmd-Alt-Left/Right.

Here's the Tab switching for MacVim (put in .gvimrc with the rest above):

:macm Window.Select\ Previous\ Tab key=<D-S-Left>
:macm Window.Select\ Next\ Tab key=<D-S-Right>
faB
A: 

See my blog post here which gives mappings for both copying and moving: http://brianfromoregon.blogspot.com/2010/07/netbeans-style-line-moving-and.html

Brian Harris