后知后觉发现虽然用 Vim 多年,不过一直都处于 vi “模式”,真正的功能很少去深入研究,遇到一些问题解决后也随即放脑后。所以这次希望能够持续的学习和记录,而不仅仅是使用。

移动

在 Vim 的帮助手册中移动操作是按方向区分的,但个人习惯主要以移动对象做区分。

方向

与众不同的方向键应该是 Vi 之中最标志性的动作,一提起 hjkl 只要对编辑器稍微有过兴趣的都知道这便是 Vim 中的上下左右:

  • 向左移动:h
  • 向下移动:j
  • 向上移动:k
  • 向右移动:l

文本

在 Vi 中是以空格区分词的,但在中文环境下,对词的的区分不是很准确,主要是以标点符号为分隔符,所以常常一跳就是半句话(标点符号也是一个“词”)

  • 上一个单词:b
  • 下一个单词:w
  • 上一个单词的词末:ge
  • 下一个单词的词末:e

需要注意的是,如果光标没在对应的位置,上述操作将会先跳到单词的词首或词尾,再次按下时才会跳到预期中的位置。此外,除了上面的四个动作,还有另外四个相应的,区别在于后者移动时会跳过 / 跳到符号:

  • 上一个单词(含标点):B
  • 下一个单词(含标点):W
  • 上一个单词的词末(含标点):gE
  • 下一个单词的词末(含标点):E

后者可以简单理解为把符号作为单词的一部分。

行相对来说容易理解一些:

  • 行首:0(数字 0)
  • 行尾:$
  • 上一行行首:-(Enter 键同样效果)
  • 下一行行首:+
  • 行中间:gm

如果文章有缩进的话,想跳到第一个字符上,可以用 ^,效果同 0 类似,但会跳到非空白字符。另一个需要说明的是 gm,它的作用是跳到有字符的行中间,而不是编辑器宽度的中间。

句子很简单:

  • 句首:(
  • 句尾:)

句子是以空行为分隔单位的,只要连续的行都视为一句。

段和句类似,不过包含句子前后的空行。

  • 段首:{
  • 段尾:}

文本

这在 Vimium 中最常用了,直接跳到页首或页尾,自然在 Vi 中作用也是一样:

  • 首行:gg
  • 尾行:G

注意是首行,不是行首,这两个动作直接回到编辑文本的第一行或最后一行。有意思的是如果在这两个操作前加上数字,两者的功能是一样的,比如说无论当前在什么位置 42gg 会跳到文本的第 42行,而 42G 的作用也同样是跳到第 42行。

屏幕

上面的移动都是以字、词、句等为单位,而这里是以当前屏幕显示的内容为范围。

屏内

屏内的移动是以当前编辑器显示的为准:

  • 屏幕首行:H(g0 同)
  • 屏幕中间:M
  • 屏幕尾行:L(g$ 同)

滚屏

滚屏严格来说不能算移动操作,毕竟光标位置是保持不变的,不过暂且先放这里吧。

    • 上滚一行:Ctrl + y
    • 下滚一行:Ctrl + e
  • 半屏
    • 上滚半屏:Ctrl + u
    • 下滚半屏:Ctrl + d
  • 整屏
    • 上滚整屏:Ctrl + b
    • 下滚整屏:Ctrl + f

搜索

搜索是一种更精细的操作,不是以固定的块为对象,而是以当前光标为指定字符之间的文本为对象。和搜索相关的动作有六个,分别是:

  • 向右搜索:f
  • 向左搜索:F

这两个很好理解,f 加上想要搜索的单个字符便可,另外两个功能类似,区别在于是停留在搜索结果的前一个字符上 tT。可能这就是大家觉的学习 Vi 曲线高的其中一个原因,相似动作太多了,多到完全可以就如何移动来写一本书(虽然大部分都是组合型的😏)。

不过用的比较多的也就 f,而且写文章基本用不到,原因也很简单,看你能不能猜到。

最后两个动作和搜索动作的缺点有关,它只能移动到第一个匹配的字符。大家知道英文就 26 字母,一行之中相同的字母自然很多,这时候就需要我们的 ,; 出场了,他们的作用是重复上一次的搜索。嗯,分向前和向后重复。

也就是说,当前用 fx 向前搜索的时候,这时候如果按 ; 便成了向前搜索。(你它喵的不是玩我么)

你以为这样就结束了吗。不,还没有,还有最后三个动作。(不是说好就6个动作吗)

分别是:

  • 匹配括号跳转:%
  • 匹配光标下字符跳转:#(向左)*(向右)

这应该很好理解了,如果想动手试试的话,记得要在英文文本环境下测试,上面三个字符对中文是无效的。

编辑

花了一小时,终于把动作这块写完了,还好不需要全部列完,不然得写到明年(开玩笑)。下面从简单(并不)的开始,也是用 vi 必须要会的。

插入

插入的姿势,额不对,这句划掉(插入的姿势)。插入的方式有很多种,具体有多少我也没数过,我尽量少说一点,就六个吧,可能会在补充一个。

  • 光标前:i
  • 光标后:a
  • 行首:gl
  • 行尾:A
  • 向上插入一行:o(小写 o)
  • 向下插入一行:O(大写 O)

怎么样,很简单吧。像移动中的跳到行首非空白字符上一样,插入也有一个插入命令对应 I,大写的 i,作用是在行首非空白字符插入。

呀,名额已经用完了,怎么办。那只能把前面讲过的移动命令拿来复习一下,比如说 wa 配合可以在下一个单词插入,ea 配合可以在下一个单词词尾插入,自然 fxa 是在搜索结果后插入咯。

替换

文章写完后,如果发现了一个错误怎么办,难道也要进入编辑模式,然后改完再退出吗?No,No,年轻人,终究还是年轻人,伟大的 Vi 已经为你想好了一切:

  • 替换光标下的字符:r

只要一个动作,里面可以把帐改成账,陆改成录。什么,想一次改多个,你做……。伟大的 vi 怎么会没考虑到这个简单的需求:

  • 进入替换模式:R

进入替换模式之后,直到手痒按下 ESC 键才会退出,不然一直处于替换模式。

多说一点,两种替换模式对中文都是有效的,先按下 rR 键,然后切换输入法输入就可以了。

合并

和并并来很简单的,一般就用一个动作,但这次复习时不但学到一个新动作,还领悟(明明也是学的)到一个骚操作。先来说说最常用的:

  • 合并下一行:J

J 的作用是把下一行合并到当前这一样,两行之间会有一个空格。如果不想这个空格呢,就要用到这次新学的动作了:

  • 合并下一行(不留空):gJ

效果同 J 一样,适合中文句子之间合并,两行之间不留空格。虽然解决了两行之间多出一个空格的问题,但是如果被合并的那一行(也就是第二行)行首自带空格也会保留下来。不过呢,现在写文章谁还在空两格啊。
好了,说完了这两个,下面讲讲领悟到偷学的骚操作:

  • 合并段:gwip

这个操作会合并所有相邻的行,直到遇到空行。

粘贴

粘贴就简单了,就两个命令,小p 和大p:

  • 粘贴在当前行下一行:p
  • 粘贴在当前行上一行:P

除了这两个,其实还有另外两个类似的,不过一般很少用就不说了(主要是电脑快没电了)。

更改、复制、删除

之所以把这三个放一起说,因为你懂的原因之外,另外就他们的动作是一样的,只是操作符不同:

  • 更改:c
  • 复制:y
  • 删除:d

有没有发现三个缩写连起来特别像某个词语的拼音简写。不扯,回来说,在操作符后面跟着移动动作,就回执行对应的操作,比如说,d 是删除,w 是移动一个单词,连起来就是 dw 删除一个单词,其他的也类似。有一点需要说明的是,当操作符重复时,会作用与整行:

  • 更改行:cc
  • 复制行:yy
  • 删除行:dd

此外,更改操作符会自动进入编辑模式。

做个补充,删除单个字符有个更简单的动作 x,按下即可删除光标下的字符。

最后

虽然已经限定了普通模式下的命令,但还有许多没写或是没写全,比如像缩进啦、大小在啦,还有撤销之类等等。什么,撤销,糟了。

  • 撤销上一命令:u
  • 撤销对当前行的所有操作:U

这两个命令混着用时千万要小心(最好不要),具体就不多说了,真没电了,明天得好好检查电脑具体原因。

最后的最后

写完后,感觉这篇笔记完全不是我以往的风格,也不知读起来如何。不准备更改了(除了错别字)等过一段时间回头看看(可能到时候会想删除)。

vi 的命令列举是没有止境的,不过我会把一些常用的命令放在我的 Life of Py 中,可以在参考中看到链接。


文章 Mate 显示的时间是 18年的8月份,距现在已过去一年多,想到草稿中还躺着一篇年代更为久远的,有些伤感。

参考