在Vim中上下移动整条线

在notepad++中,我可以使用Ctrl + 转变 + 向上 / 下来来上下移动当前行。在Vim中有类似的命令吗?我翻遍了无数的指南,但一无所获。

如果没有,我如何将动作绑定到该键组合?

编辑:Mykola的答案适用于所有行,除了缓冲区的开头和结尾。向上移动第一行或向下移动一行会删除该行,当向上移动一行时,它最初会跳跃两个空格,就像棋子一样!谁能提供一些改进吗?

184223 次浏览

如果我想与上面的一行交换一行,我通常会这样做

ddkP

解释

  • Dd将删除该行并将其添加到默认寄存器中。
  • K向上移动一行(j向下移动一行)
  • P会粘贴到当前行的上方

将以下文件放到.vimrc中来完成这项工作

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

行消失看起来像一个Vim错误。我装了个黑客来避免。也许有更精确的解决方法。

更新

仅仅使用Vim组合就有很多无法解释的困难。这些是行缺失和额外的行跳转。

这里是脚本解决方案,可以放在.vimrc或~/.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>

这招对我很管用:

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

顺便说一句,如果你想使用ALT+some_key,而你的终端(urxvt这样做)拒绝遵守,你应该在你的.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

其中^]是单个字符,表示ALT键。 要输入该字符,使用Vim中的C + v, Esc (Windows中的C + q, Esc)

下面是MacVim的简化版本,使用了Wikia文章的例子(参见的评论链接)。

" 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

我只使用块选择变量,因为它所需要的是Shift-V来选择当前行,并可选地向上/向下游标来选择更多的行。

根据上面的快捷方式,按Cmd-Shift-Up/Down将移动块的选择向上/向下。“D”是命令键在MacVim, Windows尝试“C”(控制),或“A”(Alt)(例如。& lt; C-A-f>将是Control Alt f)。

Wikia文章添加了“=gv”,它可以根据周围的文本在移动后调整块的缩进。这是令人困惑的,所以我删除了它,并添加快捷方式快速缩进选择代替。

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

头脑,同样可以做到<<>>,但是选择会丢失,所以上面这些快捷键允许多次缩进,仍然可以移动块,因为选择是保持的。

我的MacVim配置为用cmd - shift -左/右切换选项卡,所以我使用了cmd - alt -左/右。

下面是MacVim的Tab切换(把.gvimrc和上面的其他内容放在一起):

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

只需将此代码添加到.vimrc(或.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

在命令模式下,将光标定位在要向下移动的行上,然后

ddp
< p >解释: Dd将当前行删除到常规缓冲区

.

.

.

.

.

. 在许多文档中,关于命令p和p有一些混淆。 实际上p粘贴AFTER游标,p粘贴AT游标

向上移动一行:ddkP

向下移动一行:ddp

Vim插件未受损。Vim [e]e

: m。+1或m。如果只移动一条线,则是-2。下面是移动多行的脚本。在可视模式下,Alt-up/Alt-down将包含可视选择的行向上/向下移动一行。在插入模式或普通模式下,如果没有给定计数前缀,Alt-up/Alt-down将移动当前行。如果有一个计数前缀,Alt-up/Alt-down将从当前行开始向上/向下移动一行。

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

假设光标在您想要移动的行上。

上下移动: :m for move

:m +1 -向下移动一行

:m -2 -向上移动1行

(注意,你可以用任何数字替换+1,这取决于你想要向上或向下移动多少行,即+2将向下移动2行,-3将向上移动2行)

移动到特定的线上

:set number -显示数字行(更容易看到你移动到哪里)

:m 3 -在第三行之后移动行(将3替换为你想要的任何行)

移动多行:

V(即转变-V),并上下移动courser以在VIM中选择多条行

一旦选中,点击并运行上面的命令,m +1

我把以下内容放在我的.vimrc文件的末尾:

noremap H ddkkp
noremap N ddp

现在H和N分别上下移动电流线。

将以下内容添加到~/。Vimrc文件(确保你没有映射n,m)

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

现在按n键将向下移动一行,m将向上移动一行。

简单的解决方案是在你的.vimrc中放入这些行:

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

如果你想在匹配特定搜索的多行上执行此操作:

  • 上::g/Your query/ normal ddp:g/Your query/ m -1
  • 向下:g/Your query/ normal ddp:g/Your query/ m +1

当你在vim中点击命令:help move时,结果如下:

< p > <代码>(范围):m[爱]{地址 } *: m * *:莫* *:* * E134 *移动 移动[range]给出的线到线的下方 由{address}给出。

__abc1 __abc2 __abc0。

__abc1 __abc2 __abc0。

__abc1 __abc2 __abc0。

__abc1 __abc2 __abc0。

这是一个在我的机器上工作的解决方案 :运行VIM 8.1的MacBook Pro

这些命令不会删除缓冲区顶部或底部的行。

使用Alt-J和Alt-K输出的实际符号是一种变通方法,因为它们的键代码在我的环境中映射不正确。

把这个扔进旧的。Vimrc ,看看是否适合你。

" 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

对我来说,ddkkp做到了(而不是用大写P的ddkP,这也可以工作)。

最简单的方法和vscode一样。将下面的行添加到.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>

您的光标可以在任何一行。行号被打开以方便地识别行位置。
第一个例子:说我在第7行,想把第3行移到第9行,把它移到下一页。

  • : 3米9 完成移动。

案例2:我仍然在第7行,但现在我想移动第9行到第3行,把它带到页面上。

  • 注意目的地使用2而不是3。

注意:光标会移动到移动目标位置。如果我需要返回第7行,只需使用: 7

3例: 移动一系列的行。比如,从9到12,第九行到第三行