I'm using:

" move current line up
imap [u <esc>:m .-2<CR>i
" move current line down
imap [d <esc>:m+<CR>i

But I'd like to keep the current cursor position, and I would like to expand the question to move up/down a block of text.

EDIT 1: for example:
The current line ->| need to move up is here

->| is the cursor's position that we need to keep moving.

  • These are insert-mode mappings. How could you move up/down a block of text in insert mode since you cannot select text in insert mode?
    – Mass
    Commented Oct 11, 2017 at 14:02
  • It doesn't matter in v, n, i mode. Just describe what I'm using right now. Commented Oct 11, 2017 at 14:06

2 Answers 2


ddp and ddkP put the cursor at the begin of the line.

The solution was found on http://vim.wikia.com/wiki/Moving_lines_up_or_down

For insert mode:

inoremap <A-j> <Esc>:m .+1<CR>==gi
inoremap <A-k> <Esc>:m .-2<CR>==gi

For blocks of code:

vnoremap <A-j> :m '>+1<CR>gv=gv
vnoremap <A-k> :m '<-2<CR>gv=gv

After selection of a block, press <A-j> to move the whole block down, <A-k> to move it up.

For normal mode:

nnoremap <A-j> :m .+1<CR>==
nnoremap <A-k> :m .-2<CR>==
  • We always have cursor but its position reset to beginning of that line. Kind of obviously. Commented Oct 11, 2017 at 15:50
  • I try imap <c-u> <esc>:mk<CR>:m .-2<CR>`ki but get error E189: "_exrc" exists (add ! to override). Any suggestion? Commented Oct 11, 2017 at 16:18
  • 2
    @ommision: How can I keep cursor's position in normal mode? Commented Oct 11, 2017 at 18:56
  • 2
    @TuyenPham In normal mode easiest way is to use a mark: nnoremap [u mz:m .-2<cr>`z and nnoremap [d mz:m .+1<cr>`z
    – Rich
    Commented Oct 12, 2017 at 13:40
  • @Rich: It works, but up is pretty slow, doesn't work with block. Tope brings faster up with tpope/vim-unimpaired - doesn't work with block either. Commented Oct 12, 2017 at 14:05

I interpreted "keep position" as the cursor does not move, at all, which may not be what the question intended. Note: this only works with set nostartofline.

Partial answer for the insert-mode case: There are two cases to consider. The trick is to remember :move puts the cursor at the new position.

Current line up: instead of moving the current line up, we move the previous line to just below the cursor line.

inoremap [u <c-o>:-1m.<cr>

Current line down: instead of moving the current line down, we move the next line to just before the cursor line.

inoremap [d <c-o>:+1m-1<cr>

Note: in either case, we use inoremap and <c-o>, which are preferable to imap and <esc>...i.

  • Weird, just seen your answer that posted 2 hours later but important matter keeping position is not answered yet. inoremap is good to use. Commented Oct 11, 2017 at 16:26
  • This answer actually does keep position, do you not observe this?
    – Mass
    Commented Oct 11, 2017 at 16:32
  • Same result as my code. Commented Oct 11, 2017 at 16:35
  • @Mass When I test your solution in vim -Nu NONE (Vim 7.4) the cursor stays on the same line number, but moves to the start of the line. i.e. it doesn't move vertically, but it does move horizontally. Could the behaviour be inconsistent across versions?
    – Rich
    Commented Oct 12, 2017 at 13:33
  • 1
    @Rich, yes, my mistake. I think it works with set nostartofline but not by default.
    – Mass
    Commented Oct 12, 2017 at 13:55

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.