自动命令¶
自动命令,是在指定事件发生时自动执行的命令。利用自动命令可以将重复的手工操作自动化,以提高编辑效率并减少人为操作的差错。
定义自动命令¶
自动命令的格式:
:autocmd [group] events pattern [nested] command
- group 组名(可选项),用于分组管理多条自动命令
- events 事件参数,用于指明触发命令的一个或多个事件
- pattern 限定针对符合匹配模式的文件执行命令
- nested 嵌套标记是可选项,用于允许嵌套自动命令
- command 指明需要执行的命令、函数或脚本
events 参数¶
Vim 内置了近 80 个事件,可以使用以下命令查看各个事件的详细说明:
:help autocommand-events
以下为较常用的事件:
| 类别 | 事件 | 触发条件 |
|---|---|---|
| 读取 | 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 example.txt | VimEnter |
| 创建新缓冲区 | BufNew |
| 将新缓冲区加入到缓冲区列表中 | BufAdd |
| 退出默认缓冲区 | BufLeave |
| 退出默认窗口 | BufWinLeave |
| 将默认缓冲区从缓冲区列表中移除 | BufUnload |
| 删除默认缓冲区 | BufDelete |
| 将 demo.txt 读入新缓冲区 | BufReadCmd |
| 激活新缓冲区 | BufEnter |
| 激活新窗口 | BufWinEnter |
| 进入插入模式 | InsertEnter |
| 输入文本 | CursorMovedI |
| 退出插入模式 | InsertLeave |
| 将文件内容保存到磁盘 | BufWriteCmd |
| 退出新窗口 | BufWinLeave |
| 将新缓冲区从缓冲区列表中移除 | BufUnload |
| 准备退出 Vim | VimLeavePre |
| 退出 Vim | VimLeave |
参考: 事件驱动的脚本和自动化
pattern 参数¶
使用以下命令查看匹配模式的详细说明:
:help autocmd-patterns
匹配模式用来指定应用自动命令的文件。在匹配模式中,可以使用以下特殊字符:
*匹配任意字符串?匹配单个字符\?匹配英文问号字符.匹配英文句号字符,分割多个 pattern\,匹配英文逗号字符
可以使用逗号来分割多个模式,以匹配多种类型的文件。例如以下命令,对于 .c 和 .h 文件设置 textwidth 选项:
:autocmd BufRead,BufNewFile *.c,*.h set tw=0
nested 参数¶
默认情况下,自动命令并不会嵌套执行。例如在自动命令中执行 :e 或 :w 命令,不会再次触发 BufRead 和 BufWrite 事件。而使用 nested 参数,则可以激活嵌套的事件。
:autocmd FileChangedShell *.c nested e!
查看自动命令¶
使用以下命令,可以查看所有自动命令:
:autocmd
--- Autocommands ---
filetypedetect BufEnter
*.xpm if getline(1) =~ "XPM2" | setf xpm2 | else | setf xpm | endif
*.xpm2 setf xpm2
BufEnter
* if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTre
e()) | q | endif
NERDTree BufEnter
NERD_tree_*
stopinsert
NERDTreeHijackNetrw BufEnter
* call nerdtree#checkForBrowse(expand('<amatch>'))
Vimball BufEnter
*.vba setlocal bt=nofile fmr=[[[,]]] fdm=marker|if &ff != 'unix'|setloca
l ma ff=unix noma|endif|if line('$') > 1|call vimball#ShowMesg(0,"Source this fi
le to extract it! (:so %)")|endif
*.vba.gz setlocal bt=nofile fmr=[[[,]]] fdm=marker|if &ff != 'unix'|setloca
l ma ff=unix noma|endif|if line('$') > 1|call vimball#ShowMesg(0,"Source this fi
le to extract it! (:so %)")|endif
*.vba.bz2 setlocal bt=nofile fmr=[[[,]]] fdm=marker|if &ff != 'unix'|setloca
l ma ff=unix noma|endif|if line('$') > 1|call vimball#ShowMesg(0,"Source this fi
le to extract it! (:so %)")|endif
自动命令的列表将非常的长,其中既包括了在 vimrc 配置文件中定义的自动命令,也包括了各种插件定义的自动命令。
如果在命令中指定了 group,那么将会列出所有与指定 group 相匹配的自动命令;同理,也可以在命令中指定 event 和 pattern,以查看相匹配的自动命令:
:autocmd filetypedetect * *.html
--- Autocommands ---
filetypedetect BufNewFile
*.html call dist#ft#FThtml()
filetypedetect BufRead
*.html call dist#ft#FThtml()
删除自动命令¶
使用以下命令,可以删除所有自动命令:
:autocmd!
提示
此操作将删除所有自动命令,包括插件所定义的自动命令,请谨慎操作。
在命令中指定组、事件和匹配模式,可以删除特定的自动命令:
:autocmd! Unfocussed FocusLost *.txt
在命令中使用 * 来指代所有事件或文件。例如以下命令,将删除 Unfocussed 组中所有针对 txt 文件的自动命令:
:autocmd! Unfocussed * *.txt
在命令中忽略文件匹配模式,所有针对指定事件的命令都将被删除。例如以下命令,将删除 Unfocussed 组在所有针对 FocusLost 事件的自动命令:
:autocmd! Unfocussed FocusLost
自动命令组¶
可以使用以下命令,获得自动命令组的帮助信息:
:help :augroup
通过 :augroup 命令,可以将多个相关联的自动命令分组管理,以便于按组来查看或删除自动命令。例如以下命令,将 C 语言开发的相关自动命令,组织在 cprogram 组内:
:augroup cprograms
: autocmd!
: autocmd FileReadPost *.c :set cindent
: autocmd FileReadPost *.cpp :set cindent
:augroup END
如果针对同样的文件和同样的事件定义了多条自动命令,那么当满足触发条件时将分别执行多条自动命令。因此,建议在自动命令组的开头增加 :autocmd! 命令,确保不会重复的执行自动命令。
自动命令选项¶
通过 eventignore 选项,可以忽略指定的事件,而不触发自动命令。例如使用以下命令,将忽略进入窗口和离开窗口的事件:
:set eventignore=WinEnter,WinLeave
如果希望忽略所有事件,那么可以使用以下设置:
:set eventignore=all
使用实例¶
- 自动切换中英文输入法,
!为 shell 命令。
GUIEnter * :silent !ibus engine xkb:us::eng
InsertLeave * :silent !ibus engine xkb:us::eng
InsertEnter * :silent !ibus engine libpinyin
VimLeave * :silent !ibus engine libpinyin
- 调用自定义函数。
:function DateInsert()
: $read !date
:endfunction
" 调用函数
FileWritePre * :callDateInsert()
- 离开 Vim 编辑器时,自动保存文件:
:autocmd FocusLost * :wa
- 根据文件类型执行自动命令
"删除 php 文件行尾的空格
autocmd BufEnter *.php :%s/[ \t\r]\+$//e
"根据文件类型载入插件
autocmd Filetype html,xml,xsl source $VIM/vimfile/plugin/closetag.vim
"根据文件类型设置键盘映射
autocmd bufenter *.tex map <F1> :!latex %<CR>
"根据文件类型设置不同的选项
autocmd FileType ruby setlocal ts=2 sts=2 sw=2 expandtab