这篇我们来谈论vim一个相当重要的东西——自动命令。

从编程的角度来看,自动命令有点类似于事件响应,或者回调函数之类。当外部发生某些事件的时候,自动执行事先定义好的一组命令。

定义一个自动命令的格式如下

autocmd type pattern cmd
  • autocmd: 自动命令以 autocmd 关键字开始,它的作用类似与 js 中定义函数时使用的 function 关键字
  • type: 触发该命令的事件类型
  • pattern: 事件的过滤,根据不同的事件类型有不同的含义
  • cmd : 将要执行的命令

说了这么多,我们以一个例子来说明:

当我们使用 vim 打开一个不存在的文件,如果直接退出,我们会发现它并没有被保存。因为打开一个不存在的文件时 vim 并没有真的在磁盘中创建这么一个文件,它仅仅新开了一个缓冲区,当执行写命令的时候才真正会创建文件。我们使用 q! 退出的话,它是不会往文件中写的

我们来试试修改这一行为,打开新文件的时候就创建,也就是打开一个新文件的时候就执行写操作。打开新文件的事件使用 BufNewFile 来表示。这里我们不限定文件格式,因此 pattern 这块就使用 * 来表示,执行的命令是 :w 来写入。

:autocmd BufNewFile * w

自动命令的事件类型

自动命令可以监听的事件类型主要有以下几种

  • 开始编辑一个当前并不存在的文件,也就是我们上面介绍的一种情况。这种情况使用 BufNewFile 来表示
  • 开始编辑一个已存在的文件。这种情况使用 BufReadPre 或者 BufReadPost 来表示。他们分别表示文件内容被加载前和被加载后
  • 改变一个缓冲区的 filetype 选项的时候,它与 vim 的文件类型配合使用。这种情况使用 FileType 来表示
  • 文件被写回磁盘。这种情况用 BufWritePreBufWritePost。他们的含义与上面 BufReadPreBufReadPost 类似。
  • 进入和退出插入模式,进入插入模式时使用 InsertEnter,退出插入模式时使用 InsertLevel
  • Vim 完成启动所有初始化操作之后可以使用 VimEnter 来表示
  • 输入可以使 vim 退出的命令,可以使用 ExitPre 来表示。如果输入 :quit ,在决定是否退出之前,可以使用 QuitPre

这些只是 vim 庞大事件中的一小部分,想要了解其他的事件,可以使用 :help autocmd-events

同时绑定多个事件

我们可以同时绑定多个事件,事件之间使用逗号作为分割即可,例如我们想要在写入或者加载HTML文件之前对其进行自动排版,那么就可以使用如下代码

:autocmd BufReadPost,BufWritePre *.html normal gg=G

自动命令它是在事件触发时,执行命令。相当于我们在命令模式下手动输入命令。在之前介绍命令模式的时候说到过,要在命令模式下使用普通模式的操作可以使用 normal。gg表示将光标移动到第一行,=G表示从当前光标到最后一行执行自动排版的操作。

我们在 html 文件中输入

<html>
<body>
<div>
<div>
<p>hello!</p>
</div>
</div>
</body>
</html>

执行 :w之后我们发现它自动排版了。或者我们也可以使用 :edit打开一个排版混乱的HTML文件,会发现vim自动为它排版了。



或者我们再举一个例子,我们在之前设置了自动换行功能,因为在一般的编程语言中,一行代码写太长确实不是一个好习惯。但是像 markdown 或者 html 这种用来写文档的标记语言,难免会出现很长的文本,这个时候再设置自动换行就有点不合适了,我们可以使用下面的语句来针对这两种文档来消除

:autocmd BufNewFile, BufReadPost *.html setlocal nowrap

这里我们使用 BufNewFile和 BufReadPost,因为我们需要对新创建的和已存在的 html文件都启用该设置。

FileType 事件

这种类型的事件可以说是我们最常用的,通过这个事件配合 setlocal 可以很方便的针对不同的编程语言做不同的设置

例如我们将上述取消 HTML 自动换行的代码做一个改写,改写成使用 FileType

:autocmd FileType html setlocal nowrap

又或者我们可以根据不同的语言,定义一个快捷键快速添加注释

:autocmd FileType python nnoremap <buffer> <localleader>c I#<esc>
:autocmd FileType javascript nnoremap <buffer> <localleader>c I//<esc>

在输入完命令之后,我们新打开一个 js或者 python文件,就可以直接测试



我们也可以结合之前介绍过的本地缩写的定义,针对不同的文件类型定义不同的缩写,例如

:autocmd FileType c iabbrev <buffer> main int main(int argc, char* argv[])
:autocmd FileType python iabbrev <buffer> main if __name__ == "__main__":

针对不同语言快速填充main函数。

我们结合FileType 事件和缩写似乎可以针对不同语言定义出对应的代码片段,这个也就是有的编辑器提供的 code snippet 的功能,结合插件我们可以使用 vim 定义出更加强大的代码片段

自动命令组

已经讨论了自动命令的这么多东西了,各位小伙伴可能已经掌握了甚至已经开始迫不及待想往配置文件里面添加内容了。但是在 lua中该怎么使用自动命令呢?先别着急,自动命令相关内容还没讨论完,先容我卖个关子,我们在后面来讨论如何在 lua中添加自动命令吧。

我们暂时不讲如何在 lua 中添加自动命令,这里我们先尝试启用 init.vim 文件。我们在里面加入一行

autocmd BufWrite * sleep 200m

然后我们保存并使用 :source $MYVIMRC启用

好像也没什么变化是不是。别着急,我们多次执行 :source $MYVIMRC。然后再执行保存操作。是不是发现vim越来越慢了。这是怎么回事呢?

我们每次执行 :source $MYVIMRC 的时候,vim 不会丢弃原有的设置,只会重头再来读取并加载新的设置,有点像文件的追加。在多次加载配置文件的时候,vim 已经创建了多个自动命令了。随着加载次数的增多,vim 中保存了多个休眠的自动命令了。所以 vim 会变得越来越卡。

你可能会说,谁没事闲着一直加载配置文件玩啊,而且也没有人会写延时吧。但是想想这个场景是不是像我们在反复修改并测试配置的时候会做的操作。虽然我们不会做延时,但是加载配置或者加载插件也是要时间的,插件有的也会执行自动命令,如果数量大起来了,自然会影响vim的启动速度。

我们该如何处理这个问题呢?

vim中给出的解决办法是将自动命令放到一个用户命名的组中,组成一个自动命令组。

使用关键字 augroup 来创建一个自动命令组。例如我们可以创建下面的自动命令组

:augroup testgrp
: autocmd BufWrite * echom "hello1"
: autocmd BufWrite * echom "hello2"
:augroup END

直接在命令行输入这么些东西太麻烦了,我们还是在 init.vim 中输入。启用之后我们再来执行保存操作接着,执行 :message 命令来查看日志,发现有两条打印

我们再来修改一下配置文件或者在命令行输入添加下面一句

:augroup testgrp
: autocmd BufWrite * echom "hello3"
:augroup END

我们先退出vim,再打开,然后执行保存操作,再看看日志里面有几条输出呢?

答案可能会另各位百思不得其解,它会打印三条。并不是各位想象的那样,同名的组发生覆盖。这里它也会发生追加现象,将同一组的多个命令组合在一起。既然用不用组都会追加,那么我要它有何用,我还多写了这么多代码。别着急,我们慢慢往下看。

分组一个是为了划分模块,第二个原因就是我们可以使用 autocmd! 来清除同一组之前的命令。

例如我们将上述命令修改为

:augroup testgrp
: autocmd!
: autocmd BufWrite * echom "hello3"
:augroup END

这个时候再次测试,我们发现它只会打印一条语句了。

但是这里如果我们将它放在不同组的时候,情况就又发生变化了

:augroup testgrp
: autocmd BufWrite * echom "hello1"
: autocmd BufWrite * echom "hello2"
:augroup END :augroup testgrp1
: autocmd!
: autocmd BufWrite * echom "hello3"
:augroup END

我们发现在保存之后,它还是会打印3条语句



autocmd! 只会清除同一组之前的所有命令,而不同组的命令它不会生效。这就给我们按模块划分命名提供了便利。

改进自动加载配置文件的操作

之前我们通过绑定快捷键 <leader>ss来自动重新加载配置,学习了自动命令之后我们可以进一步的偷懒了,利用自动命令,我们可以做到只要配置文件被保存了,就自动加载。

:augroup NVIMRC
: autocmd!
: autocmd BufWritePost init.vim source %
:augroup END

这里我们先使用 autocmd!清除之前的加载操作。后面的自动命令中,我们使用 BufWritePost在配置文件保存到磁盘之后再来执行加载操作,保证从磁盘中加载到的配置文件与我们修改过后的保持一致。

自动命名在我们实现 vim 自动化编程的一个重要工具。甚至 vim 自身也有很多功能依靠它来实现,比如文件类型检测。文件类型检测我们将在下一章进行讨论。

从零开始配置 vim(7)——自动命令的更多相关文章

  1. mac配置vim-go

    基本的设置信息(参考网址:http://hessian.cn/p/1026.html): "还是配置/.vimrc文件. syn on "语法支持 set laststatus=2 ...

  2. sqlplus 配置方法及相关命令

    sqlplus 配置方法及相关命令 1.配置文件 1.1 全局模式什么叫全局模式呢:当我们配置完sqlplus工具加载配置文件后,无论在哪个目录下登陆数据库,您设置[sqlplus提示符样子,在任何目 ...

  3. [转]配置 VIM 的 Go 语言开发环境

    本文是针对像我这样的 VIM 小白而写的,所使用的 VIM-GO 插件虽然步骤简单但不够详细,特写此文以做记录和分享.欢迎各位大神纠正补充! 特别说明 本博文不是 Go 语言环境搭建教程,只是 VIM ...

  4. 从零开始配置TypeScript + React + React-Router + Redux + Webpack开发环境

    转载请注明出处! 说在前面的话: 1.为什么不使用现成的脚手架?脚手架配置的东西太多太重了,一股脑全塞给你,我只想先用一些我能懂的库和插件,然后慢慢的添加其他的.而且自己从零开始配置也能学到更多的东西 ...

  5. Centos6.7下面配置vim及其插件

    Vim是在vi的基础上升级而来的,比vi更强大,提供代码补全,编译功能 [4]vim Vim是从 vi 发展出来的一个文本编辑器.代码补完.编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用 ...

  6. AI应用开发实战 - 从零开始配置环境

    AI应用开发实战 - 从零开始配置环境 与本篇配套的视频教程请访问:https://www.bilibili.com/video/av24421492/ 建议和反馈,请发送到 https://gith ...

  7. centos MySQL主从配置 ntsysv chkconfig setup命令 配置MySQL 主从 子shell MySQL备份 kill命令 pid文件 discuz!论坛数据库读写分离 双主搭建 mysql.history 第二十九节课

    centos  MySQL主从配置 ntsysv   chkconfig  setup命令  配置MySQL 主从 子shell  MySQL备份  kill命令  pid文件  discuz!论坛数 ...

  8. Ubuntu vim java 自动补全javacomeplete2

    一 安装vundle $ git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim 默认安装在/.v ...

  9. Ubuntu14.04配置VIM与GVIM 高亮、跳转与变量函数列表

    一.环境:刚安装好的Ubuntu14.04,本文只能保证 在Ubuntu下能达到效果. 二.安装GVim. sudo apt-get update sudo apt-get install vim-g ...

  10. ubuntu18.04 中个性化配置vim方法

    1:新建配置文件 在终端里输入:vi ~/.vimrc (vimrc是vim的配置文件,每次打开vim时会自动加载这个文件里的配置) 2:配置的代码如下:直接就可以复制到里面然后保存就行 set ai ...

随机推荐

  1. python 升级后 yum 无法使用 File "/usr/bin/yum", line 30 except KeyboardInterrupt, e: `/usr/libexec/urlgrabber-ext-down`

    原因为升级python后新建了软连接指向了新版本,除非同时升级yum不然无法使用.需要手动更改报错文件指向新版本后即可解决. [root@localhost pdserving]# yum insta ...

  2. 关于 VS Code 用户自定义代码片段的官方 $ 命令记录

    关于 VS Code 的定义用户代码片段的部分 $ 命令 TM_SELECTED_TEXT:当前选定的文本或空字符串: 注:选定后通过在命令窗口点选「插入代码片段」插入. TM_CURRENT_LIN ...

  3. centos7.9 安装oracle11g

    安装环境: 操作系统:CentOS Linux release 7.9.2009 (Core)orcle安装包:linux.x64_11gR2_database_1of2.zip. linux.x64 ...

  4. 6 Englishi 词根

    9 pend/pends = hang 悬挂 depend   de 向下 independent   in 前缀 表否定: ent  adj后缀 suspend    sus=sub(便于发音) p ...

  5. 响应式开发bootstrap

    响应式开发原理 就是使用媒体查询针对不同宽度的设备进行布局和样式的设置,从而适配不同设备的目的. 平时我们响应式尺寸划分 超小屏幕(手机,小于768px):设置宽度为100% 小屏幕(平板,大于等于7 ...

  6. P5719 水题

    https://www.luogu.com.cn/problem/P5719 唠唠:别看这题很水,且只要求保留小数点后一位,倘若用float而不是double的话就无法AC,洛谷评测则只有40分.所以 ...

  7. C#单向链表的实现

    节点 public class ListNode { public ListNode(int NewValue) { Value = NewValue; } //前一个 public ListNode ...

  8. 简化 libevent 编译

    在 CMakePresets.json 的 cacheVariables 字段加入 { "EVENT__DISABLE_OPENSSL": "ON", &quo ...

  9. RL 基础 | 讲的很好的 TRPO 博客

    特意存档: 知乎 | 如何看懂TRPO里所有的数学推导细节? 感觉把 idea 讲的很清楚(虽然没有特别仔细看-

  10. 【动画进阶】神奇的 3D 卡片反光闪烁动效

    最近,有群里在群里发了这么一个非常有意思的卡片 Hover 动效,来源于此网站 -- key-drop,效果如下: 非常有意思酷炫的效果.而本文,我们不会完全还原此效果,而是基于此效果,尝试去制作这么 ...