Чи є шлях до І подій у autocmd?


21

Я хотів би запустити autocmd на дві події, але не таким чином, як це зазвичай робиться, тобто якщо будь-яка з подій сталася, то запускається an autocmd. Я хочу це спровокувати, якщо відбулися обидві події.

Наприклад:
Звичайний спосіб зробити це

autocmd BufWrite,BufRead *.c *.py *.h :call StripTrailingWhitespaces()

Цей код буде викликати StripTrailingWhiteSpaces () на BufWrite або BufRead

Я хотів би зробити щось на кшталт:

autocmd Filetype c,cpp,python AND BufWrite :call StripTrailingWhiteSpaces()

Іншими словами, спрацьовує a, autcmdколи тип файлу є одним із c, cpp, python і відбувається запис у цей буфер.

Будь-яка допомога вдячна.

Відповіді:


14

Команда автокоманди виконується, коли відбувається одна подія. Ви хочете, щоб команда виконувалася після того, як відбулася послідовність подій. Один із способів зробити це такий:

autocmd FileType c,cpp,python
    \ autocmd BufWritePre <buffer> call StripTrailingWhiteSpaces()

<buffer>Моделі призводять до того , автокомандами бути спрацьовувати , коли поточний буфер записуються. Побачити

:help autocmd-buflocal

Оновлення

Наведене вище рішення досить просте і має деякі недоліки, про які йшлося в коментарях. Ось більш повне рішення, яке вирішує деякі з цих недоліків. Він розміщує автокоманди у групі та видаляє автокоманду BufWritePre, якщо така існує, перед створенням нової. Він все ще створює одну автокоманду на буфер, але лише одну.

augroup TrailSpace
    autocmd FileType c,cpp,python
        \ autocmd! TrailSpace BufWritePost <buffer> call SkipTrailingWhiteSpaces()
augroup END

Іншим рішенням, подібним до відповіді, опублікованої lcd047, тепер видаленої, є визнання того, що коли відбувається подія FileType, встановлюється параметр "тип файлу". Тоді ви можете обумовити відповідь на подію BufWritePost на значення "тип файлу", як у наступному прикладі. Він має перевагу перед іншими рішеннями у створенні лише однієї автокоманди.

autocmd BufWritePre * if count(['c','cpp','python'],&filetype)
    \ | call SkipTrailingWhiteSpaces()
    \ | endif

Що робити, якщо я хочу запустити це на всіх відкритих на даний момент файлах, тобто виконувати: wa?
спалахування

Якби файли були відкриті з правильним FileTypeформатом файлів, autocmd у відповіді вже встановив би другий autocmd ( BufWritePre) для запуску під час їх збереження.
VanLaser

1
FileTypeAutocmd вище буде спрацьовувати для кожного файлу, відкрити з допомогою правильного типу файлу і настройки Уїллу буфера локального події для кожного з цих файлів. Отже, якщо ви запустите :wa, vim запустить зареєстровані події для кожного буфера, перш ніж зберегти у файл.
VanLaser

1
Отже, якщо ви відкриєте 5 файлів Python, у вас буде 5 autocmds замість одного, все в режимі запису. Тоді, якщо, скажімо, 3 з цих файлів приховані, потім знову показуються, FileTypeповторно спрацьовує, тож ви отримуєте ще 3 autocmdс, також під час запису. Це геніально, мені цікаво, чому я не придумав такого рішення. :)
lcd047

1
Продуктивність не є проблемою. Якщо запустити функцію stripTrailingWhiteSpaces()кілька разів проти одного файлу, можливо, це матиме непередбачувані наслідки. Крім того, чим більше autocmdу вас одного і того ж події для одного і того ж файлу, тим більше шансів на те, що ви зіткнетесь з деякими дійсно умовами гонки. Спробуйте знайти архіви vim_dev, щоб отримати уявлення. Потім знову, що я знаю, це може просто працювати для вас, правда?
lcd047

4

Загалом, якщо ви не знаєте, яка подія відбудеться першою, ви можете використовувати помічник, щоб відстежувати, коли кожен стріляє, і виконувати вашу команду лише тоді, коли запускається остання:

function StripTrailingWhiteSpacesIfReady(event) abort
  if !exists('b:events_for_whitespace')
    let b:events_for_whitespace = {}
  endif
  let b:events_for_whitespace[a:event] = 1
  if has_key(b:events_for_whitespace, 'FileType') && has_key(b:events_for_whitespace, 'Buf')
    " Strip trailing whitespace
    %s/\m\s\+$//
  endif
endfunction
autocmd Filetype c,cpp,python call StripTrailingWhiteSpacesIfReady('FileType')
autocmd BufWrite,BufRead * StripTrailingWhiteSpacesIfReady('Buf')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.