Vim 使用进阶:10 种寄存器剖析


原文链接: Vim 使用进阶:10 种寄存器剖析

寄存器的类型

无论是vim内部抑或外部的复制([y]ank)、删除([d]elete)、粘贴([p]ut),在vim中都是借助registers(寄存器)实现的,vim共有9类寄存器:
名称 标识 说明
无名(unnamed)寄存器 "" 缓存最后一次操作内容;
数字(numbered)寄存器 "0 - "9 缓存最近操作内容,复制与删除有别;
行内删除(small delete) "- 缓存行内删除内容;
具名(named)寄存器 "a - "z或"A - "Z 指定时可用;
只读(read-only)寄存器 ":, "., "%, "# 分别缓存最近命令、最近插入文本、当前文件名、当前交替文件名;
表达式(expression)寄存器 "= 只读,用于执行表达式命令;
选择及拖拽(selection and drop) "* , "+ , " ~ 存取GUI选择文本,可用于与外部应用交互,使用前提为系统剪切板(+clipboard)可用;
黑洞(black hole)寄存器 "_ 不缓存操作内容(干净删除);
模式寄存器(last search pattern) "/ 缓存最近的搜索模式。

上面的说明为简要概述,并不完全准确,详细说明须参考手册::help copy-move

Vim的强大功能有很大一部分体现在它丰富的寄存器上。我们可以灵活使用寄存器存取文本,还能将命令录制于寄存器中。

在Vim中,大部分的修改操作都能够撤销,而这也要归功于背后的寄存器。下面我们来看看Vim这个神器都有哪些神奇的寄存器。

在Vim中,寄存器被分为以下10种类型:

  1. 未命名寄存器 ""
  2. 数字寄存器 "0 ~ "9
  3. 小型删除寄存器 "-
  4. 字母寄存器 "a ~ "z 或 "A ~ "Z
  5. 只读寄存器3个 ": ". "%
  6. 交替文件寄存器 "#
  7. 表达式寄存器 "=
  8. 选择拖放寄存器 "* "+ "~
  9. 黑洞寄存器 "_
  10. 搜索模式串寄存器 "/

这10个寄存器都有自己的特定使用场景,等下面分析完之后,你就能很清楚地知道它们都是干嘛的了!
寄存器的分析

在正常模式(normal mode)下,我们使用 "reg 来引用某个寄存器。而在其它情况下,我们使用 @reg 来引用某个寄存器。

例如:

#正常模式,使用寄存器a来复制当前行
"ayy
#命令行模式,为寄存器a赋值
:let @a="some text..."

:let @+=@" 复制到 系统剪切板 +

接下来的文章中,我们将使用 "x 的形式来表示 寄存器x。

OK,下面我们就来分析上述10种寄存器的具体使用场景,以及它们的作用。

1. 未命名寄存器

当我们使用 d, c, s, x 这几个命令修改文本,或者使用 y 复制文本的时候,无论是否指定了寄存器,这些内容会被储存到 "" 寄存器中,除非我们指定了黑洞寄存器 "_

2. 数字寄存器

当我们进行文本的复制或删除操作时,内容就会存储到数字寄存器中。

0号寄存器 "0 储存最近一次复制的内容,除非指定了其它寄存器。

1号寄存器 "1 存储最近一次删除或修改的内容,除非指定了其它寄存器,或内容不到一行(此时将会使用小型删除寄存器 "- )。

如果删除操作与以下移动命令一起使用,那么将总是使用1号寄存器:%,(,), ,/,?,n,N,{,}。此时如果内容不到一行,"- 寄存器会被同时使用。

1号寄存器被再次使用时,原先的内容会转移到2号寄存器,而2号寄存器的内容则转移到3号寄存器,以此类推,最后9号寄存器的内容则会被丢弃。

3. 小型删除寄存器

被删除的内容不到一行时,该寄存器将被使用。
如果我们指定了其它寄存器,则该寄存器不会被使用。

4. 字母寄存器

只有当我们手动指定了字母寄存器时,它们才会被使用。

当我们使用小写形式的字母寄存器时,新内容会覆盖掉之前的内容。
当我们使用大写形式的字母寄存器时,新内容会追加到之前的内容后面。
如果 cpoptions 选项中含有 > 标志,则追加内容时会自动添加换行符。

5. 只读寄存器

只读寄存器的内容只能被读取,也就是说,只能使用 p,P,:put 或 CTRL-R 命令来获取它的内容。

". 存储最后被插入的内容。(与插入模式下使用 CTRL-A 和 CTRL-@ 命令的插入内容一致)
"% 存储当前文件名。
": 存储最后一次在命令行中执行的命令。

6. 交替文件寄存器

存储当前视窗中另一个缓冲区文件的名称。也就是当我们按下 CTRL-^ 时将会跳转到的那个文件的名称。可手动更改它的值,从而让上述命令跳转到指定文件。

let @# = 'buffer_name'

7. 表达式寄存器

表达式寄存器与其它寄存器不同,它并不存储文本内容,而是用于计算表达式的值。在正常模式下输入 "= ,或在插入模式下按 CTRL-R= 时,会进入到命令行,在这输入的命令会经过计算,然后得出结果。

使用表达式寄存器,我们就可以在编辑文件时方便地让Vim替我们完成计算(可以是算术计算,也可以是函数调用),然后把结果插入到文本中。总之,表达式寄存器可以进一步简化我们的工作,非常方便!关于表达式的详细介绍,可以输入命令 :help expression 查看。

这里有两篇介绍表达式寄存器的文章:

Extending vim with the Expression Register
Simple calculations with Vim's expression register

8. 选择拖放寄存器

这是用于存储和获取GUI剪贴板内容的寄存器。当剪贴板不可用时,会自动使用未命名寄存器 "" 来代替。

只读的 "~ 寄存器用于存储拖放到Vim的内容。当有内容拖放到Vim中时,还会触发虚拟按键 ,可以通过映射该键来完成特定任务。

9. 黑洞寄存器

正如它的名字一样,写入该寄存器的内容都会消失。我们可以使用该寄存器来避免其它寄存器受到影响。

读取该寄存器时,返回的内容为空。

10. 搜索模式串寄存器

该寄存器存储了最后一次搜索的模式串,包括使用 / 以及 :g、:s 等命令进行匹配的模式串。

手动对该寄存器赋值,也可高亮搜索结果,与 / 命令的效果一样。
关于宏录制的小技巧

我们在正常模式下录制宏的时候,使用的就是上面介绍的寄存器。除了黑洞寄存器和只读寄存器不能用于录制宏以外,其它寄存器都能够用于录制宏。

当我们录制一串较长的命令时,可能因为某个地方出了错,导致录制失败,需要重新开始。不过,既然录制的宏存放于这些寄存器中,那么我们就能够像读取普通文本一样读取它们。

例如,我使用寄存器 "a 录制了一个宏,但是中间有个地方出了错。这时我可以使用 "ap 将这串命令粘贴下来,然后修改出错的地方,最后选择这串命令,通过 "ay 将它们复制回寄存器 "a 。这样,我们不用重新录制命令,就完成了宏的修改,是不是很方便?

`