在Vim中上下移动整个行


311

在Notepad ++中,我可以使用Ctrl+ Shift+ Up/ Down上下移动当前行。在Vim中有与此类似的命令吗?我浏览了无休止的指南,但一无所获。

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

编辑:Mykola的答案适用于所有行,除了缓冲区开头和结尾处的行。向上移动第一行或向下移动底部行会删除该行,而向上移动底部线则会首先跳两个空格,就像典当一样!谁能提供任何改进?


我别无选择,只能实施脚本解决方案。我希望它是干净的并且可以满足您的需求。
Mykola Golubyev 2009年

31

我不确定为什么需要脚本,因此Wikia文章示例可以正常工作。我在下面发布了一个简化版本,因为Wikia的示例具有3种不同的映射模式,这可能令人望而生畏(并且并不是真正必要的。如果仅使用块选择映射,则只需记住块选择(Shift V)并使用这些快捷方式(请参阅下面的答案)

关于该主题的屏幕录像:vimcasts.org/e/26
glts 2014年

同样在vi SE
cfi

Answers:


81

将以下内容放入您的.vimrc以完成工作

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

该行的消失看起来像是Vim错误。我放了一个hack来避免它。可能有一些更准确的解决方案。

更新资料

仅使用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>

1
必须更改为<cj>和<ck>,因为我的设置似乎存在冲突,但是答案很不错!非常感谢
user4812

1
谢谢,非常适合git rebase --interactive。必须绑定到<cj>和<ck>。cs上/下不起作用。
拉里·霍塔里

2
如果有人想要一个不同的快捷方式:c用于控制,A用于替代,我使用<A-up>类似eclipse中的用法。
2014年1

1
消失的行不是Vim错误!而是由于ddkP在文档的最后一行执行。在3行文件中自己尝试。为避免此类问题,请使用:mVim Wiki上给出的更简单的映射
Serge Stroobandt,2015年

1
我将最后一行更改为<A-up>和,<A-down>但是当我尝试在tmux中以可视化方式运行vim中的那些键时,选择消失,光标向上移动;而不移动选定的行。
康拉德

574

如果我想与上面的一行交换一行,我通常会执行以下操作

ddkP

说明

  • dd将删除该行并将其添加到默认寄存器。
  • k将向上移动一条线(j将向下移动一条线)
  • P将粘贴在当前行上方

5
而且它也始终可用。:-)
Henno

71
ddp移动一条线(删除线和粘贴当前行下)
bcoughlan

2
要移动一串线,例如说4,4 dd然后移动到2线,然后:2是要粘贴的位置P
大师

2
@Guru应该4dd代替4 dd吗?
Patrick McDonald

3
并将dd<number>jp当前行的<number> +1行向下移动。和dd<number>kp移动当前行<编号>线组成。
egelev

230

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

上下:m移动: 移动

:m +1 -下移1行

:m -2 -上移1行

(请注意,您可以根据需要向上或向下移动几行来用任何数字替换+1,即+2可以将其向下移动2行,-3可以将其向上移动2行)

移至特定行

:set number -显示数字行(便于查看将其移动到的位置)

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

移动多行:

V(即Shift- V),然后上下移动课程练习器,以在VIM中选择多行

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


14
对我来说:m -2只向上移动一行。
2014年

2
我把这个方法放在我的vimrc中,但是我不能用'。'重复命令。有人知道为什么吗?
Hermann Ingjaldsson 2014年

非常好!不如Notepad ++中的解决方案舒适,但仍然-真实且可行。
Arturas M 2014年

Hermann,对不起,我的错别字/错误,您是对的,:m -2会将它向上移动一行。我改了 也很抱歉答复很晚(不确定.vimrc部分)干杯
Serg 2014年

2
使用命令进行移动是可行的,如果您想将其用于OP中要求的诸如Notepad ++的绑定中,则需要在.vimrc中输入以下内容:noremap <c-s-up> :m -2<CR> noremap <c-s-down> :m +1<CR>
kap 2015年

74

向上移动一行: ddkP

向下移动一行: ddp


1
在vimrc中使用此命令不允许使用'。'重复命令。
Hermann Ingjaldsson 2014年

@HermannIngjaldsson,我想如果您希望能够.重复使用,可以将命令包装在函数中。
jacobsimeon

是的..,如果您需要移动更多行,可以使用V而不是dd。
sensorario

15

这为我工作:

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键的单个字符。要输入该字符,请C+v, Esc在Vim中使用(C+q, Esc在Windows上)。


1
使用Vim的内置命令来移动行,这很好。面对撤消或错误时,它更有可能表现良好。
Josh Lee 2010年

1
为什么不以<kbd> Cv <kbd /> <kbd> Esc </ kbd>(linux)输入Esc。视窗取代<大骨节病>了Cv <万桶/>的<大骨节病> CQ <万桶/>全线但以同样的方式,进入插入/命令行模式的任何特殊键
sehe

@sehe:谢谢,当时我还不知道。我已经更新了答案。
emil.p.stanchev 2011年

1
@RafaelRinaldi [niv]noremap是法线|插入|视觉模式的重映射。<CR>Carriage ReturnEnter键)。
vp_arth 2014年

1
@vp_arth不,没有
sehe 2014年

13

将以下内容添加到〜/ .vimrc文件中(确保您没有n,m的映射)

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

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


12

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

ddp

说明:dd将当前行删除到通用缓冲区中p将其放到光标位置之后;如果是整行,则将其放回下面一行。

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





3

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

noremap H ddkkp
noremap N ddp

因此,现在“ H”和“ N”分别将当前行向上和向下移动。


H和N为实际有用的命令(H将光标移动到顶部和屏幕的开始,N移动到先前的搜索结果),所以我推荐使用不同的密钥
villapx

我知道了。我也重新配置了它们。要转到屏幕顶部,请按a,然后再向上。在我的书中,“永远”意味着一路走来。要搜索以前的结果,请按f,然后按向左。F然后代表find。但是对于那些没有那样的人,那么是的。
Hermann Ingjaldsson

1

这是MacVim的简化版本,使用Wikia文章示例(请参见gun的评论中的链接)。

" 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中的Command键,对于Windows,请尝试“ C”(控件)或“ A”(Alt)(例如,<CAf>将是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>


1

当您在中命中命令:help movevim,结果如下:

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

例如: 将当前行向下移动一行=> :m+1

例如: 将数字100的行移到数字80 =>的行下方 :100 m 80

例如: 将数字100的行移到数字200 =>的行下方 :100 m 200

例如: 将编号为200的行移动到[200,>]的下方[100,120]之内 :100,120 m 200


1

这是适用于我的机器的解决方案 :运行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


0

如果只移动一行,则: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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.