如何在 vim 中有效地添加括号或字符串?

How to efficiently add parentheses or a string in vim?

在传统的文本编辑器中,每当我需要打开一个字符串或括号并在它们之间输入一些内容时,我通常会这样做:

  1. 键入 ()""
  2. 向左按
  3. 输入我需要的内容
  4. 按右

但是在vim中(也就是说,如果我遵循vim way)这个过程变得非常乏味,因为我必须进入正常模式才能移动很多次:

  1. 键入 ()""
  2. <ESC>
  3. i
  4. 输入我需要的内容
  5. <ESC>
  6. l
  7. a

如果随时使用箭头键不是一个好习惯,vim中是否有更有效的方法来完成此类任务?

没有。在 Vim 中执行此操作与在 "traditional" 编辑器中完全相同:

  1. 键入 ()""
  2. left
  3. 输入您需要的内容
  4. right

但是……你为什么不输入开始字符,你想在这对中输入什么,然后输入结束字符?

  1. 键入 ("
  2. 键入您需要的内容
  3. 键入 )"

太简单了?

我认为在正常模式下使用箭头键移动是不好的做法,但在你的情况下;在插入模式下移动一个 space,我敢说使用箭头键可能是最佳做法。

话虽这么说,如果您坚决要避开它们,您可以使用 <i_ctrl-o>

:help i_ctrl_o

CTRL-O      execute one command, return to Insert mode   *i_CTRL-O*

因此,在插入模式下,您可以键入:()<ctrl-o>h<xxx><ctrl-o>l,其中 <xxx> 是括号中您想要的任何内容。

不幸的是,如果您的光标位于该行的最后一个字符上,这将不起作用,如果您正在键入它,则很可能是。

要解决该问题,请执行 :set virtualedit+=onemore 或将其添加到您的 ~/.vimrc 文件中。

请注意,此解决方案比简单地使用箭头键的击键次数更多,但您不需要将手从主行移开,因此它可能会更快。

在映射中自动附加那些结束字符并将光标放在所需位置实际上非常容易。诀窍是这样做,同时又不会弄乱 undo/redo/repeat 操作。问题是插入模式下的光标移动命令会破坏 "undo sequence",因此您在移动光标后所做的任何更改都将与移动光标前所做的更改分开撤消。

警告:以下信息可能会过时

有很多插件可以自动附加这些字符(参见 Vim wiki page for appending closing characters 的部分列表),在 Vim 7.4 之前,其中一些甚至有复杂的解决方法来保持撤消序列完好无损。不幸的是,他们都依赖于 Vim 中的一个错误,该错误已在 7.4 版中修复。

补丁可用于 add a cursor movement that does not break undo, so if you want to compile Vim yourself,您可以获取该补丁并使用如下映射(无需插件!)来执行您想要的操作:

inoremap            (          ()<C-G>U<Left> 
inoremap <expr>     )          strpart(getline('.'), col('.')-1, 1) == ")" ? "\<C-G>U\<Right>" : ")" 

这些映射将在您键入一个开头 (,将光标置于括号之间时插入“()”。当您键入“)”并且光标后已经有一个结尾的“)”时,Vim 将跳过括号而不是插入一个新的。光标移动之前有 <C-G>U,这是上述补丁添加的功能,允许随后的光标移动不会中断撤消序列(只要移动全部在一行中)。

截至Vim 7.4.663,该补丁仍未正式包含。