可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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>
回答2:
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
回答3:
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
回答4:
Move a line up: ddkP
Move a line down: ddp
回答5:
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).
回答6:
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.
回答7:
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.
回答8:
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
回答9:
Exactly what you're looking for in this awesome plugin: https://github.com/vim-scripts/upAndDown
回答10:
A simple solution is to put in your .vimrc
these lines:
nmap <C-UP> :m-2<CR>
nmap <C-DOWN> :m+1<CR>
回答11:
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.
回答12:
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>
回答13:
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
.
回答14:
vim plugin unimpaired.vim [e and ]e
回答15:
: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
回答16:
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
回答17:
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
回答18:
For me, ddkkp
did it (instead of ddkP
with an uppercase P, which would work too).