-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathlearn-vi-49-01-autocmd.html
175 lines (163 loc) · 14.3 KB
/
learn-vi-49-01-autocmd.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh" xml:lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="learn-vi.css" />
<title>VIM学习笔记 自动命令(autocmd)</title>
</head>
<body>
<h1>VIM学习笔记 自动命令(autocmd)</h1>
<p>自动命令,是在指定事件发生时自动执行的命令。利用自动命令可以将重复的手工操作自动化,以提高编辑效率并减少人为操作的差错。</p>
<p>比如自定义以下函数,用于在文件中插入当前日期:</p>
<pre><code>:function DateInsert()
: $read !date
:endfunction
</code></pre>
<p>使用以下命令,可以手动调用此函数:</p>
<p style="text-indent:2em"><code class="inset">:call DateInsert()</code></p>
<p>而通过以下自动命令,则可以在保存文件时自动执行函数,而不再需要额外的手动操作:</p>
<p style="text-indent:2em"><code class="inset">:autocmd FileWritePre * :callDateInsert()<CR></code></p>
<h2 class="article"><a id="autocmd-define">定义自动命令</a></h2>
<p>可以使用以下格式的autocmd命令,来定义自动命令:</p>
<p style="text-indent:2em"><code class="inset">:autocmd [group] events pattern [nested] command</code></p>
<ul>
<li><em>group</em>,组名是可选项,用于分组管理多条自动命令;</li>
<li><em>events</em>,事件参数,用于指明触发命令的一个或多个事件;</li>
<li><em>pattern</em>,限定针对符合匹配模式的文件执行命令;</li>
<li><em>nested</em>,嵌套标记是可选项,用于允许嵌套自动命令;</li>
<li><em>command</em>,指明需要执行的命令、函数或脚本。</li>
</ul>
<p style="font-weight:bold">events参数</p>
<p>Vim内置了近80个事件,以下表格按照类别列示了较为常用的事件:</p>
<table summary="Commands" border="1" frame="border" rules="all" cellspacing="0" cellpadding="3">
<tr><th>类别</th><th>事件</th><th>触发条件</th></tr>
<tr><td rowspan="8">读取</td><td><code class="inset">BufNewFile</code></td><td>编辑一个新文件时</td></tr>
<tr><td><code class="inset">BufReadPre</code></td><td>读入新缓冲区之前</td></tr>
<tr><td><code class="inset">BufRead, BufReadPost</code></td><td>读入新缓冲区之后</td></tr>
<tr><td><code class="inset">BufReadCmd</code></td><td>开始编辑新缓冲区之前</td></tr>
<tr><td><code class="inset">FileReadPre</code></td><td>使用:read命令读入文件之前</td></tr>
<tr><td><code class="inset">FileReadPost</code></td><td>使用:read命令读入文件之后</td></tr>
<tr><td><code class="inset">StdinReadPre</code></td><td>由标准输入设备读入缓冲区之前</td></tr>
<tr><td><code class="inset">StdinReadPost</code></td><td>由标准输入设备读入缓冲区之后</td></tr>
<tr><td rowspan="3">写入</td><td><code class="inset">BufWrite, BufWritePre</code></td><td>将整个缓冲区写入文件时</td></tr>
<tr><td><code class="inset">BufWritePost</code></td><td>将整个缓冲区写入文件之后</td></tr>
<tr><td><code class="inset">BufWriteCmd</code></td><td>将整个缓冲区写入文件之前</td></tr>
<tr><td rowspan="8">缓冲区</td><td><code class="inset">BufAdd, BufCreate</code></td><td>将缓冲区加入缓冲区列表之后</td></tr>
<tr><td><code class="inset">BufDelete</code></td><td>从缓冲区列表中移除缓冲区之前</td></tr>
<tr><td><code class="inset">BufEnter</code></td><td>进入缓冲区之后</td></tr>
<tr><td><code class="inset">BufLeave</code></td><td>离开缓冲区之前</td></tr>
<tr><td><code class="inset">BufWinEnter</code></td><td>在窗口中显示缓冲区之后</td></tr>
<tr><td><code class="inset">BufWinLeave</code></td><td>从窗口中关闭缓冲区之前</td></tr>
<tr><td><code class="inset">BufNew</code></td><td>创建缓冲区之后</td></tr>
<tr><td><code class="inset">BufUnload</code></td><td>卸载缓冲区之前</td></tr>
<tr><td rowspan="4">选项</td><td><code class="inset">FileType</code></td><td>设置'filetype'选项之后</td></tr>
<tr><td><code class="inset">Syntax</code></td><td>设置'syntax'选项之后</td></tr>
<tr><td><code class="inset">EncodingChanged</code></td><td>'encoding'选项改变之后触发命令;</td></tr>
<tr><td><code class="inset">OptionSet</code></td><td>设置任何选项之后</td></tr>
<tr><td rowspan="4">启动<br />退出</td><td><code class="inset">VimEnter</code></td><td>Vim启动并载入初始化文件之后</td></tr>
<tr><td><code class="inset">GUIEnter</code></td><td>启动GUI之后</td></tr>
<tr><td><code class="inset">VimLeavePre</code></td><td>改写viminfo文件之前,退出Vim之前</td></tr>
<tr><td><code class="inset">VimLeave</code></td><td>改写viminfo文件之后,退出Vim之前</td></tr>
<tr><td rowspan="11">其它</td><td><code class="inset">FileChangedShell</code></td><td>当文件的最后修改时间等属性发生改变时</td></tr>
<tr><td><code class="inset">InsertEnter</code></td><td>进入插入模式时</td></tr>
<tr><td><code class="inset">InsertLeave</code></td><td>离开插入模式时</td></tr>
<tr><td><code class="inset">FocusGained</code></td><td>Vim成为当前窗口时</td></tr>
<tr><td><code class="inset">FocusLost</code></td><td>Vim不再是当前窗口时</td></tr>
<tr><td><code class="inset">WinEnter</code></td><td>进入窗口时</td></tr>
<tr><td><code class="inset">WinLeave</code></td><td>离开窗口时</td></tr>
<tr><td><code class="inset">CursorMoved</code></td><td>在常规模式下移动光标时</td></tr>
<tr><td><code class="inset">CursorMovedI</code></td><td>在插入模式下移动光标时</td></tr>
<tr><td><code class="inset">CursorHold</code></td><td>当超过'updatetime'所指定时间用户没有输入时</td></tr>
<tr><td><code class="inset">vimResized</code></td><td>窗口尺寸变化之后</td></tr>
</table>
<p>假设我们打开文件并输入文本,然后保存并退出,那么这些操作将以下顺序触发一系列事件:</p>
<table summary="Commands" border="1" frame="border" rules="all" cellspacing="0" cellpadding="3">
<tr><th>操作</th><th>事件</th></tr>
<tr><td>启动Vim并创建默认窗口</td><td><code class="inset">BufWinEnter</code></td></tr>
<tr><td>创建默认缓冲区</td><td><code class="inset">BufEnter</code></td></tr>
<tr><td>:edit a.txt</td><td><code class="inset">VimEnter</code></td></tr>
<tr><td>创建新缓冲区</td><td><code class="inset">BufNew</code></td></tr>
<tr><td>将新缓冲区加入到缓冲区列表之中</td><td><code class="inset">BufAdd</code></td></tr>
<tr><td>退出默认缓冲区</td><td><code class="inset">BufLeave</code></td></tr>
<tr><td>退出默认窗口</td><td><code class="inset">BufWinLeave</code></td></tr>
<tr><td>将默认缓冲区从缓冲区列表之中移除</td><td><code class="inset">BufUnload</code></td></tr>
<tr><td>删除默认缓冲区</td><td><code class="inset">BufDelete</code></td></tr>
<tr><td>将a.txt文件读入新缓冲区</td><td><code class="inset">BufReadCmd</code></td></tr>
<tr><td>激活新缓冲区</td><td><code class="inset">BufEnter</code></td></tr>
<tr><td>激活新窗口</td><td><code class="inset">BufWinEnter</code></td></tr>
<tr><td>进入插入模式</td><td><code class="inset">InsertEnter</code></td></tr>
<tr><td>输入文本</td><td><code class="inset">CursorMovedI</code></td></tr>
<tr><td>退出插入模式</td><td><code class="inset">InsertLeave</code></td></tr>
<tr><td>:wq</td><td><code class="inset">BufWriteCmd</code></td></tr>
<tr><td>退出新窗口</td><td><code class="inset">BufWinLeave</code></td></tr>
<tr><td>将新缓冲区从缓冲区列表之中移除</td><td><code class="inset">BufUnload</code></td></tr>
<tr><td>准备退出Vim</td><td><code class="inset">VimLeavePre</code></td></tr>
<tr><td>退出Vim</td><td><code class="inset">VimLeave</code></td></tr>
</table>
<p style="color:gray; font-size:0.6em; margin:0; padding:0"><a href="https://developer.ibm.com/tutorials/l-vim-script-5/" title="">Source: Event-driven scripting and automation</a></p>
<p>您可以使用以下命令,获得各个事件的详细说明:</p>
<p style="text-indent:2em"><code class="inset">:help autocommand-events</code></p>
<p style="font-weight:bold">pattern参数</p>
<p>匹配模式用来指定应用自动命令的文件。在匹配模式中,可以使用以下特殊字符:</p>
<table summary="Commands" border="1" frame="border" rules="all" cellspacing="0" cellpadding="3">
<tr><td><code class="inset">*</code></td><td>匹配任意长度的任意字符</td></tr>
<tr><td><code class="inset">?</code></td><td>匹配单个字符</td></tr>
<tr><td><code class="inset">\?</code></td><td>匹配字符'?'</td></tr>
<tr><td><code class="inset">.</code></td><td>匹配字符'.'</td></tr>
<tr><td><code class="inset">,</code></td><td>用于分割多个pattern</td></tr>
<tr><td><code class="inset">\,</code></td><td>匹配字符','</td></tr>
</table>
<p>可以使用逗号来分割多个模式,以匹配多种类型的文件。例如以下命令,将对于.c和.h文件设置'textwidth'选项:</p>
<p style="text-indent:2em"><code class="inset">:autocmd BufRead,BufNewFile *.c,*.h set tw=0</code></p>
<p>您可以使用以下命令,获得匹配模式的详细说明:</p>
<p style="text-indent:2em"><code class="inset">:help autocmd-patterns</code></p>
<p style="font-weight:bold">nested参数</p>
<p>默认情况下,自动命令并不会嵌套执行。例如在自动命令中执行:e或:w命令,将不会再次触发BufRead和BufWrite事件。而使用nested参数,则可以激活嵌套的事件。</p>
<p style="text-indent:2em"><code class="inset">:autocmd FileChangedShell *.c nested e!</code></p>
<h2 class="article"><a id="autocmd-list">查看自动命令</a></h2>
<p>使用以下命令,可以列出所有自动命令:</p>
<p style="text-indent:2em"><code class="inset">:autocmd</code></p>
<p><a href="https://yyq123.github.io/learn-vim/images/autocmd.png" title="autocmd"><img src="https://yyq123.github.io/learn-vim/images/autocmd.png" alt="autocm" width="550" height="276" /></a></p>
<p>你会发现自动命令的列表将会非常的长,其中既包括了在vimrc文件中用户定义的自动命令,也包括了各种插件定义的自动命令。</p>
<p>如果在命令中指定了group,那么将会列出所有与指定group相匹配的自动命令;同理,也可以在命令中指定event和pattern,以查看相匹配的自动命令:</p>
<p style="text-indent:2em"><code class="inset">:autocmd filetypedetect * *.htm</code></p>
<p><a href="https://yyq123.github.io/learn-vim/images/autocmd_list.png" title="autocmd_list"><img src="https://yyq123.github.io/learn-vim/images/autocmd_list.png" alt="autocm_list" /></a></p>
<h2 class="article"><a id="autocmd-remove">删除自动命令</a></h2>
<p>使用以下命令,可以删除所有自动命令:</p>
<p style="text-indent:2em"><code class="inset">:autocmd!</code></p>
<p>注意:此操作也将删除插件所定义的自动命令,请谨慎操作。</p>
<p>使用以下命令,可以删除指定组的自动命令:</p>
<p style="text-indent:2em"><code class="inset">:autocmd! group</code></p>
<p>在命令中指定组、事件和匹配模式,可以删除特定的自动命令:</p>
<p style="text-indent:2em"><code class="inset">autocmd! Unfocussed FocusLost *.txt</code></p>
<p>在命令中使用特殊字符“*”来指代所有事件或文件。例如以下命令,将删除Unfocussed组中所有针对txt文件的自动命令:</p>
<p style="text-indent:2em"><code class="inset">autocmd! Unfocussed * *.txt</code></p>
<p>在命令中忽略文件匹配模式,那么所有针对指定事件的针对命令都将被删除。例如以下命令,将删除Unfocussed组在所有针对FocusLost事件的自动命令:</p>
<p style="text-indent:2em"><code class="inset">autocmd! Unfocussed FocusLost</code></p>
<h2 class="article"><a id="augroup">自动命令组</a></h2>
<p>通过<code class="inset">:augroup</code>命令,可以将多个相关联的自动命令分组管理,以便于按组来查看或删除自动命令。例如以下命令,将C语言开发的相关自动命令,组织在“cprogram”组内:</p>
<pre><code>:augroup cprograms
: autocmd!
: autocmd FileReadPost *.c :set cindent
: autocmd FileReadPost *.cpp :set cindent
:augroup END
</code></pre>
<p>如果我们针对同样的文件和同样的事件定义了多条自动命令,那么当满足触发条件时将分别执行多条自动命令。因此,建议在自动命令组的开头增加:autocmd!命令,以确保没有重复的自动命令存在。</p>
<p>您可以使用以下命令,获得自动命令组的帮助信息:</p>
<p style="text-indent:2em"><code class="inset">:help :augroup</code></p>
<h2 class="article"><a id="autocmd-option">自动命令选项</a></h2>
<p>通过eventignore选项,可以忽略指定的事件,而不触发自动命令。例如使用以下命令,将忽略进入窗口和离开窗口的事件:</p>
<p style="text-indent:2em"><code class="inset">:set eventignore=WinEnter,WinLeave</code></p>
<p>如果希望忽略所有事件,那么可以使用以下设置:</p>
<p style="text-indent:2em"><code class="inset">:set eventignore=all</code></p>
<table summary="Commands" border="2" frame="hsides" rules="all" cellspacing="0" cellpadding="3">
<caption>命令小结</caption>
<tr><td><code class="inset">:autocmd</code></td><td>定义/查看自动命令</td></tr>
<tr><td><code class="inset">:autocmd!</code></td><td>删除自动命令</td></tr>
<tr><td><code class="inset">:augroup</code></td><td>定义自动命令组</td></tr>
<tr><td><code class="inset">:set eventignore</code></td><td>设置忽略的事件</td></tr>
</table>
<p style="border-top:1px solid lightgray"><span style="float:right">Ver: 2.0 | <a href="mailto:[email protected]">YYQ</a></span><span><<a title="配置文件(vimrc)" href="http://yyq123.github.io/learn-vim/learn-vi-59-vimrc.html">上一篇</a> |<a title="笔记列表" href="http://yyq123.github.com/learn-vim/learn-vi-00-00-TOC.html"> 目录 </a>| <a title="命令相关选项(Options-CMD)" href="http://yyq123.github.io/learn-vim/learn-vi-46-03-CMD-Options.html">下一篇</a>></span></p>
</body>
</html>