自动命令,是在指定事件发生时自动执行的命令。利用自动命令可以将重复的手工操作自动化,以提高编辑效率并减少人为操作的差错。
比如自定义以下函数,用于在文件中插入当前日期:
:function DateInsert()
: $read !date
:endfunction
使用以下命令,可以手动调用此函数:
:call DateInsert()
而通过以下自动命令,则可以在保存文件时自动执行函数,而不再需要额外的手动操作:
:autocmd FileWritePre * :callDateInsert()<CR>
可以使用以下格式的autocmd命令,来定义自动命令:
:autocmd [group] events pattern [nested] command
events参数
Vim内置了近80个事件,以下表格按照类别列示了较为常用的事件:
类别 | 事件 | 触发条件 |
---|---|---|
读取 | BufNewFile | 编辑一个新文件时 |
BufReadPre | 读入新缓冲区之前 | |
BufRead, BufReadPost | 读入新缓冲区之后 | |
BufReadCmd | 开始编辑新缓冲区之前 | |
FileReadPre | 使用:read命令读入文件之前 | |
FileReadPost | 使用:read命令读入文件之后 | |
StdinReadPre | 由标准输入设备读入缓冲区之前 | |
StdinReadPost | 由标准输入设备读入缓冲区之后 | |
写入 | BufWrite, BufWritePre | 将整个缓冲区写入文件时 |
BufWritePost | 将整个缓冲区写入文件之后 | |
BufWriteCmd | 将整个缓冲区写入文件之前 | |
缓冲区 | BufAdd, BufCreate | 将缓冲区加入缓冲区列表之后 |
BufDelete | 从缓冲区列表中移除缓冲区之前 | |
BufEnter | 进入缓冲区之后 | |
BufLeave | 离开缓冲区之前 | |
BufWinEnter | 在窗口中显示缓冲区之后 | |
BufWinLeave | 从窗口中关闭缓冲区之前 | |
BufNew | 创建缓冲区之后 | |
BufUnload | 卸载缓冲区之前 | |
选项 | FileType | 设置'filetype'选项之后 |
Syntax | 设置'syntax'选项之后 | |
EncodingChanged | 'encoding'选项改变之后触发命令; | |
OptionSet | 设置任何选项之后 | |
启动 退出 | VimEnter | Vim启动并载入初始化文件之后 |
GUIEnter | 启动GUI之后 | |
VimLeavePre | 改写viminfo文件之前,退出Vim之前 | |
VimLeave | 改写viminfo文件之后,退出Vim之前 | |
其它 | FileChangedShell | 当文件的最后修改时间等属性发生改变时 |
InsertEnter | 进入插入模式时 | |
InsertLeave | 离开插入模式时 | |
FocusGained | Vim成为当前窗口时 | |
FocusLost | Vim不再是当前窗口时 | |
WinEnter | 进入窗口时 | |
WinLeave | 离开窗口时 | |
CursorMoved | 在常规模式下移动光标时 | |
CursorMovedI | 在插入模式下移动光标时 | |
CursorHold | 当超过'updatetime'所指定时间用户没有输入时 | |
vimResized | 窗口尺寸变化之后 |
假设我们打开文件并输入文本,然后保存并退出,那么这些操作将以下顺序触发一系列事件:
操作 | 事件 |
---|---|
启动Vim并创建默认窗口 | BufWinEnter |
创建默认缓冲区 | BufEnter |
:edit a.txt | VimEnter |
创建新缓冲区 | BufNew |
将新缓冲区加入到缓冲区列表之中 | BufAdd |
退出默认缓冲区 | BufLeave |
退出默认窗口 | BufWinLeave |
将默认缓冲区从缓冲区列表之中移除 | BufUnload |
删除默认缓冲区 | BufDelete |
将a.txt文件读入新缓冲区 | BufReadCmd |
激活新缓冲区 | BufEnter |
激活新窗口 | BufWinEnter |
进入插入模式 | InsertEnter |
输入文本 | CursorMovedI |
退出插入模式 | InsertLeave |
:wq | BufWriteCmd |
退出新窗口 | BufWinLeave |
将新缓冲区从缓冲区列表之中移除 | BufUnload |
准备退出Vim | VimLeavePre |
退出Vim | VimLeave |
Source: Event-driven scripting and automation
您可以使用以下命令,获得各个事件的详细说明:
:help autocommand-events
pattern参数
匹配模式用来指定应用自动命令的文件。在匹配模式中,可以使用以下特殊字符:
* | 匹配任意长度的任意字符 |
? | 匹配单个字符 |
\? | 匹配字符'?' |
. | 匹配字符'.' |
, | 用于分割多个pattern |
\, | 匹配字符',' |
可以使用逗号来分割多个模式,以匹配多种类型的文件。例如以下命令,将对于.c和.h文件设置'textwidth'选项:
:autocmd BufRead,BufNewFile *.c,*.h set tw=0
您可以使用以下命令,获得匹配模式的详细说明:
:help autocmd-patterns
nested参数
默认情况下,自动命令并不会嵌套执行。例如在自动命令中执行:e或:w命令,将不会再次触发BufRead和BufWrite事件。而使用nested参数,则可以激活嵌套的事件。
:autocmd FileChangedShell *.c nested e!
使用以下命令,可以列出所有自动命令:
:autocmd
你会发现自动命令的列表将会非常的长,其中既包括了在vimrc文件中用户定义的自动命令,也包括了各种插件定义的自动命令。
如果在命令中指定了group,那么将会列出所有与指定group相匹配的自动命令;同理,也可以在命令中指定event和pattern,以查看相匹配的自动命令:
:autocmd filetypedetect * *.htm
使用以下命令,可以删除所有自动命令:
:autocmd!
注意:此操作也将删除插件所定义的自动命令,请谨慎操作。
使用以下命令,可以删除指定组的自动命令:
:autocmd! group
在命令中指定组、事件和匹配模式,可以删除特定的自动命令:
autocmd! Unfocussed FocusLost *.txt
在命令中使用特殊字符“*”来指代所有事件或文件。例如以下命令,将删除Unfocussed组中所有针对txt文件的自动命令:
autocmd! Unfocussed * *.txt
在命令中忽略文件匹配模式,那么所有针对指定事件的针对命令都将被删除。例如以下命令,将删除Unfocussed组在所有针对FocusLost事件的自动命令:
autocmd! Unfocussed FocusLost
通过:augroup
命令,可以将多个相关联的自动命令分组管理,以便于按组来查看或删除自动命令。例如以下命令,将C语言开发的相关自动命令,组织在“cprogram”组内:
:augroup cprograms
: autocmd!
: autocmd FileReadPost *.c :set cindent
: autocmd FileReadPost *.cpp :set cindent
:augroup END
如果我们针对同样的文件和同样的事件定义了多条自动命令,那么当满足触发条件时将分别执行多条自动命令。因此,建议在自动命令组的开头增加:autocmd!命令,以确保没有重复的自动命令存在。
您可以使用以下命令,获得自动命令组的帮助信息:
:help :augroup
通过eventignore选项,可以忽略指定的事件,而不触发自动命令。例如使用以下命令,将忽略进入窗口和离开窗口的事件:
:set eventignore=WinEnter,WinLeave
如果希望忽略所有事件,那么可以使用以下设置:
:set eventignore=all
:autocmd | 定义/查看自动命令 |
:autocmd! | 删除自动命令 |
:augroup | 定义自动命令组 |
:set eventignore | 设置忽略的事件 |