СПРАВОЧНИК ПО VIM - Брам Мооленаар

Начальные сведения по использованию автокоманд приводятся в разделе 40.3 Руководства пользователя.

  1. Введение
  2. Определение автокоманд
  3. Удаление автокоманд
  4. Вывод списка автокоманд
  5. События
  6. Шаблоны
  7. Группы
  8. Выполнение автокоманд
  9. Использование автокоманд

Vi не имеет ни одной из рассматриваемых здесь команд.
Доступно только в том случае, если Vim скомпилирован с особенностью |+autocmd|


1. Введение

Vim предоставляет возможность указывать команды, которые должны автоматически выполняться при чтении или записи файла при переходе в буфер или окно или из буфера или окна, а также при выходе из Vim. Например, вы можете создать автокоманду, которая будет включать опцию 'cindent' при редактировании файлов с именами "*.c". Вы можете также использовать автокоманды для реализации продвинутых возможностей, таких как редактирование сжатых файлов  (см. |gzip-пример|). Автокоманды как правило помещаются в файлах сценариев настройки .vimrc или .exrc.

ПРЕДУПРЕЖДЕНИЕ: Автокоманды являются чрезвычайно мощным средством и могут приводить к нежелательным побочным эффектам. Будьте осторожны, чтобы не уничтожить текст, который вы редактируете.

  • Прежде всего неплохо проверить работу автокоманды на каком-нибудь ненужном файле. Например: если вы создаёте автокоманды для распаковки сжатого файла перед редактированием, то убедитесь, что соответствующие автокоманды для сжатия файла во время записи работают корректно.
  • Будьте готовы, что во время выполнения автокоманды может произойти непредвиденная ошибка (например, на диске не будет места). Vim как правило в состоянии выполнить отмену изменений, внесённых в буфер, но от вас может потребоваться вручную исправить изменения, которые могли быть внесены в другие файлы (например, сжать распакованный файл).
  • Если события BufRead* позволяют редактировать сжатый файл, то события FileRead* должны также обеспечивать такую возможность (это позволяет обеспечить возможность восстановления в ряде случаев). По возможности старайтесь использовать для событий File* и Buf* одинаковые автокоманды.

2. Определение автокоманд

Замечание: После команды ":autocmd" не может следовать другая команда, поскольку символ '|' рассматривается в качестве части этой команды.

:au[tocmd] [группа] {событие} {шаблон} [nested] {команда} Добавить указанную {команду} к списку команд, которые Vim будет выполнять автоматически при возникновении указанного {события} для файла, имя которого соответствует заданному {шаблону}. Vim всегда добавляет автокоманды в конец списка уже существующих автокоманд, так что они всегда выполняются в том порядке, в котором они были определены. Объяснение параметра [nested] приводится в разделе |автокоманды-вложенные|.

Обратите внимание, что подстановка значения спецсимволов (таких, как "%" или "<cword>") в параметрах команды ":autocmd" не выполняется при определении автокоманды. Вместо этого, подстановка значений для спецсимволов происходит при поступлении соответствующего события, перед выполнением {команды}. Единственное исключение из этого правила -- "<sfile>", значение которого подставляется во время определения автокоманды. Например:

:au BufNewFile,BufRead *.html so <sfile>:h/html.vim

В данном случае Vim выполняет подстановку имени файла, в котором содержится эта строка, на место <sfile>.

Если сценарий настройки .vimrc считывается дважды, то определённые в нём автокоманды будут также определены по два раза. Чтобы избежать этого, нужно поместить в файл .vimrc, до определения автокоманд, следующую команду:

:autocmd!        " Удалить ВСЕ автокоманды для текущей группы

Если вы не хотите удалять все автокоманды, то вы можете также использовать переменную, чтобы убедиться, что автокоманда определена только один раз:

:if !exists("autocommands_loaded")
:  let autocommands_loaded = 1
:  au ...
:endif

Если параметр [группа] не задан, то Vim использует текущую группу (как определено по команде ":augroup"); в противном случае используется заданная группа. Обратите внимание, что [группа] должна быть определена заранее. Определить новую группу по команде ":au group ..." нельзя - для этого существует команда ":augroup".

В процессе проверки работы автокоманд может пригодиться опция 'verbose':

:set verbose=9

Такая настройка заставляет Vim показывать автокоманды во время их выполнения.

При определении автокоманды в сценарии, она сможет обращаться к местным для этого сценария функциям и использовать местные по отношению к сценарию привязки. При выполнении такой автокоманды при возникновении соответствующего события она будет исполняться в контексте своего сценария. Это может оказаться немаловажным, если автокоманда использует |<SID>|.

При выполнении команд сообщения одной команды выводятся поверх предыдущих сообщений. Это отличается от выполнения команд вручную. Как правило прокрутка экрана для вывода сообщений не производится, чтобы не появлялось приглашение нажать Enter. Однако, это всё же может произойти, если одна команда выводит два сообщения.

3. Удаление автокоманд

:au[tocmd]! [группа] {событие} {шаблон} [nested] {команда} Удалить все автокоманды для указанного {события} и {шаблона}, после чего добавить указанную {команду}. Объяснение параметра [nested] приводится в разделе |автокоманды-вложенные|.
:au[tocmd]! [группа] {событие} {шаблон} Удалить все автокоманды для указанного {события} и {шаблона}.
:au[tocmd]! [группа] * {шаблон} Удалить все автокоманды для указанного {шаблона} для всех событий.
:au[tocmd]! [группа] {событие} Удалить ВСЕ автокоманды для указанного {события}.
:au[tocmd]! [группа] Удалить ВСЕ автокоманды.

Если параметр [группа] не задан, то Vim использует текущую группу (как определено по команде ":augroup"); в противном случае используется заданная группа.

4. Вывод списка автокоманд

:au[tocmd] [группа] {событие} {шаблон} Показать все автокоманды, связанные с указанным {событием} и {шаблоном}.
:au[tocmd] [группа] * {шаблон} Показать все автокоманды, связанные с указанным {шаблоном} для всех событий.
:au[tocmd] [группа] {событие} Показать все автокоманды для указанного {события}.
:au[tocmd] [группа] Показать все автокоманды.

Если задан параметр [группа], то Vim выводит только автокоманды для указанной [группы]; в противном случае Vim выводит список автокоманд для ВСЕХ групп. Обратите внимание, что поведение при незаданном параметре [группа] отличается от поведения при определении и удалении автокоманд.

5. События

Vim распознаёт нижеперечисленные события. Имена событий являются регистронезависимыми (т.е. вы можете использовать "BUFread" или "bufread" вместо "BufRead").

BufNewFile Событие происходит в начале редактирования несуществующего файла. Может применяться для загрузки файла-шаблона.
BufReadPre Событие происходит в начале редактирования нового буфера, до загрузки файла в буфер. Не используется в том случае, если файл не существует.
BufRead или BufReadPost Событие происходит в начале редактирования нового буфера, после загрузки файла в буфер и перед обработкой режимной строки. См. также |BufWinEnter|, если вам необходимо выполнить какие-либо команды после обработки режимной строки.
Это событие НЕ происходит при выполнении команды ":r file" и не используется в том случае, если файл не существует, но используется при успешном восстановлении файла в случае аварийного завершения работы.
BufReadCmd Событие происходит перед началом редактирования нового буфера. Соответствующая автокоманда должна загружать файл в буфер.
См. |Cmd-событие|.
BufFilePre Событие происходит перед изменением имени текущего буфера при выполнении команды ":file" или ":saveas".
BufFilePost Событие происходит после изменения имени текущего буфера при выполнении команды ":file" или ":saveas".
FileReadPre Событие происходит перед чтением файла по команде ":read".
FileReadPost Событие происходит после чтения файла по команде ":read".
Обратите внимание, что Vim устанавливает отметки '[ и '] в позиции первой и последней строки прочитанного файла. Это можно использовать для выполнения операций над только что прочитанными строками.
FileReadCmd Событие происходит перед чтением файла по команде ":read". Соответствующая автокоманда должна выполнять чтение файла.
См. |Cmd-событие|.
FilterReadPre Событие происходит перед чтением файла при выполнении команды-фильтра. Vim выполняет проверку соответствия шаблону для имени текущего буфера, а не для имени временного файла, который создаётся при выполнении программы-фильтра.
FilterReadPost Событие происходит после чтения файла при выполнении команды-фильтра. Vim выполняет проверку соответствия имени текущего буфера шаблону, как при обработке события FilterReadPre.
FileType Событие происходит при изменении значения опции 'filetype'.
Для получения имени файла, для которого был назначен тип файла, может использоваться <afile>, а новое значение опции 'filetype' может быть получено с помощью <amatch>.
См. Типы файлов.
Syntax Событие происходит при изменении значения опции 'syntax'.
Для получения имени файла, для которого был назначен тип файла, может использоваться <afile>, а новое значение опции 'syntax' может быть получено с помощью <amatch>.
См. |:syn-on|.
StdinReadPre Событие происходит перед выполнением чтения в буфер из потока стандартного ввода. Применяется только в том случае, если Vim был запущен с ключом командной строки "-", см. |--|.
StdinReadPost Событие происходит после чтения в буфер из потока стандартного ввода, перед обработкой режимной строки. Применяется только в том случае, если Vim был запущен с ключом командной строки "-", см. |--|.
BufWrite или BufWritePre Событие происходит перед записью всего буфера в файл.
BufWritePost Событие происходит после записи всего буфера в файл (соответствующие автокоманды должны выполнять отмену команд, выполненных для события BufWritePre).
BufWriteCmd Событие происходит перед записью всего буфера в файл. Соответствующие автокоманды должны выполнять запись файла и выключать опцию 'modified' в случае успешного выполнения.
Содержимое буфера не должно изменяться.
См. |Cmd-событие|.
FileWritePre Событие происходит перед записью в файл, если сохраняется не весь буфер.
FileWritePost Событие происходит после записи в файл, если сохраняется не весь буфер.
FileWriteCmd Событие происходит перед записью в файл, если сохраняется не весь буфер. Соответствующие автокоманды должны выполнять запись в файл и не должны изменять содержимое буфера.
См. |Cmd-событие|.
FileAppendPre Событие происходит перед добавлением к файлу.
FileAppendPost Событие происходит после добавления к файлу.
FileAppendCmd Событие происходит перед добавлением к файлу. Соответствующие команды должны выполнять операцию добавления к файлу.
См. |Cmd-событие|.
FilterWritePre Событие происходит перед записью файла при использовании команды-фильтра или команды обнаружения различий.
Vim выполняет проверку соответствия шаблону для имени текущего буфера, а не для имени временного файла, который создаётся при выполнении программы-фильтра.
FilterWritePost Событие происходит после записи файла при использовании команды-фильтра или команды обнаружения различий.
Vim выполняет проверку соответствия шаблону для имени текущего буфера, как при обработке события FilterWritePre.

FileChangedShell

Событие происходит, если Vim обнаруживает, что отметка времени изменения файла изменена с момента начала редактирования файла. То же самое касается изменения атрибутов файла. См. |отметка_времени_изменения|. Обычно это событие происходит при выполнении команды оболочки, а также при выполнении команды |:checktime| или при получении Vim-ом фокуса ввода в многозадачной рабочей среде.

Соответствующая автокоманда выполняется для каждого изменённого файла. Данное событие не происходит, если включена опция 'autoread' и содержимое буфера остаётся без изменений.  Если для события FileChangedShell определена автокоманда, то предупреждение об изменении времени последнего изменения файла и запрос необходимости сохранения файла не выводятся. Это событие может быть полезно при перезагрузке связанных друг с другом нескольких буферов, которые были затронуты единственной командой.

ЗАМЕЧАНИЕ: При выполнении данной автокоманды текущий буфер ("%") может отличаться от буфера, отметка о времени изменения которого была изменена ("<afile>").

ЗАМЕЧАНИЕ: Соответствующие автокоманды не должны изменять текущий буфер, выполнять перемещение к другому буферу или удалять буфер.

ЗАМЕЧАНИЕ: Это событие не может быть вложенным, во избежание бесконечного цикла. Иными словами, во время выполнения автокоманд для события FileChangedShell не может поступать другое событие FileChangedShell.

FileChangedRO

Событие происходит перед внесением первого изменения в открытый только для чтения файл. Оно может быть использовано для получения файла из системы управления исходными кодами. Событие не происходит, если изменение было внесено при выполнении автокоманды.

ПРЕДУПРЕЖДЕНИЕ: Это событие возникает при внесении изменения, непосредственно перед применением изменения к тексту. Если соответствующая команда выполняет операцию перемещения курсора, то последствия такого изменения не определены.

FocusGained Событие происходит при обретении Vim-ом фокуса ввода. Работает только в версии с графическим интерфейсом и в некоторых консольных версиях на системах, где распознаётся передача фокуса приложению.
FocusLost Событие происходит при потере Vim-ом фокуса ввода. Работает только в версии с графическим интерфейсом и в некоторых консольных версиях на системах, где распознаётся потеря фокуса приложением.
FuncUndefined Событие происходит в том случае, когда вызывается неопределённая пользовательская функция. Это может быть полезным для определения функции непосредственно при её использовании. Как <amatch>, так и <afile> используют в качестве своего значения имя функции.
CursorHold Событие происходит, если пользователь не нажимает никаких кнопок в течение интервала времени, заданного в значении опции 'updatetime'. Событие не повторяется до тех пор, пока пользователь не нажмёт какую-либо кнопку (иными словами, если вы отлучились, чтобы приготовить кофе, оно не будет повторяться каждые 'updatetime' миллисекунд). См. также |CursorHold-пример|, где показано, как использовать эту возможность для предварительного просмотра меток. Это событие происходит только в Обычном режиме.

Замечание: с данным событием не могут использоваться интерактивные команды. Приглашение нажать Enter не выводится, а экран обновляется напрямую, если в этом есть необходимость.

Замечание: В будущем возможно будет добавлена дополнительная возможность задавать временной интервал.

Совет: для насильного обновления строк состояния используйте

:let &ro = &ro
Доступно только на Amiga, Unix, Win32, MSDOS и всех версиях с графическим интерфейсом.
BufEnter Событие происходит после перехода в буфер. Полезно при настройке опций в зависимости от типа файла. Соответствующие автокоманды также выполняются в начале редактирования буфера, после выполнения автокоманд, связанных с событием BufReadPost.
BufLeave Событие происходит перед переходом в другой буфер, а также при закрытии или "бросании" активного окна, если новое активное окно связано с другим буфером. Это событие не используется при завершении работы Vim по команде ":qa" или ":q".
BufWinEnter Событие происходит после того, как буфер будет показан в окне: при загрузке буфера (после обработке режимной строки), при показе скрытого буфера в окне (после чего он перестаёт быть скрытым), либо если буфер, уже отображаемый в окне, отображается в другом окне.

BufWinLeave

Событие происходит перед тем, как буфер удаляется из окна, если буфер не отображается при этом в другом окне. Это событие также происходит при выходе из Vim. Событие происходит до возникновения событий BufUnload и BufHidden.

ЗАМЕЧАНИЕ: При выполнении соответствующих этому событию автокоманд, текущий буфер "%" может отличаться от выгружаемого буфера "<afile>".

BufUnload

Событие происходит перед выгрузкой буфера, т.е. перед освобождением памяти, выделенной под текст в буфере. Это происходит после события BufWritePost, но перед событием BufDelete. Также применяется для всех буферов при завершении работы Vim.

ЗАМЕЧАНИЕ: При выполнении соответствующих этому событию автокоманд, текущий буфер "%" может отличаться от выгружаемого буфера "<afile>".

BufHidden

Событие происходит сразу после того, как буфер был скрыт. Иными словами, если на экране нет окон, в которых бы отображался этот буфер, но сам буфер при этом не был выгружен из памяти или удалён. Не используется при выполнении команд ":qa" или ":q" при завершении работы Vim.

ЗАМЕЧАНИЕ: При выполнении соответствующих этому событию автокоманд, текущий буфер "%" может отличаться от скрываемого буфера "<afile>".

BufNew

Событие происходит сразу после создания нового буфера или сразу после переименования буфера. Если буфер был добавлен к списку буферов, то также происходит событие BufAdd.

ЗАМЕЧАНИЕ: При выполнении соответствующих этому событию автокоманд, текущий буфер "%" может отличаться от создаваемого буфера "<afile>".

BufAdd или BufCreate

Событие происходит сразу после создания нового буфера, добавленного к списку буферов, либо после добавления буфера к списку буферов. Также событие возникает сразу после переименования буфера в списке буферов. Событие BufCreate существует по причинам исторического характера.

ЗАМЕЧАНИЕ: При выполнении соответствующих этому событию автокоманд, текущий буфер "%" может отличаться от создаваемого буфера "<afile>".

BufDelete

Событие происходит перед удалением буфера из списка буферов. Если буфер был загружен, то сначала происходит событие BufUnload. Также это событие возникает непосредственно перед переименованием буфера в списке буферов.

ЗАМЕЧАНИЕ: При выполнении соответствующих этому событию автокоманд, текущий буфер "%" может отличаться от удаляемого буфера "<afile>".

BufWipeout

Событие происходит перед полным удалением буфера. Перед этим событием могут также произойти события BufUnload и BufDelete (если буфер был загружен и если он был в списке буферов). Событие также происходит непосредственно перед переименованием буфера (в том числе, если буфер не был в списке буферов).

ЗАМЕЧАНИЕ: При выполнении соответствующих этому событию автокоманд, текущий буфер "%" может отличаться от удаляемого буфера "<afile>".

WinEnter

Событие происходит после перехода в другое окно. Не возникает при переходе в первое окно сразу после запуска Vim. Полезно для настройки высоты окна. В том случае, если окно открыто для другого буфера, Vim выполняет автокоманды, связанные с событием BufEnter после автокоманд, связанных с событием WinEnter.

Замечание: При использовании команды ":split fname" событие WinEnter происходит после выполнения разделения окна, но до загрузки файла "fname".

WinLeave Событие происходит перед тем, как выполняется переход в другое окно. Если окно, в которое выполняется переход, открыто для другого буфера, то перед выполнением автокоманд WinLeave выполняются автокоманды BufLeave (кроме случая, когда выполняется команда ":new"). Событие не используется при выходе из Vim по командам ":qa" или ":q".
CmdwinEnter Событие происходит после перехода в окно команд. Полезно для настройки опций специально для этого типа окна. Это событие происходит ВМЕСТО событий BufEnter и WinEnter. <afile> присваивается одиночный символ, соответствующий типу командной строки.
См. |окно_команд-символы|.
CmdwinLeave Событие происходит перед переходом из окна команд в другое окно. Полезно для сброса глобальных настроек, выполненных с помощью автокоманд, связанных с событием CmdwinEnter. Это событие происходит ВМЕСТО событий BufEnter и WinEnter.
<afile> присваивается одиночный символ, соответствующий типу командной строки.
См. |окно_команд-символы|.
GUIEnter Событие происходит после успешного запуска графического интерфейса и открытия окна Vim. При использовании gvim это событие происходит перед событием VimEnter. Может использоваться для настройки положения окна Vim на экране  в сценарии настроек .gvimrc:
:autocmd GUIEnter * winpos 100 50
VimEnter Событие происходит после выполнения всех первоначальных настроек при запуске Vim, в том числе после загрузки файлов .vimrc, выполнения команд, заданных в командной строке запуска с помощью ключа "-c cmd", создания всех окон и загрузки всех связанных с ними буферов.
VimLeavePre Событие происходит перед выходом из Vim, непосредственно перед записью файла .viminfo. Оно происходит только один раз, если имеется соответствие имени текущего на момент выхода буфера. Чаще всего используется с шаблоном "*".
:autocmd VimLeavePre * call CleanupStuff()

Для обнаружения аварийного выхода используйте переменную |v:dying|.

VimLeave Событие происходит перед выходом из Vim, сразу после записи файла .viminfo. Оно происходит только один раз, как и событие VimLeavePre. Для обнаружения аварийного выхода используйте переменную |v:dying|.
EncodingChanged Событие происходит всякий раз, когда изменяется значение опции 'encoding'. Полезно, например, для настройки шрифтов.
FileEncoding Устаревшее, но по-прежнему работает. Эквивалентно |EncodingChanged|.
RemoteReply Событие происходит при получении ответа от Vim, выполняющего функции сервера. См. |server2client()|.
<amatch> эквивалентно имени сервера {serverid}, с которого был отправлен ответ, а <afile> равно строке ответа. Обратите внимание, что даже если определена автокоманда для данного события, для поглощения ответа он должен быть прочитан с помощью функции |remote_read()|.
TermChanged Событие происходит после изменения значения опции 'term'. Полезно для перезагрузки файла синтаксиса для обновления цветов подсветки, шрифтов и других настроек, зависящих от используемого терминала. Выполняется для всех загруженных буферов.
TermResponse Событие происходит после получения отклика на |t_RV| от терминала. Значение переменной |v:termresponse| может быть использовано для выполнения операций, которые зависят от версии используемого терминала.
UserGettingBored Событие происходит, когда пользователь нажимает CTRL-C.  Типа, шутка такая! :-)
User Событие никогда не происходит автоматически. Оно используется для автокоманд, которые выполняются только при помощи команды ":doautocmd".

Вы можете также указать список имён событий, разделённых запятыми. В списке не допускается использование пробелов. Команда применяется ко всем событиям в списке.

При ЧТЕНИИ ФАЙЛОВ возможно четыре вида событий:

BufNewFile в начале редактирования несуществующего файла
BufReadPre и BufReadPost в начале редактирования существующего файла
FilterReadPre и FilterReadPost при чтении временного файла, созданного при выполнении команды-фильтра
FileReadPre и FileReadPost при чтении любого другого файла

Каждый раз Vim использует только один из четырёх видов событий для чтения файла. События "Pre" и "Post" срабатывают парно, до и после чтения файла соответственно.

Обратите внимание, что автокоманды для событий *ReadPre и всех событий Filter не могут изменять текущий буфер (если это происходит, то выводится сообщение об ошибке). Это необходимо, чтобы предупредить чтение файла в не тот буфер.

Обратите внимание, что опция 'modified' отключается ПОСЛЕ выполнения автокоманд для событий BufReadPost и BufNewFile. Однако, если опция 'modified' включена с помощью автокоманд, то этого не происходит.

Вы можете использовать опцию 'eventignore', чтобы ограничить используемые события или вообще не обрабатывать никаких событий.

6. Шаблоны

Проверка соответствия {шаблону} имени файла выполняется двумя способами:

1. Если в шаблоне не встречается символ '/', то Vim выполняет проверку соответствия только для последней части путевого имени (без пути к каталогу).
2. Если в шаблоне есть символ '/', то Vim выполняет проверку соответствия как для короткого имени файла (как набрано), так и для полного имени файла (после подстановки полного пути к файлу и разрешения символических ссылок).

Примеры:

:autocmd BufRead *.txt                set et

Эта команда включает опцию 'et' для всех текстовых файлов.

:autocmd BufRead /vim/src/*.c        set cindent

Включает опцию 'cindent' для файлов C в каталоге /vim/src.

: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 ~/.vimrc   so ~/.vimrc
:autocmd BufRead ~archive/*      set readonly

Переменная окружения подставляется при определении автокоманды, а не в момент выполнения. Это отличается от обычных команд!

В данном случае используется шаблон для имени файла:

* соответствует любой последовательности символов
? соответствует любому одиночному символу
\? соответствует символу '?'
. соответствует символу '.'
~ соответствует символу '~'
, используется для разделения шаблонов
\, соответствует символу ','
{ } тоже, что и \( \) в |шаблоне|
, внутри { }: то же, что и \| в |шаблоне|
\ специальное значение, как в |шаблоне|
[ch] соответствует символам 'c' или 'h'
[^ch] соответствует любому символу, кроме 'c' и 'h'

Обратите внимание, что в качестве разделителя компонентов пути используется '/' на всех системах (даже на MS-DOS и OS/2), поскольку использование символа обратной косой черты в шаблоне затруднительно и, кроме того, это позволяет сделать автокоманды переносимыми между различными операционными системами.

Проверка соответствия шаблону происходит при возникновении события. Изменение имени буфера в одной из автокоманд, и даже удаление буфера, не приводят к изменениям в наборе выполняемых автокоманд. Например:

au BufEnter *.foo  bdel
au BufEnter *.foo  set modified

Эти автокоманды выполняют удаление текущего буфера, после чего включается опция 'modified' для того буфера, который становится текущим вместо удалённого. Vim не обращает внимания на то, что "*.foo" может не совпадать с именем этого нового буфера. Он сравнивает "*.foo" с именем буфера в тот момент, когда произошло событие.

7. Группы

Автокоманды можно объединять в группы. Эта возможность позволяет удалять или выполнять сразу несколько автокоманд. Например, все автокоманды для настройки подсветки синтаксиса можно поместить в группу "highlight", что позволяет выполнять команду ":doautoall highlight BufRead" при запуске графического интерфейса.

В том случае, если группа автокоманды не задана, Vim использует группу по умолчанию. Группа по умолчанию не имеет имени. Выполнить автокоманды только из группы по умолчанию нельзя - вам придётся выполнять для этого автокоманды из всех групп.

Обычно, при автоматическом выполнении автокоманд Vim использует автокоманды из всех групп. Имя группы имеет значение только при выполнении автокоманд с помощью команд ":doautocmd" или ":doautoall", либо при определении или удалении автокоманд.

Имя группы может содержать любые символы, кроме пробелов. Имя группы "end"  (а также "END" в верхнем регистре символов) является зарезервированным.

Имя группы является регистрозависимым. Обратите внимание, что это отличается от имени события!

:aug[roup] {имя} Определяет имя группы автокоманд для всех последующих команд ":autocmd". Для выбора группы по умолчанию используется имя "end" или "END".
:aug[roup]! {имя} Удаляет группу автокоманд с указанным {именем}. Не следует использовать эту команду, если в данной группе есть автокоманды - никаких проверок на этот счёт не выполняется!

Для определения автокоманд в определённой группе используйте следующий метод:

  1. Выберите группу с помощью ":augroup {имя}".
  2. Удалите все старые автокоманды с помощью команды ":au!".
  3. Определите необходимые автокоманды.
  4. Вернитесь к группе по умолчанию с помощью команды "augroup END".

Пример:

:augroup uncompress
:  au!
:  au BufEnter *.gz        %!gunzip
:augroup END

Это позволяет избежать повторного определения автокоманд (например, после повторного считывания файла .vimrc).

8. Выполнение автокоманд

Vim может выполнять автокоманды в неавтоматическом режиме. Это полезно в тех случаях, когда вы изменили определения автокоманд или если Vim выполнил не те автокоманды, которые требовались (например, при неверно заданном шаблоне имён файлов).

Обратите внимание, что опция 'eventignore' используется и в случае неавтоматического выполнения команд. Автокоманды, соответствующие событиям, перечисленным в значении данной опции, выполняться не будут.

:do[autocmd] [группа] {событие} [имя_файла]

Применить к текущему буферу автокоманды, соответствующие указанному [имени_файла], (по умолчанию: для текущего имени файла), определённые для указанного {события}.

Эта команда может применяться в тех случаях, когда текущее имя файла не соответствует нужному шаблону, после изменения настроек или для выполнения автокоманд, связанных с определённым событием. Вы также можете использовать эту команду внутри автокоманды, что позволяет применять автокоманды, определённые для файлов с одним расширением, к файлом с другим расширением. Например:

:au Bufenter *.cpp so ~/.vimrc_cpp
:au Bufenter *.cpp doau BufEnter x.c

Будьте внимательны, чтобы не нарваться на бесконечный цикл. См. |автокоманды-вложенные|.

Если параметр [группа] не задан, то Vim выполняет автокоманды во всех группах. Если же параметр [группа] задан, то Vim будет выполнять соответствующие автокоманды только для данной группы.

Замечание: при попытке использовать неопределённое имя группы Vim выводит сообщение об ошибке.

:doautoa[ll] [группа] {событие} [имя_файла]

То же, что и ":doautocmd", но соответствующие автокоманды применяются ко всем загруженным буферам. Обратите внимание, что {имя_файла} используется для выбора автокоманд, а не буферов, в которых они должны быть применены.

Внимание: не применяйте эту команду для выполнения автокоманд, которые приводят к удалению буфера, перемещению в другой буфер или изменению содержимого буфера; результат такой операции непредсказуем. Эта команда предназначена для выполнения автокоманд, которые выполняют настройку значений опций, изменение режима подсветки синтаксиса и тому подобных вещей.

9. Использование автокоманд

При ЗАПИСИ ФАЙЛОВ возможно появление четырёх пар событий. Vim каждый раз использует только одну из этих пар при выполнении команды записи:

BufWriteCmd BufWritePre BufWritePost запись всего буфера
  FilterWritePre FilterWritePost запись временного файла при выполнении команды-фильтра
FileAppendCmd FileAppendPre FileAppendPost добавление к файлу
FileWriteCmd FileWritePre FileWritePost любая другая команда записи

При использовании автокоманд для событий "*Cmd" считается, что запись осуществляется в соответствующей автокоманде. Запись с использованием других средств не производится и остальные события не происходят.
См. |Cmd-событие|.

Обратите внимание, что команды для событий *WritePost должны отменять изменения, внесённые в буфер по командам, связанным с событиями *WritePre;  в противном случае при записи файла возникает побочный эффект: внесение в буфер изменений.

Перед выполнением автокоманд буфер, строки которого должны быть записаны, временно становится текущим буфером. После отработки автокоманд предыдущий текущий буфер снова становится текущим, если соответствующие автокоманды не изменяют текущий буфер или не выполняют удаление предыдущего текущего буфера.

Автокоманды *WritePre и *AppendPre не должны удалять буфер, строки которого должны быть записаны.

Отметки '[ и '] используются для обозначения специальных позиций:

  • Перед событием *ReadPre отметка '[ устанавливается на строку, расположенную непосредственно над строкой, где будет выполнена вставка новых строк.
  • Перед событием *ReadPost отметка '[ устанавливается в первую из только что прочитанных строк, а отметка '] -- в последнюю строку.
  • Перед выполнением автокоманд для событий *WritePre и *AppendPre отметка '[ устанавливается на первую строку, подлежащую записи, а отметка '] - на последнюю строку.

Внимание: отметки '[ и '] изменяются при использовании команд, которые изменяют буфер.

В командах, в качестве параметра которых используется имя файла, можно использовать "<afile>" для указания прочитанного файла |:<afile>| (вы также можете использовать "%" вместо имени текущего файла). Вместо номера текущего буфера можно использовать "<abuf>", что также подходит и для безымянных буферов, но не работает для файлов без буфера (например, при выполнении команды ":r file").

Примеры чтения и записи сжатых файлов:

: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". Вы можете использовать команду ":q" и при выполнении команды ":undo" по событию BufWritePostв для отмены изменений, внесённых при выполнении команд, связанных с событием BufWritePre (это также позволяет использовать команду "ZZ"). Если вы желаете, чтобы буфер был помечен как содержащий несохранённые изменения, включите опцию 'modified'.

Для выполнения в автокоманде команд Обычного режима, используйте команду ":normal". Будьте внимательны! Если команда Обычного режима не завершена, то Vim будет ожидать от пользователя ввода символов для её завершения (например, после ":normal m" следует ввести имя отметки).

Если вы желаете, чтобы после внесения изменений буфер был помечен как не содержащий изменений, выключите опцию 'modified'. Это позволяет выйти из буфера по команде ":q" вместо ":q!".

По умолчанию, автокоманды не являются вложенными. Если вы используете в автокоманде ":e" или ":w", то Vim не выполняет автокоманды для событий BufRead и BufWrite при выполнении этих команд. Если вам необходима такая возможность, то в тех командах, где требуется выполнение вложенных автокоманд, следует использовать специальный флаг "nested". Например:

:autocmd FileChangedShell *.c nested e!

Чтобы обеспечить выход из рекурсивных циклов, максимально допустимая глубина вложения автокоманд ограничивается 10 уровнями.

Вы можете использовать в автокоманде команду ":au". Более того, это позволяет определять самоизменяющиеся автокоманды! Такая возможность может оказаться полезной для автокоманд, которые должны выполняться только один раз.

На сегодня не существует способа отключения автокоманд. Если вы желаете записать файл без выполнения автокоманд для этого типа файла, то вы можете записать его под другим именем и затем переименовать его с помощью команд оболочки. В некоторых ситуациях помогает использование опции 'eventignore'.

Замечание: Если последняя строка в файле, прочитанном по команде ":read file" или с помощью команды-фильтра, не заканчивается символом <EOL>, то Vim помнит об этом, так что при последующей записи (по команде ":write file" или с помощью команды-фильтра) Vim не будет вставлять символ <EOL> в последней строке в том случае, когда последней строкой файла является по-прежнему всё та же самая строка И включена опция 'binary'. Это позволяет команде-фильтру выполнять запись того же самого файла, что и прочитанные строки, а команде записи выполнять запись того же самого файла, что и строки, прочитанные с вывода команды фильтра. Например, ещё один способ записи сжатого файла:

:autocmd FileWritePre *.gz   set bin|'[,']!gzip
:autocmd FileWritePost *.gz  undo|set nobin

Вы можете задавать несколько шаблонов, разделённых запятыми. Вот несколько примеров:

: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;", то поиск будет начинаться с того места, в которое был перемещён курсор после перехода в данный буфер, а не с начала файла.

Чтобы при открытии нового файла загрузить в буфер файл-заготовку (рыбу), используйте примерно такие автокоманды:

: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/Последнее изменение: /s/Последнее изменение: .*/Последнее изменение: " .
:  \strftime("%Y %b %d")
:endfun

чтобы эти команды работали, в первых 20 строках файла должна содержаться строка "Последнее изменение: <дата время>". Vim выполняет замену <дата время> (и всего последующего текста в данной строке) на текущую отметку времени. Поясним, как это работает:

ks текущая позиция в файле помечается отметкой 's'
call LastMod() вызывается функция LastMod(), которая выполняет всю работу
's курсор перемещается в старую позицию.

Функция LastMod() проверяет, чтобы файл был короче 20 строк, после чего использует команду ":g" для поиска строк, в которых содержится фраза "Последнее изменение: ". Для каждой такой строки выполняется команда ":s", которая производит замену существующей отметки времени на текущую. Для задания выражения для команд ":g" и ":s" применяется команда ":execute". Текущая дата и время берётся из значения, возвращаемого функцией strftime(). Вы можете поменять её параметр для изменения формата отметки даты и времени.

При вводе :autocmd в командной строке вы можете при необходимости использовать автодополнение имён событий и команд (при помощи <Tab>, CTRL-D и т.д.).

Vim выполняет все соответствующие автокоманды в том же порядке, в котором они были определены. Рекомендуется, чтобы первая автокоманда применялась ко всем файлам, что организуется при помощи шаблона файла "*". Иными словами, вы можете сначала определить значения по умолчанию для всех файлов, а затем переопределить эти значения для особых случаев с помощью последующих автокоманд. При этом, если для данного файла не существует специальной автокоманды, вы сможете по крайней мере восстановить значения по умолчанию (если, например, выполняется переход к данному файлу из другого файла, для которого существуют специальные автокоманды). Обратите внимание, что "*" также затрагивает файлы, начинающиеся с ".", что отличается от поведения оболочек Unix.

При выполнении автокоманд шаблоны текущего поиска не изменяются. Vim сохраняет шаблоны текущего поиска перед выполнением автокоманд, после чего восстанавливает их значение. Это, в частности, означает, что автокоманды не затрагивают подсветку соответствий шаблону, выполненную с помощью опции 'hlsearch'. Внутри автокоманд, однако, вы можете использовать шаблоны поиска как обычно, например, используя команду "n". Если вы желаете, чтобы автокоманда изменяла шаблон поиска с тем, чтобы он мог быть использован после завершения автокоманды, то воспользуйтесь командой ":let @/ =".

Подсветка соответствий шаблону поиска не может быть отключена во время выполнения автокоманды по ":nohlsearch". Используйте флаг 'h' в значении опции 'viminfo' для отключения подсветки соответствий шаблону поиска при запуске Vim.

Автокоманды, соответствующие событиям "*Cmd" сами должны позаботиться о чтении или записи файла. Данная особенность применяется при работе со специальными файлами, например, расположенными на удалённой системе.

ОСТОРОЖНО: при неправильном использовании этих событий может оказаться невозможным выполнить чтение или запись соответствующих файлов! Убедитесь, что ваши автокоманды работают правильно. Лучше всего использовать для проверки шаблон, которому ни при каких обстоятельствах не будет соответствовать имя обычного файла, например "ftp://*".

При определении BufReadCmd Vim может столкнуться с трудностями при восстановлении аварийно завершённого сеанса редактирования. При восстановлении из исходного файла Vim выполняет чтение только тех частей файла, которые отсутствуют в своп-файле. Поскольку это не возможно при использовании автокоманд, связанных с событием BufReadCmd, применяйте команду |:preserve|, чтобы быть уверенным, что исходный файл не нужен для восстановления. Возможно, вы пожелаете делать это только тогда, когда считаете, что файл мог быть изменён.

Переменная |v:cmdarg| используется для хранения действующих аргументов командной строки "++enc=" и "++ff=". Их следует использовать при выполнении команд для чтения и записи файла. Значение переменной |v:cmdbang| равно 1, если используется модификатор "!", или 0, если "!" не используется.

См. в качестве примера сценарий модуля $VIMRUNTIME/plugin/netrw.vim.