我该如何在vim中交换两行?

139

我有这个:

pick 887b66f add 222 Dziewiecsil to flowers new title
pick dc331cb new name of beginning commit

我希望你能将这个内容翻译成中文:

pick dc331cb new name of beginning commit
pick 887b66f add 222 Dziewiecsil to flowers new title

有没有一种使用键盘快捷键快速完成这个操作的方法?


如果您不熟悉vim,可以考虑使用其他编辑器。您可以通过git config --global core.editor <whatever>仅为git配置编辑器,或者在.bashrc中包含export EDITOR=<whatever>以一次性为多个事项(包括git)配置编辑器。 - Sven Marnach
5个回答

237

在命令模式下,要将当前行与下一行交换,请键入ddp

  • dd - 删除行(在其他编辑器中实际上称为剪切),并将其保存到寄存器中
  • p - 从寄存器中粘贴行

6
将光标移至第一行,然后键入“ddp”。如果你还没有进入命令模式,请按“Esc”键进入命令模式。 - Sven Marnach
39
dd命令会将当前行复制到一个“寄存器”中,并删除该行。p命令会在当前行之后将寄存器的内容复制(“粘贴”)到你的缓冲区中。同样地,你可以使用xp交换两个字符或使用dwwP交换两个单词。 - Keith Thompson
@KeithThompson 不幸的是,交换两个单词并不像那么容易。 - C S
1
@KeithThompson 是的,尽管我在发表评论后感到有点不好意思,因为那是一个字面上的边缘情况 ;) - C S
我既知道 dd 也知道 p ,但从来没有想到可以组合起来使用。太棒了! - windmaomao
显示剩余2条评论

72

dd命令删除当前行,然后你可以用p命令将移除的行粘贴回来。不过还有另一种方法,使用m命令。使用m命令可以移动行,例如:

:m 1 将当前行移动到第一行之后

:m 0 将当前行移动到顶部

:m $ 将当前行移动到底部

在你的例子中,将光标放在第一行并输入:m $

更多信息:http://vim.wikia.com/wiki/Moving_lines_up_or_down


2
感谢您为非 Vim “原住民”提供的解释 :-) - Bruno Bieri
3
这正是我也在寻找的答案,以扩展我的 Vim 知识。 - Phemelo Khetho
2
谢谢!这就是我一直在寻找的答案。使用可视模式同时滑动多行时,这将变得更加方便。 - KareemJ
1
这太棒了!比被选答案更加多才多艺! :) - Dario Piotrowicz

24

例子:

  1. one
> 2. two

使用:m-2,切换到(当前行-2)

> 2. two
  1. one

使用:m+1,切换到当前行加1的位置

  1. one
> 2. two

如果您想的话,您可以进行映射。


2
例如 https://github.com/benknoble/Dotfiles/blob/master/links/vim/plugin/bubble.vim - D. Ben Knoble
2
这是比默认答案更好的答案。 - Alex Bin Zhao

14

尽管这个问题很老并且已经被标记为已回答,我想通过以下方式扩展答案:您可以使用常规模式命令,这些命令由Sven Marnach提供,使用nnoremap

:nnoremap <C-Up> <Up>ddp<Up>
:nnoremap <C-Down> ddp

这将允许您使用Ctrl+UpCtrl+Down在文件中移动行。但是,这将覆盖存储您最后复制的字符/单词/字母等的@"寄存器。因此,通过在ddp命令之前添加“(reg)”,我们可以解决这个问题:

:nnoremap <C-Up> <Up>"add"ap<Up>
:nnoremap <C-Down> "add"ap

在这里,我们在删除和粘贴命令之前添加"a来将我们的行存储在@a寄存器中,这样您的默认复制寄存器就不会被覆盖。但是它可能会覆盖@a寄存器的内容(谁知道呢,但在您的用例中可能需要使用它进行一些重要工作)。如果您觉得这个步骤有点多余,可以跳过它。让我们来修复一下这个问题:

:nnoremap <silent><C-Up> :let save_a=@a<Cr><Up>"add"ap<Up>:let @a=save_a<Cr>
:nnoremap <silent><C-Down> :let save_a=@a<Cr>"add"ap:let @a=save_a<Cr>

(<silent>用于防止将我们的命令输出到底部的消息行中。)

现在我们有两个映射,可以使用键盘快捷键在文件中移动行。您可以重新定义按钮,我使用 Alt + j/k,这对应的命令是 <A-j><A-k>。但是据我所知,并非所有终端仿真器都支持 Alt 键映射。


7
在Vim的维基页面中提出的映射实际上是模拟Sublime和其他编辑器实现此功能的最佳键组合方式。
这包括移动后的缩进操作,这也很好(那就是双等号==符号,如果您不想要)。
它还支持可视插入模式,以便您可以在编辑或使用完整块时移动行。
nnoremap <A-j> :m .+1<CR>==
nnoremap <A-k> :m .-2<CR>==
inoremap <A-j> <Esc>:m .+1<CR>==gi
inoremap <A-k> <Esc>:m .-2<CR>==gi
vnoremap <A-j> :m '>+1<CR>gv=gv
vnoremap <A-k> :m '<-2<CR>gv=gv

我个人将它们映射到我的 Mac 上的 <D-J><D-K>,而不是映射到 <A- 键,该键映射到 Alt 键。这样我就可以使用 Cmd + Shift + j/k,对我的手指来说更为自然。


这正是我所需要的。使用Alt修饰符非常适合这个任务。谢谢! - kohane15

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接