401

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?

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
user4812
  • 5,942
  • 9
  • 30
  • 35
  • 1
    I had no choice but to implement scripting solution. I hope it is clean and adoptable for your needs. – Mykola Golubyev Apr 12 '09 at 14:44
  • 41
    For ye children of the future: http://vim.wikia.com/wiki/Moving_lines_up_or_down – guns May 30 '10 at 00:09
  • I'm not sure why you need a script, the Wikia article examples work. I've posted below a simplified version, because Wikia's example with 3 different mapping modes can be rather daunting (and not really necessary. If you use only the block selection mappings, then you can simply remember to block select (Shift V) and use these shortcuts (see my answer below). –  Jul 11 '10 at 22:17
  • Screencast on the topic: http://vimcasts.org/e/26 – glts Apr 11 '14 at 19:01
  • Also on [vi SE](http://vi.stackexchange.com/questions/2674/how-can-i-easily-move-a-line) – cfi Sep 17 '15 at 07:34
  • If anyone wants a quick plugin, it is [here](https://github.com/matze/vim-move) – Jdeep Nov 18 '20 at 12:48

22 Answers22

741

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

ddkP

Explanation

  • dd will delete the line and add it to the default register.
  • k will move up a line (j would move down a line)
  • P will paste above the current line
Henno
  • 1,448
  • 4
  • 18
  • 30
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
338

Assuming the cursor is on the line you like to move.

Moving up and down: :m for move

:m +1 - moves down 1 line

:m -2 - move up 1 lines

(Note you can replace +1 with any numbers depending on how many lines you want to move it up or down, ie +2 would move it down 2 lines, -3 would move it up 2 lines)

To move to specific line

:set number - display number lines (easier to see where you are moving it to)

:m 3 - move the line after 3rd line (replace 3 to any line you'd like)

Moving multiple lines:

V (i.e. Shift-V) and move courser up and down to select multiple lines in VIM

once selected hit : and run the commands above, m +1 etc

Serg
  • 3,503
  • 1
  • 12
  • 7
  • 22
    for me :m -2 only moves up one line. – john-jones Jan 11 '14 at 10:34
  • 2
    i put this method in my vimrc but then i cant repeat the command using '.'. does anybody know why that is? – john-jones Jan 11 '14 at 10:37
  • Very nice! Not as comfortable as the solution in Notepad++, but still - real and working. – Arturas M Oct 01 '14 at 11:32
  • Hermann, Sorry, typo/mistake on my part, you are right, :m -2 will move it up one line. I changed it. Also sorry for very late reply (not sure about .vimrc part) Cheers – Serg Oct 07 '14 at 22:59
  • 6
    Moving using the command works, if you want to use it in bindings such as the ones from Notepad++ as the OP asked, you need to enter the following into .vimrc: `noremap :m -2 noremap :m +1 ` – kap Jun 03 '15 at 10:43
  • When I try this, I end up with this `:'<,'>` at the start of the command, then things don't work as expected (even if I do remove those parts). – f1lt3r Jan 14 '16 at 03:24
  • @AlistairMacDonald to get the `:'<,'>` it must have meant that you are selecting lines in visual mode. Be sure you are in command mode when trying to move with the technique mentioned in this answer. – Sgnl Apr 24 '16 at 02:04
  • 2
    I would consider this the true "move x lines" motion as it also does not place the selection in your copy register – John Oct 06 '22 at 03:16
96

Move a line up: ddkP

Move a line down: ddp

jacobsimeon
  • 2,012
  • 1
  • 18
  • 20
94

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
  • 57,943
  • 15
  • 89
  • 102
  • Thanks - This is almost right, but there are issues with moving the last line - I'll update the question with details. – user4812 Apr 12 '09 at 14:11
  • I am still playing around. Please wait. – Mykola Golubyev Apr 12 '09 at 14:26
  • 1
    Had to change to and as there appears to be a clash with my setup, but fantastic answer! Thanks so much – user4812 Apr 12 '09 at 15:04
  • 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 Apr 29 '09 at 00:58
  • 2
    Thanks, great for git rebase --interactive . Had to bind to and . c-s-up/down didn't work. – Lari Hotari Sep 06 '12 at 06:43
  • 2
    If somebody wants a different shortcut: c is for control, A is for alt, I use `` like used in eclipse. – jan Apr 29 '14 at 09:01
  • 1
    The disappearing line is not a Vim bug! It is rather due to performing `ddkP` on the last line of the document. Try it for yourself on a 3-line file. To avoid such problems, use rather the much easier [`:m` mappings as given on the Vim wiki](http://vim.wikia.com/wiki/Moving_lines_up_or_down#Mappings_to_move_lines). – Serge Stroobandt Jan 11 '15 at 20:15
  • 1
    I changed last lines to `` and `` but when I try those keys in vim in visual running in [tag:tmux] the selection disappears and the cursor moves line up; without moving the selected lines. – Konrad Dec 27 '16 at 09:49
23

add the following to ~/.vimrc file (make sure you have no mapping for n,m )

nmap n :m +1<CR>
nmap m :m -2<CR>

now pressing n key will move a line down and m will move a line up.

mikew
  • 1,634
  • 2
  • 15
  • 25
Gajendra Jena
  • 490
  • 6
  • 7
  • 1
    That will conflict with the default keybinding: `go to the next search result` with the `n` key, after you searched the document with `/pattern`. – theerrormagnet Jun 11 '22 at 13:57
16

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. To input that character, use C+v, Esc in Vim (C+q, Esc on Windows).

shybovycha
  • 11,556
  • 6
  • 52
  • 82
emil.p.stanchev
  • 672
  • 5
  • 13
  • 1
    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. – Josh Lee Mar 13 '10 at 20:11
  • 1
    Why don't you enter Esc as C-vEsc (linux). Windows replaces C-v by C-q across the board but has the same way to enter any special key in insert/command mode – sehe Apr 03 '11 at 17:06
  • @sehe: Thanks, I didn't know that at the time. I've updated the answer. – emil.p.stanchev Apr 04 '11 at 16:38
  • I'm new to Vim and I know your answer is from a while ago but I have a few questions if you don't mind: 1. What's the difference between `nnoremap`, `inoremap` and `vnoremap`? I thought one could only use `map` for general purposes? 2. What `` does? 3. I want to map option+up to move a line up and option+down to move a line down, can you help me? –  Jun 23 '14 at 01:14
  • 1
    @RafaelRinaldi, `[niv]noremap` are remaps for normal|insert|visual modes. `` is `Carriage Return` (`Enter` key). – vp_arth Jul 29 '14 at 07:38
  • @sehe, is there difference between `` and `^]` ? – vp_arth Jul 29 '14 at 08:11
  • 1
    @vp_arth No there isn't – sehe Jul 29 '14 at 08:18
  • Note that Escape is ^[, not ^] -- I submitted an edit that fixes it in the answer, but some comments still refer to ^]. (You can check what escape characters a special key outputs by typing into `cat` if you're unsure.) – Soren Bjornstad Feb 21 '16 at 15:01
13

Just add this code to .vimrc (or .gvimrc)

nnoremap <A-j> :m+<CR>==
nnoremap <A-k> :m-2<CR>==
inoremap <A-j> <Esc>:m+<CR>==gi
inoremap <A-k> <Esc>:m-2<CR>==gi
vnoremap <A-j> :m'>+<CR>gv=gv
vnoremap <A-k> :m-2<CR>gv=gv
alexkv
  • 5,144
  • 2
  • 21
  • 18
12

In command mode position the cursor on the line you want to move down, and then

ddp

Explanation: dd deletes the current line to the general buffer p puts it back AFTER the cursor position, or in case of entire lines, one line below.

There is some confusion regarding commands p and P in many docs. In reality p pastes AFTER cursor, and P AT cursor.

szg
  • 121
  • 1
  • 2
9

Easiest way same like vscode. Add below line to .vimrc

"Ctrl+Shift+up move line above"
nmap <C-S-Up> :m -2<CR>

"Ctrl+Shift+down move line below
nmap <C-S-Down> :m +1<CR>
Bishal Udash
  • 142
  • 2
  • 8
7

A simple solution is to put in your .vimrc these lines:

nmap <C-UP> :m-2<CR>  
nmap <C-DOWN> :m+1<CR>
7

Exactly what you're looking for in these plugins:

timoxley
  • 5,156
  • 3
  • 36
  • 40
5

When you hit command :help move in vim, here is the result:

:[range]m[ove] {address} *:m* *:mo* *:move* *E134* Move the lines given by [range] to below the line given by {address}.

E.g: Move current line one line down => :m+1.

E.g: Move line with number 100 below the line with number 80 => :100 m 80.

E.g: Move line with number 100 below the line with number 200 => :100 m 200.

E.g: Move lines with number within [100, 120] below the line with number 200 => :100,120 m 200.

Casey Rodarmor
  • 14,878
  • 5
  • 30
  • 33
ako
  • 2,000
  • 2
  • 28
  • 34
5

Your cursor can be on any line. Line numbers are turned on to easily identify line locations.
1st case: Say I'm on line #7 and want to move line #3 to line #9 bring it down the page.

  • :3m 9 completes the move.

2nd case: I'm still on line #7 but now I want to move line #9 to line #3 bring it up the page.

  • :9m 2 completes the move. Note the use of 2 for the destination instead of 3.

Note: the cursor will move to the move destination location. If I want are need to go back to line #7 simply use :7

3rd case: move a range of lines. Say, 9 thru 12 where line 9 ends up on on line 3

David Robért
  • 51
  • 1
  • 4
4

For me, ddkkp did it (instead of ddkP with an uppercase P, which would work too).

Guillaume Chevalier
  • 9,613
  • 8
  • 51
  • 79
3

I put the following at the end of my .vimrc file:

noremap H ddkkp
noremap N ddp

So now 'H' and 'N' move current line up and down respectively.

john-jones
  • 7,490
  • 18
  • 53
  • 86
  • H and N are actually useful commands (H moves the cursor to the top and beginning of the screen, N moves to the previous search result), so I'd recommend using different keys – villapx Dec 16 '16 at 16:23
  • I see. I have also reconfigured them. To go to the top of the screen I press a and then up. A always means all-the-way in my books. And to search through previous results I press f and then left. F then stands for find. But for those who don't have it like that then yeah.. its valid. – john-jones Dec 16 '16 at 16:33
2

Here is a solution that works on my machine : MacBook Pro running VIM 8.1

These commands will not delete your lines at the top or bottom of your buffer.

Using the actual symbols that Alt-J and Alt-K output is a workaround for their key-codes not mapping properly in my environment.

Throw this in the old .vimrc and see if works for you.

" Maps Alt-J and Alt-K to macros for moving lines up and down
" Works for modes: Normal, Insert and Visual
nnoremap ∆ :m .+1<CR>==
nnoremap ˚ :m .-2<CR>==
inoremap ∆ <Esc>:m .+1<CR>==gi
inoremap ˚ <Esc>:m .-2<CR>==gi
vnoremap ∆ :m '>+1<CR>gv=gv
vnoremap ˚ :m '<-2<CR>gv=gv
Nick Sugar
  • 379
  • 3
  • 5
1

vim plugin unimpaired.vim [e and ]e

Baranina
  • 35
  • 1
  • 2
    This seems like overkill, I don't think you really need a full plugin for this. 2 lines in a vimrc does exactly what the OP wants – daniel gratzer Oct 22 '12 at 00:51
1

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>
1

In case you want to do this on multiple lines that match a specific search:

  • Up: :g/Your query/ normal ddp or :g/Your query/ m -1
  • Down :g/Your query/ normal ddp or :g/Your query/ m +1
Gleb Sabirzyanov
  • 765
  • 1
  • 8
  • 18
1

can use command:

:g/^/move 0

reference: https://vi.stackexchange.com/questions/2105/how-to-reverse-the-order-of-lines

kai
  • 1,640
  • 18
  • 11
0

:m.+1 or :m.-2 would do if you're moving a single line. Here's my script to move multiple lines. In visual mode, Alt-up/Alt-down will move the lines containing the visual selection up/down by one line. In insert mode or normal mode, Alt-up/Alt-down will move the current line if no count prefix is given. If there's a count prefix, Alt-up/Alt-down will move that many lines beginning from the current line up/down by one line.

function! MoveLines(offset) range
    let l:col = virtcol('.')
    let l:offset = str2nr(a:offset)
    exe 'silent! :' . a:firstline . ',' . a:lastline . 'm'
        \ . (l:offset > 0 ? a:lastline + l:offset : a:firstline + l:offset)
    exe 'normal ' . l:col . '|'
endf

imap <silent> <M-up> <C-O>:call MoveLines('-2')<CR>
imap <silent> <M-down> <C-O>:call MoveLines('+1')<CR>
nmap <silent> <M-up> :call MoveLines('-2')<CR>
nmap <silent> <M-down> :call MoveLines('+1')<CR>
vmap <silent> <M-up> :call MoveLines('-2')<CR>gv
vmap <silent> <M-down> :call MoveLines('+1')<CR>gv
Ji Han
  • 651
  • 8
  • 6
0

Try "Simple VIM" addon in VScode, it let's you use new-age shortcuts with old VIM ones together.

Eva4684
  • 21
  • 3