0%

Vim 实用技巧(02):插入模式 & 可视模式

这篇文章继续介绍 Vim 插入模式以及可视模式下的实用技巧。

插入模式

技巧 13:在插入模式中可即时更正错误

在输入错误时,可以用退格键删除错误的文本,然后在输入正确的内容。另外你也可以切换到普通模式,进行错误修正,然后在返回原来的位置。

虽然说我们可以切换模式,不过这并不意味着一定就得切换。在插入模式下,我们还可以用下面这些组合键:

  • <Ctrl-h>:删除前一个字符(同退格键)
  • <Ctrl-w>:删除前一个单词
  • <Ctrl-u>:删至行首

这些命令不是插入模式所独有的,甚至也不是 Vim 所独有的。在 Vim 的命令行模式中,以及在 bash shell 中,也可以使用它们。

技巧 14:返回普通模式

切换回普通模式的经典方式是使用 <ESC> 键,但在许多键盘上这个键的距离似乎有点远。作为替代,我们也可以使用 <Ctrl-[>,它的效果与 <ESC> 完全相同。

  • <ESC>:切换到普通模式
  • <Ctrl-[>:切换到普通模式
  • <Ctrl-o>:切换到插入-普通模式

当我们处于插入模式时,想运行一个普通模式命令,然后马上回到原来的位置继续输入。Vim 为此提供了一种巧妙的方法,以减少模式切换所带来的不畅。这就是 插入-普通模式插入-普通模式 是普通模式的一个特例,它能让我们执行一次普通模式命令,执行完后,马上就又返回到插入模式。要从插入模式切换到 插入-普通模式,可以按 <Ctrl-o>

技巧 15:不离开插入模式,粘贴寄存器中的文本

Vim 的复制和粘贴操作一般在普通模式中执行。在插入模式中,粘贴寄存器中的文本的方法是 <Ctrl-r>{register},其中 {register} 是寄存器的名字。

Vim 在插入寄存器中的文本时,其插入方式就如同这些文本是由键盘上一个个输进来的。因此,如果 textwidthautoindent 选项被激活了的话,那么就可能会出现不必要的换行或额外的缩进。<Ctrl-r><Ctrl-p>{register} 命令则会更加智能一些,它会按原义插入寄存器内的文本,并修正任何不必要的缩进。

技巧 16:随时随地做运算

大部分 Vim 寄存器中保存的都是文本,不过表达式寄存器则是一个另类。它可以用来执行一段 Vim 脚本,并返回其结果。在这里,我们将把它当成计算器来用。可以使用 = 符号指明使用表达式寄存器。在插入模式中,输入 <Ctrl-r>= 就可以访问这一寄存器。

如下所示,我们要计算该算术运算的结果:

1
the result of 111 * 111 is =

输入 <Ctrl-r>=,之后屏幕下方就会出现 = 提示符,输入 111 * 111,按下回车键,计算结果就会直接插入文本中。

表达式寄存器远不止能做简单算术运算,以后还将看到一些更高级的应用。

技巧 17:用字符编码插入非常用字符

只要知道某个字符的编码,就可以让 Vim 插入该字符,我们可以用这种方式插入任意字符,包括那些在键盘上找不到的符号。

要根据字符编码插入字符,只需在插入模式中输入 <Ctrl-v>{code} 即可。其中 {code} 是要插入字符的编码,vim所接受的字符编码共包含 3 位数字(十进制,不足 3 位补充 0)。对于 Unicode 字符,可以用 4 位十六进制编码来输入这些字符,即输入 <Ctrl-v>u{code}

如果想知道文档中任意字符的编码,只需把光标移到它上面并按 ga 命令。

另外,如果 <Ctrl-v> 命令后面跟一个非数字键,它会插入这个按键本身所代表的字符。例如,如果启用了 expandtab 选项,那么按 <tab> 键将会插入空格而不是制表符。然而,按 <Ctrl-v><tab> 则会一直插入制表符,不管 expandtab 选项激活与否。

技巧 18:用二合字母插入非常用字符

虽然可以使用数字编码插入任意字符,但是这种方式难以记忆。二合字母用起来很方便,在插入模式中,只需输入 <Ctrl-k>{char1}{char2} 即可。Vim在选择组成二合字母的两个字符时,尽量使之具有描述性,这样就更容易记住他们,甚至也能猜出其含义。例如,如果想输入如下字符 ½,只需输入 Ctrl+k 12 即可。

Vim 的缺省二合字母集遵从一定的惯例,使用 :h digraphs-default 获得更多信息。用命令 :digraphs 查看可用的二合字母列表,或者使用 :h digraph-table 查看另一个更为有用的列表。

以下总结了插入 非常用字符 的命令:

  • <Ctrl-v>{digit}:以十进制字符编码插入字符
  • <Ctrl-v>u{digit}:以十六进制字符编码插入字符
  • <Ctrl-v>{nodigit}:按原义插入非数字字符
  • <Ctrl-k>{char1}{char2}:插入以二合字母 {char1}{char2} 表示的字符

技巧 19:用替换模式替换已有文本

R 命令可以由普通模式进入替换模式,在替换模式中输入时会替换文档中的已有文本,替换完成之后,需要输入 Esc 回到普通模式。

Vim 还有另外一种替换模式,称为 虚拟替换模式,该模式可由 kR 命令触发。在虚拟替换模式中,我们是按屏幕上实际显示的宽度来替换字符的,而不是按文件中所保存的字符进行替换。虚拟替换模式 最典型的用途就是把制表符当成一组空格进行处理。
用虚拟替换模式替换制表符:

Vim 也提供了单次版本的替换模式及虚拟替换模式。r{char}gr{char} 命令允许我们覆盖一个字符,之后马上又回到普通模式。

可视模式

技巧 20:深入理解可视模式

Vim 可视模式允许我们选中一个文本区域并在其上操作。可视模式仅仅是另外一种模式,也就是说在此模式中,每个按键都完成一种不同的功能。

很多普通模式下的命令,在可视模式下也完成相同的功能。每次在可视模式中移动光标,都会改变高亮选区的边界。在可视模式中,我们先选中选区,再触发修改命令(在普通模式下,我们先触发修改命令,然后使用动作命令指定其作用范围)。

Vim 还提供了选择模式,Vim的 选择模式类似于 Microsoft Windows 的选择模式,在此模式下,输入的可见字符会使所选中的文本被删除,同时 Vim 会进入插入模式,并插入这个可见字符。输入 <Ctrl-g> 可以在可见模式及选择模式间切换。还是要尽量少用 Vim 的选择模式,该模式更多是为了迎合那些想让 Vim 更像普通编辑器的用户。

技巧 21:选择高亮选区

Vim 有 3 种风格的可视模式:

  • 面向字符的可视模式:能够选择任意的字符范围,该模式适用于操作单词或短语
  • 面向行的可视模式:能够整行进行进行操作
  • 面向列块的可视模式:能够对文档中的列块进行操作

激活可视模式:

  • v:激活面向字符的可视模式
  • V:激活面向行的可视模式
  • <Ctrl-v>:激活面向列块的可视模式
  • gv:重选上次的高亮选区;

可以在不同风格在可视模式间切换,方法和在普通模式下激活可视模式的方式相同。下面简单进行了总结:

  • <Ctrl-[>:回到普通模式
  • vV<C-v>:普通模式与相应的可视模式间的转换开关
  • v:其他可视模式切换到面向字符的可视模式
  • V:其他可视模式切换到面向行的可视模式
  • <Ctrl-v>:其他可视模式切换到面向列块的可视模式

高亮选区的范围由其两个端点界定,其中一端固定,而另一端可以随光标自由移动。我们可以用 o 键来切换其活动的端点。

技巧 22:重复执行面向行的可视命令

在使用 . 命令重复一条可视模式命令时,它所操作的文本数量和上次被高亮选中的文本数量相同。对于面向行的高亮选区来说,这种做法往往符合我们的需要。但是对于面向字符的高亮选取来说,却会产生令人意外的结果。

在可视模式下,执行完一条命令后,就返回到普通模式,而且可视模式下所选中的文本也不再高亮显示了,如果需要对相同的文本执行另一条可视命令:

  • 可以首先使用gv命令恢复对原高亮区域的选中,然后执行新的命令
  • 如果是同一条命令,直接使用 . 命令即可

技巧23 只要可能,最好用操作符命令,而不是可视命令

当使用面向字符的高亮选区时,使用 . 命令有时会有一些异常的表现。

对于如下文本,假设我们想把标签中的文字转换成大写形式:

1
2
3
<a href="#">one</a>
<a href="#">two</a>
<a href="#">three</a>

可以用 vit 命令来选中标签里的内容,其中 it 命令是一种被称为 文本对象 的特殊动作命令。之后使用 U 命令来把选中的字符转换成大写。

接下来如果连续使用 j. 命令来对接下来的两行做重复修改时,最终的结果如下:

1
2
3
<a href="#">ONE</a>
<a href="#">TWO</a>
<a href="#">THRee</a>

在第三行时出现问题,其原因是当一条可视模式命令被重复执行时,它只会影响相同数量的文本。

如果我们使用普通模式下的操作符命令,例如可视模式下的 U 命令等效于普通模式的 gU 命令,则通过 gUit 完成第一行修改后,直接输入 j.j. 即可完成之后两行的修改。

这个例子告诉我们:

  • 如果我们想使 . 命令能够重复某些有用的工作,那么最好远离可视模式。在做一系列可重复修改时,最好首选操作符命令,而不是其对应的可视模式命令
  • 但对一次性的修改任务来说,尤其是要修改的文本范围的结构很难用动作命令表达出来,这就是可视模式所擅长的

技巧 24:用面向列块的可视模式编辑表格数据

Vim 提供了面向列块的可视模式,使得我们可以以列为单位进行文本操作。

例如对如下文本,想添加分割线,以使之看上去更像表格:

1
2
3
1    one
2 two
3 three

可以通过如下操作(假设当前光标在第一行第一个空格处):

  • <Ctrl-V>jj:选中一列文本
  • x:删除该列
  • ..:重复删除
  • gv:再次选中文本
  • r|:将文本替换为 |
  • gg:回到第一行
  • yyp:复制一行
  • Vr-:选中新生成的行,并将该行文本替换为 -

最后得到如下文本:

1
2
3
4
1|one
-----
2|two
3|three

技巧 25:修改列文本

用列块可视模式可以同时往若干行中插入文本,该功能非常有用。

例如对于如下文本,想要把images目录修改为contents,

1
2
3
the path is /images/1
the path is /images/2
the path is /images/3

可以通过如下步骤实现(假设当前光标在 images 的 i 字符上)

  • <Ctrl-v>jje:选中文本
  • c:进入插入模式,修改文本
  • 输入 contents(输入时只有顶行显示)
  • Esc 键后,输入的修改在下两行同时生效

技巧 26:在长短不一的高亮块后添加文本

列块可视模式并不仅限于操作方形的文本区域,对于不同长度的高亮块,我们可以非常方便选中。

例如,需要对如下文本的每行结尾添加 ;,可以使用如下命令:

  • <C-v>jj$:选中每行
  • A:在行末尾添加字符
  • Esc 键后,所有行都添加了 ;

同样在插入模式期间,只有顶行才会显示插入的字符,但是 Esc 键后,这些修改就会扩散到其余选中的行上。

在列块可视模式下,I 命令和 A 命令分别将光标置于选区的开头和结尾。需要注意,不同于普通模式,此时输入 i 或者 a 并不会进入插入模式,在可视模式以及操作符待决模式下,它们会被当成一个文本对象的组成部分。