vim 入坑指南(二)— vim 的模式

如果你还没有 vim,那么可以先看看上一篇里的相关说明,里面也提到了几个 vimrc 的基本设置。这一篇,咱们说说 vim 之所以高效的原因。 在任何与文本处理相关的任务里,无论是编程,写论文,或是准备 PPT,都会涉及到以下这四个操作:

  1. 移动光标
  2. 输入
  3. 删除
  4. 替换(删除 + 输入)

而 vim 之所以高效就是因为它通过几个模式,把四个操作都做到了极致。举几个简单的例子,假设,我们有 9 行文字,我可以如下几个简单的操作 (所有的演示我没有做任何处理,也没有用任何插件,vim 的神速可见一斑) :

  1. 把 9 行文字合成一段

  2. 把每行的开头都统一改成别的内容

  3. 删除前 5 行

  4. 或者把第 9 行挪到第 1 行 (有两种办法)

卖完了关子,我们说点有用的。先复述一下 vim 的几个模式,然后说说在 vim 中如何移动光标,最后提供一个简单的 vim 操作公式。

vim 的几个模式

  • 普通模式 (Normal Mode)

    不出意外的话,我们使用 vim 时大部分时间都会停留在普通模式下。移动光标和对文本处理(并进入相关模式)都是从普通模式发起的。

    1
    2
    3
    按 i 键 --> 进入输入模式
    按 v 键 --> 进入可视模式
    按 : 键 --> 进入命令行
  • 输入模式 (Insert Mode)

    在输入模式下,我们直接对文本进行输入,以及简单的删除处理。抽象点说,光标的移动和文字处理都是单向线性的,文本输入的效率取决于你打键盘的速度。当然,如果我们有了插件,两个字:如飞。不过先别急,之后慢慢讲。

  • 可视模式 (Visual Mode)

    可视模式实现的功能就和用鼠标选中文字差不多。选中的部分会被高亮,然后对其进行处理。比如:删除,更换大小写,排列等等。

  • 命令行 (Command Line)

    在普通模式和可视模式下按冒号键(:) 都能进入命令行(严格的来说,这并不算是一个模式)。许多复杂的操作其实都可通过一个简单的命令来完成。在命令行中,我们可以执行 vim 自带的命令,也可以执行自定义的命令。比如,我可以很简单的把文本中所有行末的 “空格”(显示为红色)都去掉。StripWhitespace 是通过插件 vim-better-whitespace 实现/提供的。

vim 操作基础:如何移动光标

移动光标 可以说是四个操作里最重要的一个,因为 删除输入替换 这三个操作都是以光标所在位置为基础做的。可以说,高效的文本处理大多依赖于光标移动的效率,而如何高效的把光标移动到 “目标” 处是一个不小的学问,

一般来说,我们通常采用的方式是用鼠标点。这么做并不是最高效的,因为类似这样的一个操作涉及到:使用鼠标以及移动手两个无关文字处理的动作。 这两个动作不仅中断了键盘的 “输出”,同时也会打断思路,最终降低了文本处理的效率。所以解决方案也很容易:不要用鼠标,尽量别(大范围的)移动手。

vim 的 普通模式 (Normal Mode) 完美解决了这一问题。在这个模式下,我们使用 h j k l (来代替 ← ↓ ↑ → 箭头键),w, b 等键来移动光标。这么做可以保持双手处于的基本键位 (Home Row) 处,从而保证了键盘的高效 “输出”。说句题外话,vim 之所以使用 h j k l的原因是因为当年创建 vi1 时所用的电脑的键盘就是这么设计的(原 po 链接在此)。另外,可能用 ~ 代表 HOME 也是同一个原因吧。

说完了影响效率的外在因素,现在说说如何更快速的移动光标,毕竟一字节一个字节的挪是低效的。为了简明,咱们先列一个公式,然后慢慢解释(其中括号代表可加可不加):

1
[数字] + 移动光标

我们已经熟知的移动光标的方法有 h j k lwb,而数字则代表按同一方法移动光标的次数,这是个单位和数量的关系。举几个例子:

  • 2w 表示向前移动两个词
  • 3j 表示向下移动三行

我们把这个公式总结为 motion,即

1
motion = [数字] + 移动光标

写到这里咱们只介绍了一个操作:移动光标,以后会涉及到更多的快速高效移动光标的内容。有了对 motion 的基本了解, 删除替换 就很容易了。因为它们都和刚才提到的 motion 有更为密切的联系,只需把之前的公式稍作变形即可。

vim 操作基础:输入

输入 其实简单明了,即进入 输入模式 后敲键盘就可以了。咱们先假装忽略掉输入模式下的种种高效手段,之后单谈。

vim 操作基础:如何删除和替换

删除 (delete) 和 替换 (change) 都是在 普通模式 下比较常用的两个操作。在 vim 里,d 代表删除,c 则代表替换(并进入输入模式)。而删除或替换的对象则由之前的 motion 决定。

1
删除/替换 + motion

组合在一起,就很实用啦,比如

  • c2w 代表更改两词,并进入输入模式。
  • dj 删除光标向下一步之间的所有内容,即 j 跨过的内容。

其实类似 dc 的操作还有不少,比如:

  • > 右缩进
  • < 左缩进
  • y 复制
  • gu 变换为小写
  • gU 变换为大写

它们统称为 operator,所以我们的公式就变成了

1
[数字] + operator + motion

在这里,数字依旧代表重复的次数。如果我们考虑以下这两个操作: d2w2dw。 它们所达成的效果是一样的,但是实质原理略有不同。前者是 “删除两词”,后者是 “删一词重复两遍”。 如果你真的理解了,那么 2d2w 和什么一致的呢? (答案见注解2

这里出现了一个问题:没有以 “行” 为单位的 motion。如果我想删除 d 两行文字的话,按下 d2j 是做不到的,我们只能删除光标在 2j 位移之间的文字。这情况下,公式有个小小的变形。

以 “行” 为单位的 operator 操作

1
operator + [数字] + operator (前后均为同一个 operator)

举几个例子:

  • dd 删除光标所在行

  • c2c 更改光标向下 2 行(含所在行),并进入输入模式

  • >3> 向右缩进光标向下 3 行(含所在行)

几个常用 motion 补充

其实许多 operatormotion 都是十分简单直接的,比如 w 代表 wordb 代表 back。习惯后应用起来也是得心应手,能做到手速赶上思维的状态,一想到 delete 2 words 手上自然而然的就按出 d2w 了,这也是为什么 V 字君更推荐直接读原版 vimtutor 的原因。除了刚才提到的,咱们再列举一些常用的 motion,更多的之后都会慢慢涉及到:

motion 意思
e 移光标至词末
$ 移光标至行末
0 移光标至行首
^ 移光标至本行首个非空格的字节
gg 移光标至整个文本的首行首个非空格字节
G 移光标至整个文本最后一行首个非空格字节
% 移光标至匹配括号的另一端

这些都只是一部分,有的内容也需要一定时间记忆。最好的办法就是准备个小抄,使用 vim 的时候没事看一眼就可以了。当然,这小抄也是可用插件的,比如我用了个名为 vim-cheat40 的插件,忘了什么就直接唤出(右侧新增的窗口),于是再也不愁找不到小抄的问题啦。

好啦,这一篇就说这么多啦。这一篇太抽象了,还要列举一些更复杂的例子,然后介绍一下什么是 文本对象。另外,在关键词 里,我也放了相关的演示图(我会尽量赶上文章进度的)。


  1. 1.vi 是 vim 的前身,vim 的全称则是 Vi IMproved。
  2. 2.d4w
VZJ wechat
欢迎您扫一扫上面的二维码,订阅 V 字君的微信公众号。