这篇文章继续介绍 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 在插入寄存器中的文本时,其插入方式就如同这些文本是由键盘上一个个输进来的。因此,如果 textwidth
或 autoindent
选项被激活了的话,那么就可能会出现不必要的换行或额外的缩进。<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-[>
:回到普通模式v
、V
、<C-v>
:普通模式与相应的可视模式间的转换开关v
:其他可视模式切换到面向字符的可视模式V
:其他可视模式切换到面向行的可视模式<Ctrl-v>
:其他可视模式切换到面向列块的可视模式
高亮选区的范围由其两个端点界定,其中一端固定,而另一端可以随光标自由移动。我们可以用 o
键来切换其活动的端点。
技巧 22:重复执行面向行的可视命令
在使用 .
命令重复一条可视模式命令时,它所操作的文本数量和上次被高亮选中的文本数量相同。对于面向行的高亮选区来说,这种做法往往符合我们的需要。但是对于面向字符的高亮选取来说,却会产生令人意外的结果。
在可视模式下,执行完一条命令后,就返回到普通模式,而且可视模式下所选中的文本也不再高亮显示了,如果需要对相同的文本执行另一条可视命令:
- 可以首先使用gv命令恢复对原高亮区域的选中,然后执行新的命令
- 如果是同一条命令,直接使用
.
命令即可
技巧23 只要可能,最好用操作符命令,而不是可视命令
当使用面向字符的高亮选区时,使用 .
命令有时会有一些异常的表现。
对于如下文本,假设我们想把标签中的文字转换成大写形式:
1 | <a href="#">one</a> |
可以用 vit
命令来选中标签里的内容,其中 it
命令是一种被称为 文本对象
的特殊动作命令。之后使用 U
命令来把选中的字符转换成大写。
接下来如果连续使用 j.
命令来对接下来的两行做重复修改时,最终的结果如下:
1 | <a href="#">ONE</a> |
在第三行时出现问题,其原因是当一条可视模式命令被重复执行时,它只会影响相同数量的文本。
如果我们使用普通模式下的操作符命令,例如可视模式下的 U
命令等效于普通模式的 gU
命令,则通过 gUit
完成第一行修改后,直接输入 j.j.
即可完成之后两行的修改。
这个例子告诉我们:
- 如果我们想使
.
命令能够重复某些有用的工作,那么最好远离可视模式。在做一系列可重复修改时,最好首选操作符命令,而不是其对应的可视模式命令 - 但对一次性的修改任务来说,尤其是要修改的文本范围的结构很难用动作命令表达出来,这就是可视模式所擅长的
技巧 24:用面向列块的可视模式编辑表格数据
Vim 提供了面向列块的可视模式,使得我们可以以列为单位进行文本操作。
例如对如下文本,想添加分割线,以使之看上去更像表格:
1 | 1 one |
可以通过如下操作(假设当前光标在第一行第一个空格处):
<Ctrl-V>jj
:选中一列文本x
:删除该列..
:重复删除gv
:再次选中文本r|
:将文本替换为|
gg
:回到第一行yyp
:复制一行Vr-
:选中新生成的行,并将该行文本替换为-
最后得到如下文本:
1 | 1|one |
技巧 25:修改列文本
用列块可视模式可以同时往若干行中插入文本,该功能非常有用。
例如对于如下文本,想要把images目录修改为contents,
1 | the path is /images/1 |
可以通过如下步骤实现(假设当前光标在 images 的 i 字符上)
<Ctrl-v>jje
:选中文本c
:进入插入模式,修改文本- 输入
contents
(输入时只有顶行显示) Esc
键后,输入的修改在下两行同时生效
技巧 26:在长短不一的高亮块后添加文本
列块可视模式并不仅限于操作方形的文本区域,对于不同长度的高亮块,我们可以非常方便选中。
例如,需要对如下文本的每行结尾添加 ;
,可以使用如下命令:
<C-v>jj$
:选中每行A
:在行末尾添加字符;
Esc
键后,所有行都添加了;
同样在插入模式期间,只有顶行才会显示插入的字符,但是 Esc
键后,这些修改就会扩散到其余选中的行上。
在列块可视模式下,I 命令和 A 命令分别将光标置于选区的开头和结尾。需要注意,不同于普通模式,此时输入 i 或者 a
并不会进入插入模式,在可视模式以及操作符待决模式下,它们会被当成一个文本对象的组成部分。