如何用好 vim 里面的宏

引言

在我学习 vim 的过程中,最具有启发意义的一句话是:

vim 其实是一门编程语言

很早之前我就接触过 vim,但是当时 vim 的按键组合和按键的逻辑对我来说很难记忆,再加上 vim 的界面实在太过于复古,于是我就转向了比较现代的文本编辑器。但当我学完 Missing semester 的时候,我对 vim的看法完全改观:它远远不止是一个文本编辑器

这似乎和这篇博客要讨论的主题没有关系。但其实不是这样的,认识到 vim 是一门编程语言是一件重要的事情。程序员经常经常通过编程来完成很多枯燥重复的工作,不同人对编程语言的偏好各不相同。vim 也可以完成这样的任务,今天要讨论的宏就是。我希望看完这一篇之后 vim 也会被你们用来解决一些问题🚀

什么是 vim 里面的宏

下面假定你对 vim 有一定的了解 : )

vim 里面,我们可以用 . 重复上一次的“更改”,这里的“更改”一般指的是比较简单的操作,比如删除一个单词等

但其实,vim 也提供了宏让我们可以重复执行一些比较复杂的操作,它会把我们的操作记录下来,存放到指定的寄存器里面。那么我们可以只录制宏一次而执行它很多次

基本指南

### 怎么录制一个宏

步骤

  1. 在 Normal 模式下,按q<register>.

    1. 这里的意思是说先按q 然后选择一个寄存器 register 来存放待会录制的宏

    2. 可以选用的寄存器 regitser 包括: 0-9, a-z, 和 "。关于这里为什么没有大写字母我会在后面解释

  2. 开始录制宏,如果上一步正确执行的话,此时你应该会看到左下角显示 recording @<register>。从此刻起,你所有的操作都会被录制下来

  3. 再次按下 q 退出录制

📒 要让自己录制的宏鲁棒性强一点,关键在于你在录制的时候要想想:不同的 文件可能会有哪些情况要处理,要保证自己的每一步都可以在各种不同的情况里面复现出来

怎么查看宏的内容

前面提到,vim 会把我们录制的宏存放在指定的寄存器里面,所以查看宏的内容很简单,用一个简单的 :reg 命令就行,比如

:reg <register>

里面你会看到一些奇怪的字符,比如

  • ^[<ESC>

  • <80>kbBAKESPACE

怎么执行宏

在一个文件里面执行

  • @<register>: 执行存放在 <register> 这个寄存器里面的宏

  • @@: 执行我们上一次调用过的宏

  • 如果想要多次执行的话,在命令的前面先输入 [COUNT] 表示要执行多少次。

    • e.g. 100@@ 的意思是:执行上一次调用的宏 100 次
    • 有时候我们想要在这个文件里面重复执行直到整个文件都修改完,但是我们没有必要自己手动计算这个次数 [COUNT] 应该是多少,可以设置一个很大的值,超过的部分会被 vim 忽略

在多个文件里面执行

当然,如果只能在一个文件里面重复执行宏的话,能用它来解决的问题还比较局限。我们总不可能每次都要打开一个文件然后手动输入 @@ 执行宏。好在 vim 提供了方法让我们可以批量处理多文件

比如说现在我们想要编辑当前目录下的所有 txt 文件,只要在命令行输入 vim *.txt 就可以打开所有文件(每个文件对应一个 buffer,整体可以看成是一个列表)。在这个模式下我们可以一次编辑一个文件,编辑完毕之后按 :wn 保存当前文件的更改并跳转到下一个文件。但我们也能一次性对这个文件列表里的所有文件进行更改

  1. 此时我们位于文件列表的第一个文件,第一件要做的事情是以第一个文件文样本录制宏
    1. 注意录制完毕之后,需要使用 :edit! 命令撤销在录制宏对过程中对第一个文件的更改。因为我们之后会对文件列表中所有对文件应用我们对宏,如果没有这个撤销操作的话,第一个文件就会被更改两次
    2. 虽然界面看起来像是在编辑一个文件,但如果你要直接按 :x 保存退出的话就会弹出警告
  2. 输入命令: :bufdo execute "normal @<register> | update.
    1. 关于 bufdo 的说明可以在 vim 里面输入 :h bufdo 查看。可以理解为对所有的 buffer 执行操作
    2. 这里的 normal @<register> 的意思就是在 Normal 模式下执行 @<register> 里面的宏

更多的细节可以看这里

怎么修改已经录制好的宏

简单情况

这里说的简单情况是,你只是想要在你本来录制好的宏后面追加一些操作。还记得之前我刻意跳过了把 A-Z 当作寄存器的这个情况吗?事实上,当你用大写字母的寄存器的时候,你录制的东西会追加在对应的小写寄存器的内容后面

复杂情况

此时你要编辑宏,但是要编辑的位置是在宏的中间,这也是可以实现的吗?当然,我们没有必要从头录制,宏其实本质上只是存储在寄存器里面的字符序列,vim 可以解读这些内容重复执行。我们要做的事情只是修改寄存器里面的内容而已。

具体步骤如下:

  1. 按下 G 跳转到当前文件的最后一行(其实别的行也可以,只是跳转到最后一行我们编辑宏的时候比较不会受到干扰),然后输入 :put <register> 命令,对应寄存器里面的内容就会被粘贴在下一行
  2. 然后我们开始编辑就行
  3. 编辑完成之后(确保还在这一行),按下 :d <register> 就可以把当前行的内容存回去

下面是我录制的一个简单的例子,我们来录制了一个宏放在寄存器 y 里面,功能是在当前行的末尾追加 world,现在我想要修改在当前行追加 hello world

和其他工具协同工作

在 Linux 中,我们可以将一些命令行工具和 vim 结合使用。一个使用场景比如:我们想要批量编辑一些文件,但是这个文件散落在不同的地方。那我们就可以使用 find 命令和 vim 做到这件事情。可以参考这个.

  1. 使用 find <pattern> -exec vim {} + 打开所有对应的文件
  2. 使用之前提到过的 bufdo 命令批量操作

总结

这只是一个简单的关于 vim 里面宏的应用,这只是 vim 强大功能的冰山一角,当你掌握其他 vim 相关的功能的时候(比如搜索与替换,快速定位到某个位置),才能发挥出 vim 的最大效力。如果这篇博客可以让你对 vim 产生兴趣那就再好不过。别忘了一句著名的话:一开始我们挑选了我们喜欢的工具,后来工具会反过来塑造我们,它甚至影响着我们的思维😉

posted @ 2022-07-02 21:55  MartinLwx  阅读(347)  评论(0编辑  收藏  举报