文艺复兴·VIM使用指南·Day 3

688 阅读8分钟

本章我们学习寄存器/跳转列表等知识,以及他们的应用:复制/粘贴/撤销/重做/跳转,同时介绍一个各个GUI编辑器都支持的多行编辑。

👁️前置任务

本章我们要利用好已经学过的能力。首先来复习一下如何使用原生的帮助文档

:h              # 打开帮助
:h y            # 查看y命令帮助
["x]y{motion}   # y命令前可选一个寄存器,后面需要搭配motion使用
{Visual}["x]y   # 在Visual模式下使用y命令,y命令前可选一个寄存器
<C-]>           # 文档跳转
<C-o>           # 跳回
y/Y             # 一个命令的小写和大写往往有关联,比如o向下另起一行,O向上另起一行。
{count}{motion} # 执行{count}次{motion}

利用好这些能力可以帮助我们阅读好文档。

🧳寄存器

寄存器是程序中用于存储特定数据的单元,使用:reg命令可以查看当前寄存器情况。vim中用[”x]表示寄存器,x表示寄存器名字。

一共有这十种寄存器:

1. 未命名寄存器[””]                        d/c/s/x/y命令处理的文本除了被其他寄存器处理外,还被存储在未命名寄存器,就像是未命名寄存器指向了最后一个使用的寄存器一样。
2. 10个数字编号的寄存器[”0]-[”9]            和yank/delete命令相关的文本被存储在数字寄存器。0/1寄存器分别存储yank和delete产生的最新文本,就文本被依次序传入2/3/4...9,最多到93. 删除号寄存器[”-]                        存储删除文本少于一行的
4. 26个字母寄存器,不区分大小写[”a]-[”z]      存储自定义的文本,小写字母覆盖,大写字母添加
5. 三个只读寄存器[”,] [”.] [”%]            存储文件、当前行、当前命令等。只能和p/P命令结合使用
6. 可选缓存寄存器[”#]                      存储当前窗口可选文件的名字
7. 表达式寄存器[”=]                        存储命令字符串
8. 选择区域寄存器[”*] [”+]                 存储选择的文本。"*y可以把选区复制到系统剪切板
9. 黑洞(the black hole)寄存器[”_]         这个寄存器不做任何事情
10. 上一次搜索模式寄存器[”/]                存储上次搜索的模式匹配字符串

vim的寄存器你可以理解为内存中的一个缓存机制,它类似于一些程序语言中的buffer,但它确实和汇编里面的寄存器很相似。

:reg命令输出格式

Type   Name   Content
c       "0    123
l       ""    aaa

宏录制和播放

这是实现强大的自动化能力的方式。我们要用到这两个命令

q                 # 实现宏定义,q["x]{motion}q 可以把你的motion定义到x寄存器
@                 # 调用寄存器,并执行寄存器内的命令

最简单的宏录制:新增一百行。

qao<Esc>q         # q["x]{motion}q 给寄存器存储o<Esc>命令
100@a             # {count}@a 调用count次寄存器a的命令

vim.day3.macro.gif

在这个基础上,可以复杂一点,新增一百行,并给出序号

o1.<Esc>          # 写入1.
qayypj_<C-a>q     # 复制当前行到下一行,移动到新行头部,增加数字。操作记录入寄存器a
100@a             # 得到结果

vim.day3.macro-list.gif

寄存器调用

除了在以后的VimScript中我们会使用到寄存器外,正常的编辑行为也支持快捷键。

<C-r>0                  # 读取寄存器信息并粘贴到光标处

也就是说你可以在Insert模式中使用命令调用指定寄存器的内容,上述文本表示我们取用了[”0]寄存器,得到最后一次被yank(vim的复制)的内容。

vim.day3.insert-mode-call-register.gif

😼复制粘贴

现在我们来看一下复制粘贴命令。vim里面的复制,使用英文yank表示,简写为y复制命令实际是把文本转存到某个寄存器里面了,复制命令支持指定寄存器复制。

["x]y{motion}            # 如果没有文本可以被复制,则复制motion,复制地点为[x]寄存器。比如"ay,复制到a寄存器
["x]yy                   # 复制行,可以带{count},复制多行
["x]Y                    # 复制光标到行结尾,不带换行符
{Visual}["x]y            # 复制选区文本
{Visual}["x]Y            # 复制选区行,多行

["x]p                    # 可以带{count} 把寄存器的内容粘贴到光标后面 {count}多次
["x]P                    # 可以带{count} 把寄存器的内容粘贴到光标前面 {count}多次

当你不清楚哪个寄存器存入了数据,你可以使用**:reg查看寄存器状态,然后通过[”x]p**来粘贴对应的内容。根据我们第一节讲到的寄存器概念,实际上p就是””p的缩写~,也就是说p会得到最后一次yank或者delete的内容。

vim.day3.yank.gif

这里需要明确一个概念,就是vim中的复制粘贴都是相对寄存器来说的,你可以看到命令的定义都是基于寄存器的,因此要想实现操作系统的剪贴板复制粘贴,可以自定义命令。

{Visual}"*y              # 把选取内容复制到[*]寄存器。这个寄存器同时也复制到操作系统
{Normal}"*y{motion}      # 普通模式执行,把motion的结果复制到寄存器,同时也复制到操作系统
"*p                      # 把[*]寄存器的内容取出并粘贴

使用「{Normal}"*y{motion}」复制两行到剪贴板:

vim.day3.yank-clipboard.gif

[*] [+]寄存器就是你和操作系统的剪贴板交互的功能。因此你可以映射一下

vmap Y "*y               " Visual模式下Y命令把选区复制到剪贴板
nmap PP "*p              " Normal模式下PP命令把剪贴板内容粘贴

👨‍🍳撤销/重做

编辑器里面,通用的撤销和重做英文对应undo/redo。vim直接就用了这两个单词的首字母。同样你可以用{count}表示需要undo/redo的次数。

u                       # 撤销上一个动作
<C-r>                   # 取消上一个撤销动作

vim.day3.redo-undo.gif

除了使用u/之外,你的文本编辑状态是被vim记录了的,因此你还可以在任意状态中穿梭。

:undol[ist]             # 查看可以使用的undo清单
g-                      # 进入上一个编辑状态 对应:earlier
g+                      # 进入下一个编辑状态 对应:after
:earlier {count}        # {count}个状态之前
:earlier {N}s           # N秒之前的状态,同理可以用s/m/h/d 秒/分/时/天
:after{count}           # {count}个状态之后
:after {N}s             # N秒之后的状态,同理可以用s/m/h/d 秒/分/时/天

不过日常写代码,用的最多的还是u/组合

👯‍♂️多行编辑

之前我们提到过多行编辑的功能。使用命令可以进入块选择模式,需要多行编辑可以

  1. 进入块选择模式
  2. {motion} 选择区域
  3. i/I 进入插入
  4. 或<C-[> 退出

这里需要注意,退出不会检查缩写,也不会执行InsterLeave的自动触发事件,因此必须用或<C-[>进行退出

vim.day3.multiple-lines.gif

✨跳转

跳转列表-jumps

在vim世界,光标位置也是被记录的,自然也可以查看历史位置、调用历史位置。跳转列表就像是一个函数调用栈,在这个栈里面你可以用JumpIn/JumpOut的方式读取一个函数的内容。而生成跳转列表的逻辑,就是motion。motion触发光标转移,转移前后的位置被跳转列表记录,生成一个调用链。

:ju[mps]             # 可以查看当前的跳转列表
:cle[arjumps]        # 清除当前的跳转列表

跳转列表显示如下

jump    line    col    file/text
 3       1       0      some text
 2       70      0      another text
 1      1154     23     end.

几列分别表示跳转列表的第几个/光标行号/光标列号/对应的文件或文本。

你可以使用下面两个组合来在跳转表中进行跳转

<C-i>               # 跳入,往前跳
<C-o>               # 跳出,往后跳

以下常用命令可以进行跳转(类型上属于text motion文本光标操作),你可以用/进行组合使用

gg                  # 跳转到文件头部
G                   # 跳转到文件尾部
[[                  # 往上章节section跳转
]]                  # 往下章节section跳转
{                   # 往上段落paragraph跳转
}                   # 往下段落paragraph跳转
(                   # 往上句子sentence跳转
)                   # 往下句子sentence跳转

实际上,你可以理解为一些大幅度跳转光标的操作,都会被跳转列表记录。现在你只需要记住这一点,然后在实践中多运用和两个命令。

change list jumps

同时,所有的修改也被记录到了列表,形成了修改记录

:changes            # 查看当前的修改列表

修改列表和跳转列表类似,行号表示修改产生的光标位置。

change   line  col   text
 3         16   0     abcdef
 2         35   3     abc
 1         7    3     aadf6

有很多方式可以产生一个change,新增/修改/删除都算,新增文本可以是insert(i)也可以是paste(p),修改可以是change(c),删除可以是x/X

你可以使用下面的组合来跳转

g;                  # {count}个以前的修改位置
g,                  # {count}个以后的修改位置

vim.day3.jumps.gif

🗡️总结

今天我们学习了几个重要的概念,以及一些高级的编辑器操作,赶快去运用一下吧~

  1. 寄存器。寄存器基础概念,存储和调用
  2. 跳转。跳转列表,修改列表,跳转
  3. 多行编辑。
  4. 撤销/重做
  5. 复制粘贴

有了这些概念,你可以做一些更丰富的操作了,特别是寄存器,可以让你任意存/取文本。

下一次我们将讲讲搜索/替换(搜索和替换会用到更深入的知识)