Apakah ada cara untuk DAN acara di autocmd?

21

Saya ingin memicu autocmd pada dua peristiwa tetapi tidak dengan cara yang biasanya dilakukan, yaitu jika salah satu peristiwa terjadi maka memicu autocmd. Saya ingin memicu jika kedua peristiwa itu terjadi.

Misalnya:
Cara yang biasa dilakukan

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

Kode ini akan memanggil StripTrailingWhiteSpaces () di BufWrite atau BufRead

Saya ingin melakukan sesuatu seperti:

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

Dengan kata lain memicu autcmdketika filetype adalah salah satu dari c, cpp, python dan penulisan pada buffer ini terjadi.

Bantuan apa pun dihargai.

flashburn
sumber

Jawaban:

14

Perintah perintah otomatis dijalankan ketika satu peristiwa terjadi. Anda ingin perintah dieksekusi setelah urutan peristiwa telah terjadi. Salah satu cara untuk melakukannya adalah seperti ini:

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

The <buffer>Pola menyebabkan autocommand yang akan dipicu ketika buffer saat ditulis. Lihat

:help autocmd-buflocal

Memperbarui

Solusi di atas cukup sederhana dan memiliki beberapa kekurangan yang dibahas dalam Komentar. Berikut ini adalah solusi yang lebih lengkap untuk mengatasi beberapa kekurangan tersebut. Itu menempatkan autocommand dalam grup dan menghapus autocommand BufWritePre, jika ada, sebelum membuat yang baru. Itu masih membuat satu perintah otomatis per buffer, tetapi hanya satu.

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

Solusi lain, mirip dengan jawaban yang diposting oleh lcd047, sekarang dihapus, adalah untuk mengenali bahwa ketika peristiwa FileType terjadi, opsi 'filetype' diatur. Kemudian Anda dapat mengkondisikan respons terhadap acara BufWritePost pada nilai 'filetype', seperti dalam contoh berikut. Ini memiliki keunggulan dibandingkan solusi lain yang hanya dibuat satu autocommand.

autocmd BufWritePre * if count(['c','cpp','python'],&filetype)
    \ | call SkipTrailingWhiteSpaces()
    \ | endif
garyjohn
sumber
Bagaimana jika saya ingin menjalankan ini pada semua file yang sedang terbuka, yaitu saya jalankan: wa?
Flashburn
Jika file dibuka dengan tipe file yang benar, FileTypeautocmd dalam jawabannya akan sudah mengatur autocmd kedua ( BufWritePre) untuk diaktifkan ketika Anda menyimpannya.
VanLaser
1
The FileTypeautocmd atas kehendak api untuk setiap file yang dibuka dengan filetype benar, dan kemauan setup penyangga-lokal acara untuk setiap file-file. Jadi, jika Anda menjalankan :wa, vim akan menjalankan aktivitas terdaftar untuk setiap buffer, sebelum menyimpan ke file.
VanLaser
1
Jadi, jika Anda membuka 5 file Python, Anda akan memiliki 5 autocmds alih-alih satu file, semua tertulis. Kemudian jika, katakanlah, 3 file ini disembunyikan, lalu ditampilkan kembali, FileTypedipicu kembali sehingga Anda mendapatkan 3 file lagi autocmd, juga saat ditulis. Ini luar biasa, saya heran mengapa saya tidak menemukan solusi ini. :)
lcd047
1
Performa bukan masalah. Menjalankan fungsi stripTrailingWhiteSpaces()beberapa kali terhadap file yang sama mungkin memiliki konsekuensi yang tidak diinginkan. Juga, semakin banyak autocmdyang Anda miliki untuk acara yang sama untuk file yang sama, semakin besar kemungkinan Anda mengalami beberapa kondisi yang benar-benar berlomba. Coba cari arsip vim_dev untuk mendapatkan ide. Kemudian lagi, apa yang saya tahu, mungkin hanya bekerja untuk Anda, bukan?
lcd047
4

Secara umum, jika Anda tidak tahu acara mana yang akan terjadi terlebih dahulu, Anda dapat menggunakan helper untuk melacak ketika masing-masing menyala dan hanya menjalankan perintah Anda ketika yang terakhir menyala:

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')
Mu Mind
sumber