Autocmd

Nvim :help 页面,生成源代码 使用 tree-sitter-vimdoc 解析器。


自动命令 autocommand
有关基本解释,请参见用户手册中的第 40.3 节。

1. 简介 autocmd-intro

您可以指定在读取或写入文件、进入或离开缓冲区或窗口以及退出 Vim 时自动执行的命令。例如,您可以创建一个自动命令来设置 'cindent' 选项,以匹配 *.c 的文件。您还可以使用自动命令来实现高级功能,例如编辑压缩文件(请参见 gzip-example)。将自动命令放在 vimrc 文件中的通常位置。
E203 E204 E143 E855 E937 E952 警告:使用自动命令功能非常强大,可能会导致意想不到的副作用。请注意不要破坏您的文本。
最好先在可废弃的文件副本上进行一些测试。例如:如果您使用自动命令在开始编辑文件时解压缩文件,请确保用于在写入时压缩文件的自动命令能正常工作。
要做好中途出错的准备(例如,磁盘已满)。Vim 通常能够撤销对缓冲区的更改,但您可能需要手动清理对其他文件的更改(例如,压缩已解压缩的文件)。
如果 BufRead* 事件允许您编辑压缩文件,则 FileRead* 事件应该也能做到这一点(这使得在某些极端情况下可以进行恢复)。最好在可能的情况下对 File* 和 Buf* 事件使用相同的自动命令。

2. 定义自动命令 autocmd-define

:au :autocmd :au[tocmd] [group] {event} {aupat} [++once] [++nested] {cmd}{cmd} 添加到 Vim 将在 {event} 上自动执行的命令列表中,用于匹配 {aupat} 的文件 autocmd-pattern注意:引号字符被视为 :autocmd 的参数,不会开始注释。Nvim 始终在现有自动命令之后添加 {cmd},因此它们按定义顺序执行。有关 [++nested],请参见 autocmd-nestedautocmd-once
如果提供了 [++once],则该命令将执行一次,然后删除(“一次性”)。
特殊模式 <buffer> 或 <buffer=N> 定义了缓冲区局部自动命令。请参见 autocmd-buflocal
注意:“:autocmd”命令只能在模式预期出现的位置出现“|”时才能后跟另一个命令。这有效
:augroup mine | au! BufRead | augroup END
但这将“augroup”视为已定义命令的一部分
:augroup mine | au! BufRead * | augroup END
:augroup mine | au BufRead * set tw=70 | augroup END
相反,您可以将组名放在命令中
:au! mine BufRead *
:au mine BufRead * set tw=70
或者使用 :execute
:augroup mine | exe "au! BufRead *" | augroup END
:augroup mine | exe "au BufRead * set tw=70" | augroup END
autocmd-expand
请注意,“:autocmd”参数中的特殊字符(例如,“%”、“<cword>”)在定义自动命令时不会扩展。这些将在识别事件时扩展,并且将执行 {cmd}。唯一例外是 "<sfile>" 会在定义 autocmd 时扩展。示例
:au BufNewFile,BufRead *.html so <sfile>:h/html.vim
这里 Vim 将 <sfile> 扩展为包含此行的文件的名称。
:autocmd 会将命令添加到自动命令列表中,无论它们是否已经存在。当您的 .vimrc 文件被源两次时,自动命令将出现两次。为了避免这种情况,请在组中定义您的自动命令,这样您就可以轻松地清除它们
augroup vimrc
  " Remove all vimrc autocommands
  autocmd!
  au BufNewFile,BufRead *.html so <sfile>:h/html.vim
augroup END
如果您不想删除所有自动命令,可以改用一个变量来确保 Vim 只包含一次自动命令
:if !exists("autocommands_loaded")
:  let autocommands_loaded = 1
:  au ...
:endif
当未给出 [group] 参数时,Vim 使用当前组(由“:augroup”定义);否则,Vim 使用 [group] 定义的组。请注意,[group] 必须先定义。您不能使用“:au group …”定义新组;为此使用“:augroup”。
在测试自动命令时,您可能会发现 'verbose' 选项很有用
:set verbose=9
此设置会让 Vim 在执行自动命令时回显它们。
在脚本中定义自动命令时,它将能够调用脚本中局部的函数并使用脚本中局部的映射。当触发事件并执行命令时,它将在定义它的脚本的上下文中运行。如果在命令中使用 <SID>,这一点很重要。
在执行命令时,来自一个命令的消息会覆盖之前的消息。这与手动执行命令不同。屏幕通常不会向上滚动,因此不会出现回车提示。当一个命令输出两条消息时,这可能会发生。

3. 删除自动命令 autocmd! autocmd-remove

:au[tocmd]! [group] {event} {aupat} [++once] [++nested] {cmd} 删除与 {event}{aupat} 关联的所有自动命令,并添加命令 {cmd}。有关 [++once],请参见 autocmd-once。有关 [++nested],请参见 autocmd-nested
:au[tocmd]! [group] {event} {aupat} 删除与 {event}{aupat} 关联的所有自动命令。
:au[tocmd]! [group] * {aupat} 删除与 {aupat} 关联的所有自动命令,适用于所有事件。
:au[tocmd]! [group] {event} 删除 {event} 的所有自动命令。警告:如果没有 BufRead 等常用事件的组,您不应该这样做,它会破坏插件、语法高亮等。
:au[tocmd]! [group] 删除所有自动命令。注意:引号将被视为 :autocmd 的参数,不会开始注释。警告:通常情况下,如果没有组,您不应该这样做,它会破坏插件、语法高亮等。
当未给出 [group] 参数时,Vim 使用当前组(由“:augroup”定义);否则,Vim 使用 [group] 定义的组。

4. 列出自动命令 autocmd-list

:au[tocmd] [group] {event} {aupat} 显示与 {event}{aupat} 关联的自动命令。
:au[tocmd] [group] * {aupat} 显示与 {aupat} 关联的所有自动命令,适用于所有事件。
:au[tocmd] [group] {event} 显示 {event} 的所有自动命令。
:au[tocmd] [group] 显示所有自动命令。
如果您提供 [group] 参数,Vim 只会列出 [group] 的自动命令;否则,Vim 会列出所有组的自动命令。请注意,此参数行为与定义和删除自动命令的行为不同。
要列出缓冲区局部自动命令,请使用 <buffer> 或 <buffer=N> 形式的模式。请参见 autocmd-buflocal
:autocmd-verbose
'verbose' 非零时,列出自动命令也会显示其最后定义的位置。示例
:verbose autocmd BufEnter
FileExplorer  BufEnter
    *          call s:LocalBrowse(expand("<amatch>"))
        Last set from /usr/share/vim/vim-7.0/plugin/NetrwPlugin.vim
有关详细信息,请参见 :verbose-cmd
您可以指定一个以逗号分隔的事件名称列表。此列表中不能使用空格。该命令适用于列表中的所有事件。
对于读取文件,可以有四种事件: BufNewFile 开始编辑不存在的文件 BufReadPre BufReadPost 开始编辑现有文件 FilterReadPre FilterReadPost 读取带有过滤器输出的临时文件 FileReadPre FileReadPost 任何其他文件读取 Vim 在读取文件时只使用这四种类型中的一种。“Pre”和“Post”事件都会触发,分别在读取文件之前和之后触发。
请注意,"*ReadPre" 事件的自动命令以及所有 Filter 事件不允许更改当前缓冲区(如果发生这种情况,您将收到错误消息)。这是为了防止将文件读入错误的缓冲区。
请注意,'modified' 标志在执行 BufReadPost 和 BufNewFile 自动命令之后被重置。但是,当 'modified' 选项由自动命令设置时,不会发生这种情况。
您可以使用 'eventignore' 选项忽略一些事件或所有事件。
events {event} Nvim 识别以下事件。名称不区分大小写。
BufAdd
BufAdd 在将新的缓冲区或现有的未列出缓冲区添加到缓冲区列表(启动期间除外,请参见 VimEnter)或重命名已列出的缓冲区后。在 BufEnter 之前。注意:当前缓冲区“%”不是目标缓冲区“<afile>”、“<abuf>”。<buffer=abuf> BufDelete
BufDelete 在从缓冲区列表中删除缓冲区之前。如果缓冲区已加载,则 BufUnload 可能首先被调用。也用于在缓冲区列表中的缓冲区被重命名之前。注意:当前缓冲区“%”不是目标缓冲区“<afile>”、“<abuf>”。<buffer=abuf> 不要更改到另一个缓冲区。 BufEnter
BufEnter 进入(访问、切换到)新的或现有的缓冲区后。用于设置文件类型选项。与 BufNew 相比,后者不会对现有缓冲区触发。在 BufAdd 之后。在 BufReadPost 之后。 BufFilePost
BufFilePost 使用“:file”或“:saveas”命令更改当前缓冲区名称后。 BufFilePre
BufFilePre 使用“:file”或“:saveas”命令更改当前缓冲区名称之前。 BufHidden
BufHidden 在缓冲区变为隐藏之前:当不再有显示缓冲区的窗口时,但缓冲区未卸载或删除。
不适用于退出 Vim 时使用“:qa”或“:q”。注意:当前缓冲区“%”不是目标缓冲区“<afile>”、“<abuf>”。<buffer=abuf> BufLeave
BufLeave 在离开到另一个缓冲区之前。当离开或关闭当前窗口并且新的当前窗口不属于同一个缓冲区时也是如此。
不适用于退出 Vim 时使用“:qa”或“:q”。 BufModifiedSet
BufModifiedSet 在缓冲区的 'modified' 值发生更改后。 BufNew
BufNew 在创建新的缓冲区(启动期间除外,请参见 VimEnter)或重命名现有缓冲区后。与 BufEnter 不同,访问(切换到)现有缓冲区不会再次触发此事件。注意:当前缓冲区“%”不是目标缓冲区“<afile>”、“<abuf>”。<buffer=abuf> 另请参见 BufAddBufNewFileBufNewFile
BufNewFile 当开始编辑不存在的文件时。可用于读入骨架文件。 BufRead BufReadPost BufRead 或 BufReadPost 当开始编辑新的缓冲区时,在将文件读入缓冲区后,在处理 modelines 之前。请参见 BufWinEnter,以在处理 modelines 后执行操作。在以下情况下也会触发
以使缓冲区获得名称的方式写入未命名的缓冲区时
成功恢复文件后
对于在执行“:filetype detect”时使用“filetypedetect”组时,不会触发
对于 :read file 命令
当文件不存在时 BufReadCmd
BufReadCmd 在开始编辑新的缓冲区之前。应将文件读入缓冲区。 Cmd-event BufReadPre E200 E201 BufReadPre 在开始编辑新的缓冲区时,在将文件读入缓冲区之前。如果文件不存在,则不使用。 BufUnload
BufUnload 在卸载缓冲区之前,当缓冲区中的文本将被释放时。在 BufWritePost 之后。在 BufDelete 之前。当 Vim 即将退出时,会为所有已加载的缓冲区触发。 注意:当前缓冲区 "%" 不是目标缓冲区 "<afile>","<abuf>"。 <buffer=abuf> 不要切换缓冲区或窗口!在退出时不会触发,v:dying 为 2 或更大。 BufWinEnter
BufWinEnter 缓冲区在窗口中显示后。这可能是缓冲区加载时(处理模型行后)或隐藏缓冲区显示时(不再隐藏)发生的。
对于没有参数的 :split 不会触发,因为缓冲区没有改变,或者使用已在窗口中打开的文件的 :split。对于使用当前缓冲区名称的 ":split" 触发,因为它会重新加载该缓冲区。 BufWinLeave
BufWinLeave 在缓冲区从窗口中删除之前。当它仍然在另一个窗口中可见时不会发生。在退出时也会触发。在 BufUnload、BufHidden 之前。 注意:当前缓冲区 "%" 不是目标缓冲区 "<afile>","<abuf>"。 <buffer=abuf> 在退出时不会触发,v:dying 为 2 或更大。 BufWipeout
BufWipeout 在完全删除缓冲区之前。BufUnload 和 BufDelete 事件可能会首先被调用(如果缓冲区已加载并在缓冲区列表中)。在缓冲区重命名之前也会使用(即使它不在缓冲区列表中)。 注意:当前缓冲区 "%" 不是目标缓冲区 "<afile>","<abuf>"。 <buffer=abuf> 不要切换到另一个缓冲区。 BufWrite BufWritePre BufWrite 或 BufWritePre 在将整个缓冲区写入文件之前。 BufWriteCmd
BufWriteCmd 在将整个缓冲区写入文件之前。应完成文件的写入并重置 'modified'(如果成功),除非 'cpo' 中有 '+' 并且写入另一个文件 cpo-+。缓冲区内容不应该改变。当命令重置 'modified' 时,撤消信息将被调整为将旧的撤消状态标记为 'modified',就像 :write 一样。 Cmd-event BufWritePost
BufWritePost 在将整个缓冲区写入文件之后(应撤消 BufWritePre 的命令)。 ChanInfo
ChanInfo 通道状态改变,例如 RPC 通道的客户端描述了自己。设置这些 v:event 键:info 有关 info 字典的格式,请参见 nvim_get_chan_info()ChanOpen
ChanOpen 在通道打开后立即发生。设置这些 v:event 键:info 有关 info 字典的格式,请参见 nvim_get_chan_info()CmdUndefined
CmdUndefined 当使用用户命令但未定义时。对仅在使用时才定义的命令很有用。该模式与命令名称匹配。<amatch><afile> 都扩展到命令名称。 注意:在定义命令之前,自动完成将无法正常工作。另一种方法是始终定义用户命令,并让它调用自动加载的函数。参见 autoloadCmdlineChanged
CmdlineChanged 在命令行内的文本发生改变之后。注意不要弄乱命令行,否则可能会导致 Vim 无法正常工作。<afile> 扩展到 cmdline-charCmdlineEnter
CmdlineEnter 在进入命令行后(包括在映射中非交互式地使用 ":":使用 <Cmd> 避免这种情况)。该模式与 cmdline-char 匹配。<afile> 扩展到 cmdline-char。设置这些 v:event 键:cmdlevel cmdtype CmdlineLeave
CmdlineLeave 在离开命令行之前(包括在映射中非交互式地使用 ":":使用 <Cmd> 避免这种情况)。<afile> 扩展到 cmdline-char。设置这些 v:event 键:abort(可变)cmdlevel cmdtype 注意:abort 只能从 false 更改为 true:无法通过将其更改为 false 来执行已中止的命令行。 CmdwinEnter
CmdwinEnter 在进入命令行窗口后。对专门为这种特殊类型的窗口设置选项很有用。<afile> 扩展为单个字符,表示命令行的类型。 cmdwin-char CmdwinLeave
CmdwinLeave 在离开命令行窗口之前。对使用 CmdwinEnter 完成的任何全局设置进行清理很有用。<afile> 扩展为单个字符,表示命令行的类型。 cmdwin-char ColorScheme
ColorScheme 在加载颜色方案后。 :colorscheme 如果未找到颜色方案,则不会触发。该模式与颜色方案名称匹配。<afile> 可用于实际设置此选项的文件的名称,<amatch> 可用于新颜色方案的名称。
ColorSchemePre
ColorSchemePre 在加载颜色方案之前。 :colorscheme 对在加载另一个颜色方案之前,设置删除由颜色方案添加的内容很有用。
CompleteChanged CompleteChanged
每次插入模式完成菜单改变后。在弹出菜单隐藏时不会触发,请使用 CompleteDonePreCompleteDone 来实现。
设置这些 v:event 键:completed_item 参见 complete-items。height 可见项目数 width 屏幕单元 row 最上面的屏幕行 col 最左边的屏幕列 size 项目总数 scrollbar 如果可见,则为 TRUE
非递归(事件不能自触发)。不能更改文本。 textlock
还可以通过调用 pum_getpos() 获取弹出窗口的大小和位置。
CompleteDonePre
CompleteDonePre 在插入模式完成之后。无论完成什么或放弃完成都会触发。 ins-completion complete_info() 可用,信息在触发 CompleteDonePre 后被清除。 v:completed_item 变量包含有关完成项目的信息。
CompleteDone
CompleteDone 在插入模式完成之后。无论完成什么或放弃完成都会触发。 ins-completion complete_info() 不可使用,信息在触发 CompleteDone 之前被清除。如果需要,请使用 CompleteDonePre。 v:completed_item 提供完成的项目。
设置这些 v:event 键:reason 完成的原因。可以是以下之一
"accept": 完成已使用 complete_CTRL-Y 接受。
"cancel": 完成已使用 complete_CTRL-E、按下非关键字字符或触发新的完成而取消。
CursorHold
CursorHold 当用户在用 'updatetime' 指定的时间内未按下任何键时。在用户按下键之前不会触发(即,如果您离开 Vim 去喝咖啡,则不会每隔 'updatetime' 毫秒触发一次)。有关预览标签的示例,请参见 CursorHold-example。此事件仅在普通模式下触发。它在等待命令参数输入或操作符后的移动时不会触发。在录制时,不会触发 CursorHold 事件。 q <CursorHold>
在内部,自动命令由 <CursorHold> 键触发。在表达式映射中,getchar() 可能会看到此字符。
注意:交互式命令不能用于此事件。没有命中回车提示,屏幕将直接更新(如果需要)。 注意:将来可能会有另一个选项来设置时间。提示:要强制更新状态行,请使用
:let &ro = &ro
CursorHoldI
CursorHoldI 与 CursorHold 相似,但在插入模式下。在等待另一个键时不会触发,例如在 CTRL-V 之后,并且不会在 CTRL-X 模式 insert_expand 下触发。
CursorMoved
CursorMoved 在光标在普通模式或可视模式下移动或移动到另一个窗口后。当光标所在行的文本发生改变时也会触发,例如使用 "x"、"rx" 或 "p"。在存在预输入、在脚本文件中执行命令或操作符处于挂起状态时,不总是触发。有关示例,请参见 match-parens 注意:不能使用 :noautocmd 跳过。小心:这会非常频繁地触发,不要做任何用户不期待或速度很慢的事情。 CursorMovedC
CursorMovedC 在光标在命令行中移动后。注意不要弄乱命令行,否则可能会导致 Vim 无法正常工作。<afile> 扩展到 cmdline-charCursorMovedI
CursorMovedI 在光标在插入模式下移动后。在弹出菜单可见时不会触发。否则与 CursorMoved 相同。 DiffUpdated
DiffUpdated 在差异更新后。根据正在使用的差异类型(内部或外部),这可能在每次更改时触发,或者在执行 :diffupdate 时触发。 DirChanged
DirChanged 在 current-directory 改变后。模式可以是:"window" 在 :lcd 时触发 "tabpage" 在 :tcd 时触发 "global" 在 :cd 时触发 "auto" 在 'autochdir' 时触发。设置这些 v:event 键:cwd: 当前工作目录 scope: "global"、"tabpage"、"window" changed_window: 如果我们触发了切换窗口(或标签)的事件,则为 v:true <afile> 设置为新目录名称。非递归(事件不能自触发)。 DirChangedPre
DirChangedPre 当 当前目录 将要发生更改时,例如使用 DirChanged。模式与 DirChanged 相同。设置以下 v:event 键:directory: 新的工作目录 scope: "global", "tabpage", "window" changed_window: 如果我们触发了切换窗口(或标签页)的事件,则为 v:true <afile> 设置为新的目录名称。非递归(事件不能自行触发)。 ExitPre
ExitPre 使用 :quit:wq 以使 Vim 退出,或使用 :qall,紧接在 QuitPre 之后。可用于关闭任何不必要的窗口。如果存在未自动保存的已修改缓冲区,退出仍可能被取消,请使用 VimLeavePre 来真正退出。另请参阅 QuitPreWinClosedFileAppendCmd
FileAppendCmd 在追加到文件之前。应执行对文件的追加操作。使用 '[' 和 ']' 标记来表示行范围。 Cmd-event FileAppendPost
FileAppendPost 在追加到文件之后。 FileAppendPre
FileAppendPre 在追加到文件之前。使用 '[' 和 ']' 标记来表示行范围。 FileChangedRO
FileChangedRO 在对只读文件进行首次修改之前。可用于从源代码管理系统中签出文件。在更改由自动命令引起时不会触发。在缓冲区中进行首次更改或在 'readonly' 被设置后进行首次更改时触发,在应用更改到文本之前。 警告: 如果自动命令移动了光标,则更改的效果将是未定义的。 E788
无法切换缓冲区。您可以重新加载缓冲区,但不能编辑另一个缓冲区。 E881
如果行数发生变化,则保存撤消可能失败,并且更改将被中止。 FileChangedShell
FileChangedShell 当 Vim 发现文件自开始编辑以来的修改时间已更改时。当文件的属性发生变化或文件的大小发生变化时,也会触发。 timestamp 为每个更改的文件触发,在
执行 shell 命令之后
'autoread' 被设置并且缓冲区未被更改时不会使用。如果存在 FileChangedShell 自动命令,则不会显示警告消息和提示。 v:fcs_reason 指示发生了什么。设置 v:fcs_choice 来控制接下来会发生什么。 注意: 当前缓冲区 "%" 不是目标缓冲区 "<afile>" 和 "<abuf>"。 <buffer=abuf> E246 E811 无法切换、跳转或删除缓冲区。非递归(事件不能自行触发)。 FileChangedShellPost
FileChangedShellPost 在处理在 Vim 之外更改的文件后。可用于更新状态行。 FileReadCmd
FileReadCmd 在使用 ":read" 命令读取文件之前。应执行对文件的读取操作。 Cmd-event FileReadPost
FileReadPost 在使用 ":read" 命令读取文件之后。请注意,Vim 将 '[' 和 ']' 标记设置为读取的第一行和最后一行。这可用于对刚读取的行进行操作。 FileReadPre
FileReadPre 在使用 ":read" 命令读取文件之前。 FileType
FileType 当 'filetype' 选项被设置时。模式与文件类型匹配。<afile> 是设置此选项的文件的名称。<amatch>'filetype' 的新值。无法切换窗口或缓冲区。请参阅 filetypesFileWriteCmd
FileWriteCmd 在写入文件之前,不写入整个缓冲区时。应执行对文件的写入操作。不应更改缓冲区。使用 '[' 和 ']' 标记来表示行范围。 Cmd-event FileWritePost
FileWritePost 在写入文件之后,不写入整个缓冲区时。 FileWritePre
FileWritePre 在写入文件之前,不写入整个缓冲区时。使用 '[' 和 ']' 标记来表示行范围。 FilterReadPost
FilterReadPost 从过滤器命令读取文件之后。Vim 会像 FilterReadPre 一样检查模式与当前缓冲区的名称是否匹配。当 'shelltemp' 关闭时不会触发。 FilterReadPre E135 FilterReadPre 从过滤器命令读取文件之前。Vim 会检查模式与当前缓冲区的名称是否匹配,而不是过滤器命令输出的临时文件的名称。当 'shelltemp' 关闭时不会触发。 FilterWritePost
FilterWritePost 在为过滤器命令写入文件或使用外部 diff 进行差异化时(请参阅 DiffUpdated 以了解内部 diff)。Vim 会像 FilterWritePre 一样检查模式与当前缓冲区的名称是否匹配。当 'shelltemp' 关闭时不会触发。 FilterWritePre
FilterWritePre 在为过滤器命令写入文件或使用外部 diff 进行差异化之前。Vim 会检查模式与当前缓冲区的名称是否匹配,而不是过滤器命令输出的临时文件的名称。当 'shelltemp' 关闭时不会触发。 FocusGained
FocusGained Nvim 获得焦点。 FocusLost
FocusLost Nvim 失去焦点。当 GUI 对话框弹出时也会(可能)触发。 FuncUndefined
FuncUndefined 当使用用户函数但该函数未定义时。可用于仅在使用时定义函数。模式与函数名称匹配。<amatch><afile> 都设置为函数的名称。 注意: 在编写 Vim 脚本时,更好的方法是使用自动加载函数。请参阅 autoload-functionsUIEnter
UIEnter 在 UI 通过 nvim_ui_attach() 连接后,或在内置 TUI 启动后,在 VimEnter 之后。设置以下 v:event 键:chan: channel-id of the UI UILeave
UILeave 在 UI 与 Nvim 断开连接后,或在内置 TUI 停止后,在 VimLeave 之后。设置以下 v:event 键:chan: channel-id of the UI InsertChange
InsertChange 在插入或替换模式下键入 <Insert> 时。v:insertmode 变量指示新模式。请小心,不要移动光标或执行用户不期望的任何其他操作。 InsertCharPre
InsertCharPre 在插入模式下键入字符时,在插入字符之前。v:char 变量指示键入的字符,可以在事件期间更改以插入不同的字符。当 v:char 设置为多个字符时,此文本将按字面意义插入。
无法更改文本。 textlock InsertEnter
InsertEnter 在开始插入模式之前。也适用于替换模式和虚拟替换模式。v:insertmode 变量指示模式。请小心,不要执行用户不期望的任何其他操作。光标将在之后恢复。如果您不希望这样,请将 v:char 设置为非空字符串。 InsertLeavePre
InsertLeavePre 在离开插入模式之前。在使用 CTRL-O i_CTRL-O 时也会触发。请小心,不要更改模式或使用 :normal,这很可能会导致问题。 InsertLeave
InsertLeave 在离开插入模式之后。在使用 CTRL-O i_CTRL-O 时也会触发。但不适用于 i_CTRL-CMenuPopup
MenuPopup 在显示弹出菜单之前(在鼠标右键下)。可用于根据光标或鼠标指针下的内容调整菜单。模式与表示模式的一个或两个字符匹配:n 普通 v 可视 o 运算符等待 i 插入 c 命令行 tl 终端 ModeChanged
ModeChanged 更改模式之后。模式与 'old_mode:new_mode' 匹配,例如与 *:c 匹配以模拟 CmdlineEnter。将设置以下 v:event 值:old_mode 更改之前的模式。new_mode 新模式,与使用非零参数调用 mode() 时返回的值相同。当 ModeChanged 被触发时,old_mode 将具有事件上次触发时 new_mode 的值。这将在每次微模式更改时被触发。使用示例:在进入可视模式时使用相对行号
:au ModeChanged [vV\x16]*:* let &l:rnu = mode() =~# '^[vV\x16]'
:au ModeChanged *:[vV\x16]* let &l:rnu = mode() =~# '^[vV\x16]'
:au WinEnter,WinLeave * let &l:rnu = mode() =~# '^[vV\x16]'
OptionSet
OptionSet 在设置选项之后(除了在 启动 期间)。autocmd-pattern 与长选项名称匹配。 <amatch> 指示已设置哪个选项。
v:option_type 指示是全局范围还是局部范围。 v:option_command 指示使用了哪种类型的 set/let 命令(请遵循标签以查看表格)。 v:option_new 指示新设置的值。 v:option_oldlocal 具有旧的局部值。 v:option_oldglobal 具有旧的全局值。 v:option_old 指示旧的选项值。
v:option_oldlocal 仅在使用 :set:setlocalmodeline 设置选项时被设置。类似地,v:option_oldglobal 仅在使用 :set:setglobal 时被设置。
这不会设置 <abuf>,您可以使用 bufnr()
请注意,使用 :set 设置 全局-局部 选项时,v:option_old 是旧的全局值。但是,对于所有不是全局-局部的选项,它都是旧的局部值。
使用示例:检查 'backupdir''undodir' 选项中目录是否存在,如果目录不存在,则创建该目录。
注意: 在此自动命令中不要重置相同的选项,这可能会破坏插件。您可以始终使用 :noautocmd 来阻止触发 OptionSet。
非递归:自动命令中的 :set 不会再次触发 OptionSet。
在启动时不会触发。
QuickFixCmdPre
QuickFixCmdPre 在执行快速修复命令(:make:lmake:grep:lgrep:grepadd:lgrepadd:vimgrep:lvimgrep:vimgrepadd:lvimgrepadd:cfile:cgetfile:caddfile:lfile:lgetfile:laddfile:helpgrep:lhelpgrep:cexpr:cgetexpr:caddexpr:cbuffer:cgetbuffer:caddbuffer)之前。模式与正在执行的命令匹配。当使用 :grep'grepprg' 设置为 "internal" 时,它仍然匹配 "grep"。此命令不能用于设置 'makeprg''grepprg' 变量。如果此命令导致错误,则不会执行快速修复命令。 QuickFixCmdPost
QuickFixCmdPost 与 QuickFixCmdPre 相似,但在执行快速修复命令后,跳转到第一个位置之前触发。对于 :cfile:lfile 命令,它在读取错误文件后,移动到第一个错误之前触发。参见 QuickFixCmdPost-exampleQuitPre
QuitPre 当使用 :quit:wq:qall 时,在决定是否关闭当前窗口或退出 Vim 之前触发。对于 :wq,缓冲区在触发 QuitPre 之前写入。可以用来在当前窗口是最后一个普通窗口时关闭任何非必要的窗口。另见 ExitPreWinClosedRemoteReply
RemoteReply 当从作为服务器运行的 Vim 收到回复 server2client() 时触发。模式与 {serverid} 匹配。<amatch> 等于发送回复的 {serverid}<afile> 是实际的回复字符串。请注意,即使定义了自动命令,也应该使用 remote_read() 读取回复以消耗它。 SearchWrapped
SearchWrapped 当使用 nN 进行搜索,并且搜索绕过文档回到开头/结尾时触发。 RecordingEnter
RecordingEnter 当宏开始录制时触发。模式是当前文件名,reg_recording() 是正在使用的当前寄存器。 RecordingLeave
RecordingLeave 当宏停止录制时触发。模式是当前文件名,reg_recording() 是已录制的寄存器。reg_recorded() 仅在此事件之后更新。设置这些 v:event 键:regcontents regname SafeState
SafeState 当没有任何操作挂起时触发,进入等待用户输入字符的状态。当以下情况发生时,不会触发此事件:
操作符正在挂起
使用 "r" 输入寄存器
正在执行命令的中间阶段
正在执行映射
有预输入
插入模式完成处于活动状态
命令行完成处于活动状态 可以使用 mode() 找出 Vim 处于何种状态。状态可能为:
可视模式
普通模式
插入模式
命令行模式 根据你的需求,你可以使用 state() 检查更多信息,例如屏幕是否滚动以显示消息。
SessionLoadPost
SessionLoadPost 加载使用 :mksession 命令创建的会话文件后触发。 SessionWritePost
SessionWritePost 使用 :mksession 命令写入会话文件后触发。 ShellCmdPost
ShellCmdPost 使用 :!cmd:make:grep 执行 shell 命令后触发。可以用来检查是否有任何文件被修改。对于非阻塞 shell 命令,参见 job-controlSignal
Signal Nvim 接收信号后触发。模式与信号名称匹配。仅支持 "SIGUSR1" 和 "SIGWINCH"。示例
autocmd Signal SIGUSR1 call some#func()
ShellFilterPost
ShellFilterPost 使用 ":{range}!cmd"、":w !cmd" 或 ":r !cmd" 执行 shell 命令后触发。可以用来检查是否有任何文件被修改。 SourcePre
SourcePre 在加载 Vimscript/Lua 文件之前触发。 :source <afile> 是正在加载的文件的名称。 SourcePost
SourcePost 在加载 Vimscript/Lua 文件之后触发。 :source <afile> 是正在加载的文件的名称。在加载被中断时不会触发。在 SourceCmd 自动命令触发之后也会触发。 SourceCmd
SourceCmd 当加载 Vimscript/Lua 文件时触发。 :source <afile> 是正在加载的文件的名称。自动命令必须加载该文件。 Cmd-event SpellFileMissing
SpellFileMissing 当尝试加载拼写检查文件,但找不到时触发。模式与语言匹配。<amatch> 是语言,'encoding' 也起作用。参见 spell-SpellFileMissingStdinReadPost
StdinReadPost 在启动时,从 stdin 读取到缓冲区后,在执行 modelines 之前触发。 -- StdinReadPre
StdinReadPre 在启动时,从 stdin 读取到缓冲区之前触发。 -- SwapExists
SwapExists 当开始编辑文件时,检测到存在交换文件。仅在可以选择处理这种情况的方式时触发,此时 Vim 会询问用户下一步操作。v:swapname 变量包含找到的交换文件的名称,<afile> 是正在编辑的文件。v:swapcommand 可能包含在打开的文件中执行的命令。这些命令应该将 v:swapchoice 变量设置为包含一个字符的字符串,以告诉 Vim 下一步应该做什么:'o' 以只读方式打开 'e' 无论如何编辑文件 'r' 恢复 'd' 删除交换文件 'q' 退出,不编辑文件 'a' 取消,类似于按 CTRL-C 当设置为空字符串时,用户将被询问,就像没有 SwapExists 自动命令一样。 E812
无法切换到另一个缓冲区,更改缓冲区名称或更改目录。 Syntax
Syntax 当 'syntax' 选项被设置时触发。模式与语法名称匹配。<afile> 展开为设置此选项的文件的名称。<amatch> 展开为 'syntax' 的新值。参见 :syn-onTabEnter
TabEnter 进入标签页后立即触发。 tab-page 在 WinEnter 之后触发。在 BufEnter 之前触发。 TabLeave
TabLeave 离开标签页之前立即触发。 tab-page 在 WinLeave 之后触发。 TabNew
TabNew 创建新的标签页时触发。 tab-page 在 WinEnter 之后触发。在 TabEnter 之前触发。 TabNewEntered
TabNewEntered 进入新的标签页后触发。 tab-page 在 BufEnter 之后触发。 TabClosed
TabClosed 关闭标签页后触发。<afile> 展开为标签页编号。 TermOpen
TermOpen 当 terminal 任务开始时触发。可以用来配置终端缓冲区。 TermEnter
TermEnter 进入 Terminal-mode 后触发。在 TermOpen 之后触发。 TermLeave
TermLeave 离开 Terminal-mode 后触发。在 TermClose 之后触发。 TermClose
TermClose 当 terminal 任务结束时触发。设置这些 v:event 键:status TermRequest
TermRequest 当 :terminal 子进程发出 OSC 或 DCS 序列时触发。设置 v:termrequestevent-data 是请求字符串。 TermResponse
TermResponse 当 Nvim 从主机终端接收 OSC 或 DCS 响应时触发。设置 v:termresponseevent-data 是响应字符串。可能在其他事件(文件 I/O、shell 命令或任何其他需要时间的操作)期间触发。示例
-- Query the terminal palette for the RGB value of color 1
-- (red) using OSC 4
vim.api.nvim_create_autocmd('TermResponse', {
  once = true,
  callback = function(args)
    local resp = args.data
    local r, g, b = resp:match("\027%]4;1;rgb:(%w+)/(%w+)/(%w+)")
  end,
})
io.stdout:write("\027]4;1;?\027\\")
TextChanged
TextChanged 在普通模式下对当前缓冲区中的文本进行更改后触发。也就是说,在 b:changedtick 发生变化后触发(即使在定义 TextChanged 自动命令之前发生了变化)。当有预输入或操作符挂起时,不会触发此事件。 注意: 无法使用 :noautocmd 跳过此事件。小心:此事件非常频繁地触发,不要执行任何用户没有预期或速度很慢的操作。 TextChangedI
TextChangedI 在插入模式下对当前缓冲区中的文本进行更改后触发。当弹出菜单可见时,不会触发此事件。否则与 TextChanged 相同。 TextChangedP
TextChangedP 在插入模式下对当前缓冲区中的文本进行更改后触发,但仅当弹出菜单可见时。否则与 TextChanged 相同。 TextChangedT
TextChangedT 在 Terminal-mode 中对当前缓冲区中的文本进行更改后触发。否则与 TextChanged 相同。 TextYankPost
TextYankPost 刚执行 yankdeleting 命令后触发,但如果使用了黑洞寄存器 quote_ 或对 setreg() 使用,则不会触发。模式必须为 "*". 设置这些 v:event 键:inclusive operator regcontents regname regtype visual inclusive 标志与 '['] 标记一起使用,可以用来计算操作的精确区域。
非递归(事件不能触发自身)。无法更改文本。 textlock User
User 不会自动执行。使用 :doautocmd 触发此事件,通常用于插件中的“自定义事件”。示例
:autocmd User MyPlugin echom 'got MyPlugin event'
:doautocmd User MyPlugin
UserGettingBored
UserGettingBored 当用户连续按下同一个键 42 次时触发。开玩笑! :-) VimEnter
VimEnter 在完成所有启动操作,包括加载 vimrc 文件、执行 "-c cmd" 参数、创建所有窗口并在其中加载缓冲区之后触发。在触发此事件之前,v:vim_did_enter 变量被设置,这样您就可以执行
if v:vim_did_enter
  call s:init()
else
  au VimEnter * call s:init()
endif
VimLeave
VimLeave 在退出 Vim 之前,就在写入 .shada 文件之后执行。仅执行一次,类似于 VimLeavePre。使用 v:dying 检测异常退出。使用 v:exiting 获取退出代码。如果 v:dying 大于或等于 2,则不会触发。 VimLeavePre
VimLeavePre 在退出 Vim 之前,就在写入 .shada 文件之前执行。这仅在退出时与当前缓冲区的名称匹配的情况下执行一次。在使用 "*" 模式时非常有用。
:autocmd VimLeavePre * call CleanupStuff()
使用 v:dying 检测异常退出。使用 v:exiting 获取退出代码。如果 v:dying 大于或等于 2,则不会触发。 VimResized
VimResized Vim 窗口调整大小后触发,因此 'lines' 和/或 'columns' 发生了更改。但在启动时不会触发。 VimResume
VimResume Nvim 从 暂停 状态恢复后触发。 VimSuspend
VimSuspend Nvim 进入 暂停 状态之前触发。 WinClosed
WinClosed 关闭窗口时,在将其从窗口布局中移除之前触发。模式与 窗口 ID 匹配。<amatch><afile> 都被设置为 窗口 ID。在 WinLeave 之后触发。非递归(事件不能自触发)。另请参见 ExitPreQuitPreWinEnter
WinEnter 进入另一个窗口后触发。在 Vim 刚刚启动时,不会为第一个窗口执行此操作。对于设置窗口高度很有用。如果窗口用于另一个缓冲区,Vim 会在 WinEnter 自动命令之后执行 BufEnter 自动命令。 注意:对于 split 和 tabpage 命令,WinEnter 事件将在 split 或 tab 命令之后但在加载文件之前触发。
WinLeave
WinLeave 离开窗口之前触发。如果要进入的下一个窗口用于不同的缓冲区,Vim 会在 WinLeave 自动命令之前执行 BufLeave 自动命令(但不会为 ":new" 执行)。不会为 ":qa" 或 ":q" 在退出 Vim 时使用。在 WinClosed 之前触发。 WinNew
WinNew 创建新窗口时触发。在 Vim 刚刚启动时,不会为第一个窗口执行此操作。在 WinEnter 之前触发。
WinScrolled
WinScrolled 当前选项卡页中的任何窗口滚动文本(水平或垂直)或更改宽度或高度后触发。参见 win-scrolled-resized
模式与第一个滚动或调整大小的窗口的 窗口 ID 匹配。<amatch><afile> 都被设置为 窗口 ID
v:event 被设置为有关大小和滚动更改的信息。 WinScrolled-event
仅在启动完成并完成第一次屏幕重绘后开始触发。在定义第一个 WinScrolled 或 WinResized 事件时不会触发,但在添加更多事件时可能会触发。
非递归:在为 WinScrolled 事件执行命令时,该事件不会触发。但是,如果命令导致窗口滚动或更改大小,则稍后会触发另一个 WinScrolled 事件。
WinResized
WinResized 当前选项卡页中的窗口更改宽度或高度后触发。参见 win-scrolled-resized
v:event 被设置为有关大小更改的信息。 WinResized-event
WinScrolled 相同的行为,用于模式、触发和递归性。
{aupat}:autocmd 的参数,可以是逗号分隔的列表。这就像使用每个模式单独执行命令一样。因此,此命令
:autocmd BufRead *.txt,*.info set et
等效于
:autocmd BufRead *.txt set et
:autocmd BufRead *.info set et
文件模式 {aupat} 以两种方式之一针对文件名进行匹配测试:1. 当模式中没有 '/' 时,Vim 只检查与文件名尾部(不包括其前导目录路径)的匹配情况。2. 当模式中存在 '/' 时,Vim 检查与短文件名(如您输入的)和完整文件名(在将其扩展为完整路径并解析符号链接后)的匹配情况。
特殊模式 <buffer> 或 <buffer=N> 用于缓冲区局部自动命令 autocmd-buflocal。此模式不与缓冲区的名称匹配。
示例
:autocmd BufRead *.txt                set et
为所有文本文件设置 'et' 选项。
:autocmd BufRead /vim/src/*.c        set cindent
为 /vim/src 目录中的 C 文件设置 'cindent' 选项。
:autocmd BufRead /tmp/*.c        set ts=5
如果您从 "/tmp/test.c" 到 "/home/nobody/vim/src/test.c" 存在链接,并且您开始编辑 "/tmp/test.c",则此自动命令将匹配。
注意:要匹配路径的一部分,但不包括根目录,请在第一个字符中使用 "*"。例如
:autocmd BufRead */doc/*.txt        set tw=78
此自动命令将例如为 "/tmp/doc/xx.txt" 和 "/usr/home/piet/doc/yy.txt" 执行。目录数量在这里并不重要。
用于匹配模式的文件名是在扩展通配符之后生成的。因此,如果您发出此命令
:e $ROOTDIR/main.$EXT
该参数首先扩展为
/usr/root/main.py
然后将其与自动命令的模式匹配。在使用诸如 FileReadCmd 之类的事件时要小心,<amatch> 的值可能并非您期望的值。
环境变量可以在模式中使用
:autocmd BufRead $VIMRUNTIME/doc/*.txt  set expandtab
并且 ~ 可以用于主目录(如果定义了 $HOME)
:autocmd BufWritePost ~/.config/nvim/init.vim   so <afile>
:autocmd BufRead ~archive/*      set readonly
环境变量在定义自动命令时进行扩展,而不是在执行自动命令时进行扩展。这与命令不同!
文件模式
模式的解释与文件名中常用的解释类似:* 匹配任何字符序列;不寻常:包括路径分隔符 ? 匹配任何单个字符 \? 匹配 '?' . 匹配 '.' ~ 匹配 '~' , 分隔模式 \, 匹配 ',' { } 类似于 模式 中的 \( \) ,在 { } 内:类似于 模式 中的 \| ,\} 字面 {} \{ 字面 { \\\{n,m\} 类似于 模式 中的 \{n,m} \ 特殊含义类似于 模式 中的 [ch] 匹配 'c' 或 'h' [^ch] 匹配除 'c' 和 'h' 之外的任何字符
请注意,对于所有系统,'/' 字符都用作路径分隔符(即使是 Windows)。之所以这样做是因为反斜杠在模式中难以使用,并且为了使自动命令在不同系统之间可移植。
可以使用 模式 项目,但它们可能无法按预期工作,因为对上述内容进行了转换。
autocmd-changes
在触发事件时,会进行与模式的匹配。在其中一个自动命令中更改缓冲区名称,甚至删除缓冲区,都不会改变要执行的自动命令。例如
au BufEnter *.foo  bdel
au BufEnter *.foo  set modified
这将删除当前缓冲区,然后在已成为当前缓冲区的缓冲区中设置 'modified'。Vim 不会考虑 "*.foo" 与该缓冲区名称不匹配。它将 "*.foo" 与事件触发时的缓冲区名称匹配。
但是,缓冲区局部自动命令不会为使用 :bwipe 清除的缓冲区执行。使用 :bdel 删除缓冲区后,缓冲区实际上仍然存在(它变得未列出),因此自动命令仍然执行。
缓冲区局部自动命令附加到特定缓冲区。如果缓冲区没有名称,并且名称与特定模式不匹配,它们很有用。但这同时也意味着它们必须显式添加到每个缓冲区。
缓冲区局部自动命令不使用模式,而是使用以下形式之一:<buffer> 当前缓冲区 <buffer=99> 缓冲区编号 99 <buffer=abuf> 使用 <abuf>(仅在执行自动命令时) <abuf>
示例
:au CursorHold <buffer>  echo 'hold'
:au CursorHold <buffer=33>  echo 'hold'
:au BufNewFile * au CursorHold <buffer=abuf>  echo 'hold'
所有用于自动命令的命令也适用于缓冲区局部自动命令,只需使用特殊字符串代替模式。示例
:au! * <buffer>                     " remove buffer-local autocommands for
                                 " current buffer
:au! * <buffer=33>                     " remove buffer-local autocommands for
                                 " buffer #33
:bufdo :au! CursorHold <buffer>  " remove autocmd for given event for all
                                 " buffers
:au * <buffer>                     " list buffer-local autocommands for
                                 " current buffer
请注意,当为当前缓冲区定义自动命令时,它将与缓冲区编号一起存储。因此,它使用形式 "<buffer=12>",其中 12 是当前缓冲区的编号。您在列出自动命令时会看到这一点,例如。
要测试缓冲区局部自动命令的存在,请使用 exists() 函数,如下所示
:if exists("#CursorHold#<buffer=12>") | ... | endif
:if exists("#CursorHold#<buffer>") | ... | endif    " for current buffer
当然,当缓冲区被清除时,它的缓冲区局部自动命令也会消失。请注意,当删除缓冲区时,例如使用 ":bdel",它只是未列出,自动命令仍然存在。为了查看缓冲区局部自动命令的删除
:set verbose=6
无法为不存在的缓冲区定义缓冲区局部自动命令。
自动命令可以放在一起作为一个组。这对于删除或执行一组自动命令很有用。例如,所有用于语法高亮的自动命令都放在 "highlight" 组中,以便在 GUI 启动时能够执行 ":doautoall highlight BufRead"。
当没有选择特定组时,Vim 会使用默认组。默认组没有名称。您不能单独执行默认组中的自动命令;您只能通过执行所有组的自动命令来执行它们。
通常,在自动执行自动命令时,Vim 会使用所有组的自动命令。组仅在使用 ":doautocmd" 或 ":doautoall" 执行自动命令时,或在定义或删除自动命令时才重要。
组名可以包含除空格之外的任何字符。组名 "end" 是保留的(在英文大写字母中也是如此)。
组名区分大小写。请注意,这与事件名称不同!
:aug :augroup :aug[roup] {name} 为以下 ":autocmd" 命令定义自动命令组名。名称 "end" 或 "END" 选择默认组。为了避免混淆,名称应该与现有的 {event} 名称不同,因为这很可能不会按预期工作。
:augroup-delete E367 W19 E936 :aug[roup]! {name} 删除自动命令组 {name}。如果仍然存在使用此组的自动命令,请不要使用此命令!如果您仍然这样做,您将收到警告。如果组是当前组,您将收到错误 E936。
要为特定组输入自动命令,请使用以下方法:1. 使用“:augroup {name}”选择组。2. 使用“:au!”删除所有旧的自动命令。3. 定义自动命令。4. 使用“augroup END”返回默认组。
示例
:augroup uncompress
:  au!
:  au BufEnter *.gz        %!gunzip
:augroup END
这样可以防止自动命令被定义两次(例如,在再次引用 vimrc 文件后)。
FileExplorer
Vim 识别一个名为 FileExplorer 的组。如果此组存在,Vim 假设可以编辑目录,并将触发一个插件来列出该目录中的文件。 netrw 插件使用此功能。这使您能够
browse edit

9. 执行自动命令 autocmd-execute

Vim 还可以非自动地执行自动命令。如果您更改了自动命令或 Vim 执行了错误的自动命令(例如,文件模式匹配错误),这将非常有用。
请注意,'eventignore' 选项在此处也适用。在此选项中列出的事件不会导致执行任何命令。
:do :doau :doaut :doautocmd E217 :do[autocmd] [<nomodeline>] [group] {event} [fname] 对当前缓冲区应用与 [fname](默认:当前文件名)匹配的 {event} 的自动命令。当当前文件名与正确模式不匹配、更改设置后或要为特定事件执行自动命令时,可以使用此命令。您也可以在自动命令内部使用此命令,以便将一个扩展名的自动命令建立在另一个扩展名之上。示例
:au BufEnter *.cpp so ~/.config/nvim/init_cpp.vim
:au BufEnter *.cpp doau BufEnter x.c
注意避免无休止的循环。 autocmd-nested
当没有给出 [group] 参数时,Vim 会执行所有组的自动命令。当包含 [group] 参数时,Vim 只会执行该组的匹配自动命令。未定义的组是错误。 <nomodeline>
应用自动命令后,会处理模型行,以便在编辑文件时,它们的设置会覆盖来自自动命令的设置。如果指定了 <nomodeline>,则会跳过此操作。您可能希望对加载缓冲区时未使用(例如,User)的事件使用 <nomodeline>。当没有执行匹配的自动命令时,也会跳过模型行。
:doautoa :doautoall :doautoa[ll] [<nomodeline>] [group] {event} [fname] 与“:doautocmd”类似,但将自动命令应用于每个已加载的缓冲区。当前缓冲区最后完成。
请注意,[fname] 用于选择自动命令,而不是应用它们的缓冲区。示例
augroup mine
  autocmd!
  autocmd FileType * echo expand('<amatch>')
augroup END
doautoall mine FileType Loaded-Buffer
引用此脚本后,您将看到与已加载缓冲区数量一样多的“Loaded-Buffer”回显。
小心:不要对删除缓冲区、更改为另一个缓冲区或更改缓冲区内容的自动命令使用此命令;结果不可预测。此命令适用于设置选项、更改突出显示和类似操作的自动命令。

10. 使用自动命令 autocmd-use

对于写入文件,有四组可能的事件。Vim 仅对写入命令使用其中一组
BufWriteCmd BufWritePre BufWritePost 写入整个缓冲区 FilterWritePre FilterWritePost 写入过滤器临时文件 FileAppendCmd FileAppendPre FileAppendPost 追加到文件 FileWriteCmd FileWritePre FileWritePost 任何其他文件写入
如果存在匹配的“*Cmd”自动命令,则假定它会执行写入操作。不再执行进一步的写入操作,并且不会触发其他事件。 Cmd-event
请注意,“*WritePost”命令应撤消“*WritePre”命令导致的缓冲区中的任何更改;否则,写入文件将具有更改缓冲区的副作用。
在执行自动命令之前,将要从中写入行的缓冲区暂时变为当前缓冲区。除非自动命令更改当前缓冲区或删除先前当前的缓冲区,否则将使先前当前的缓冲区再次成为当前缓冲区。
“*WritePre”和“*AppendPre”自动命令不能删除将要从中写入行的缓冲区。
“[ 和 ]”标记具有特殊位置
在“*ReadPre”事件之前,“[”标记将设置为将要插入新行的正上方。
在“*ReadPost”事件之前,“[”标记将设置为刚读入的第一行,“]”标记将设置为最后一行。
在执行“*WriteCmd”、“*WritePre”和“*AppendPre”自动命令之前,“[”标记将设置为将要写入的第一行,“]”标记将设置为最后一行。小心:“[ 和 ]”在使用更改缓冲区的命令时会发生变化。
在预期文件名的命令中,您可以使用“<afile>”表示正在读取的文件名 :<afile>(您也可以使用“%”表示当前文件名)。“<abuf>”可用于当前有效缓冲区的缓冲区编号。这也适用于没有名称的缓冲区。但这不适用于没有缓冲区的文件(例如,使用“:r file”)。
gzip 示例
读取和写入压缩文件的示例
:augroup gzip
:  autocmd!
:  autocmd BufReadPre,FileReadPre        *.gz set bin
:  autocmd BufReadPost,FileReadPost        *.gz '[,']!gunzip
:  autocmd BufReadPost,FileReadPost        *.gz set nobin
:  autocmd BufReadPost,FileReadPost        *.gz execute ":doautocmd BufReadPost " .. expand("%:r")
:  autocmd BufWritePost,FileWritePost        *.gz !mv <afile> <afile>:r
:  autocmd BufWritePost,FileWritePost        *.gz !gzip <afile>:r
:  autocmd FileAppendPre                *.gz !gunzip <afile>
:  autocmd FileAppendPre                *.gz !mv <afile>:r <afile>
:  autocmd FileAppendPost                *.gz !mv <afile> <afile>:r
:  autocmd FileAppendPost                *.gz !gzip <afile>:r
:augroup END
使用“gzip”组是为了能够使用“:autocmd!”删除任何现有的自动命令,以便在文件被引用两次时使用。
(“<afile>:r”是文件名,不包括扩展名,请参见 :_%:
针对 BufNewFile、BufRead/BufReadPost、BufWritePost、FileAppendPost 和 VimLeave 事件执行的命令不会设置或重置缓冲区的更改标志。当您使用 BufReadPost 自动命令解压缩缓冲区时,您仍然可以使用“:q”退出。当您在 BufWritePost 中使用“:undo”撤消 BufWritePre 命令所做的更改时,您仍然可以使用“:q”(这也使“ZZ”工作)。如果您希望将缓冲区标记为已修改,请设置 'modified' 选项。
要从自动命令执行普通模式命令,请使用“:normal”命令。谨慎使用!如果普通模式命令未完成,用户需要键入字符(例如,在“:normal m”之后,您需要键入一个标记名称)。
如果您希望缓冲区在更改后保持未修改状态,请重置 'modified' 选项。这使得可以使用“:q”而不是“:q!”退出缓冲区。
autocmd-nested E218 默认情况下,自动命令不会嵌套。例如,如果您在自动命令中使用“:e”或“:w”,Vim 不会执行这些命令的 BufRead 和 BufWrite 自动命令。如果您希望这样做,请在要嵌套的命令中使用“++nested”标志。例如
:autocmd FileChangedShell *.c ++nested e!
嵌套限制为 10 级,以避免递归循环。
可以在自动命令中使用“:au”命令。这可以是一个自我修改的命令!这对于只应执行一次的自动命令非常有用。
如果您想跳过一个命令的自动命令,请使用 :noautocmd 命令修饰符或 'eventignore' 选项。
注意:当读取文件(使用“:read file”或使用过滤器命令)并且文件中的最后一行没有 <EOL> 时,Vim 会记住这一点。在下次写入(使用“:write file”或使用过滤器命令)时,如果将同一行再次写入文件作为文件的最后一行,并且设置了 'binary',则 Vim 不会提供 <EOL>。这使得对刚读取行的过滤器命令写入与读取的相同文件,并且使得对刚过滤行的写入命令写入与从过滤器读取的相同文件。例如,另一种写入压缩文件的方法
:autocmd FileWritePre *.gz   set bin|'[,']!gzip
:autocmd FileWritePost *.gz  undo|set nobin
autocommand-pattern
您可以指定多个模式,用逗号隔开。以下是一些示例
:autocmd BufRead   *                set tw=79 nocin ic infercase fo=2croq
:autocmd BufRead   .letter        set tw=72 fo=2tcrq
:autocmd BufEnter  .letter        set dict=/usr/lib/dict/words
:autocmd BufLeave  .letter        set dict=
:autocmd BufRead,BufNewFile   *.c,*.h        set tw=0 cin noic
:autocmd BufEnter  *.c,*.h        abbr FOR for (i = 0; i < 3; ++i)<CR>{<CR>}<Esc>O
:autocmd BufLeave  *.c,*.h        unabbr FOR
对于 makefile(makefile、Makefile、imakefile、makefile.unix 等)
:autocmd BufEnter  ?akefile*        set include=^s\=include
:autocmd BufLeave  ?akefile*        set include&
始终在第一个函数处开始编辑 C 文件
:autocmd BufRead   *.c,*.h        1;/^{
如果没有上面的“1;”,搜索将从文件输入的位置开始,而不是从文件的开头开始。
skeleton template 在打开新文件时读取骨架(模板)文件
:autocmd BufNewFile  *.c        0r ~/vim/skeleton.c
:autocmd BufNewFile  *.h        0r ~/vim/skeleton.h
:autocmd BufNewFile  *.java        0r ~/vim/skeleton.java
在写入“*.html”文件时在其中插入当前日期和时间
:autocmd BufWritePre,FileWritePre *.html   ks|call LastMod()|'s
:fun LastMod()
:  if line("$") > 20
:    let l = 20
:  else
:    let l = line("$")
:  endif
:  exe "1," .. l .. "g/Last modified: /s/Last modified: .*/Last modified: " ..
:  \ strftime("%Y %b %d")
:endfun
您需要在文件的前 20 行中有一行“Last modified: <date time>”才能使此功能生效。Vim 会将 <date time>(以及同一行中的任何内容)替换为当前日期和时间。解释:ks 用标记“s”标记当前位置调用 LastMod() 调用 LastMod() 函数执行工作“s”将光标返回到旧位置 LastMod() 函数检查文件是否短于 20 行,然后使用“:g”命令查找包含“Last modified: ”的行。对于这些行,会执行“:s”命令以将现有日期替换为当前日期。使用“:execute”命令是为了能够对“:g”和“:s”命令使用表达式。使用 strftime() 函数获取日期。您可以更改其参数以获取另一个日期字符串。
在命令行中输入 :autocmd 时,可以在适当的情况下完成事件和命令名称(使用 <Tab>CTRL-D 等)。
Vim 会按您指定的顺序执行所有匹配的自动命令。建议您的第一个自动命令使用“*”作为文件模式来用于所有文件。这意味着您可以在这里定义您喜欢的任何设置的默认值,如果存在另一个匹配的自动命令,它将覆盖这些默认值。但是,如果没有其他匹配的自动命令,至少会恢复您的默认设置(如果从另一个执行自动命令匹配的文件输入此文件)。请注意,“*”也会匹配以“.”开头的文件,这与 Unix shell 不同。
autocmd-searchpat
自动命令不会更改当前搜索模式。Vim 在执行自动命令之前保存当前搜索模式,然后在自动命令完成后恢复它们。这意味着自动命令不会影响使用 'hlsearch' 选项突出显示的字符串。在自动命令中,您仍然可以正常使用搜索模式,例如,使用“n”命令。如果您希望自动命令设置搜索模式,以便在自动命令完成后使用它,请使用“:let @/ =”命令。不能在自动命令中使用“:nohlsearch”关闭搜索突出显示。使用 'shada' 选项中的“h”标志在启动 Vim 时禁用搜索突出显示。
Cmd-event
当使用其中一个“*Cmd”事件时,预期匹配的自动命令会执行文件读取、写入或引用。这在处理特殊类型的文件时可以使用,例如在远程系统上。小心:如果您错误地使用这些事件,可能会导致无法读取或写入匹配的文件!请确保正确测试您的自动命令。最好使用一个永远不会匹配正常文件名的模式,例如“ftp://*”。
在定义 BufReadCmd 时,Vim 很难恢复崩溃的编辑会话。从原始文件恢复时,Vim 只会读取在交换文件中找不到的文件部分。由于在 BufReadCmd 中不可能做到这一点,因此请使用 :preserve 命令确保恢复不需要原始文件。您可能只希望在预计修改文件时执行此操作。
对于文件读取和写入命令,v:cmdarg 变量保存有效的“++enc=”和“++ff=”参数。这些参数应用于读取/写入文件的命令。当使用“!”时,v:cmdbang 变量为 1,否则为 0。
有关示例,请参见 $VIMRUNTIME/plugin/netrwPlugin.vim。

11. 禁用自动命令 autocmd-disable

要禁用一段时间内的自动命令,请使用 'eventignore' 选项。请注意,这可能会导致意外行为,请确保使用 :try 块和 :finally 在之后恢复 'eventignore'
:noautocmd :noa 为了仅禁用一个命令的自动命令,请使用 ":noautocmd" 命令修饰符。这将在以下命令的持续时间内将 'eventignore' 设置为 "all"。示例
:noautocmd w fname.gz
这将在不触发 gzip 插件定义的自动命令的情况下写入文件。
请注意,一些自动命令不会立即触发,而是在稍后触发。这尤其适用于 CursorMovedTextChanged
命令索引
快速参考