autocmdでイベントをANDする方法はありますか?


21

autocmd 2つのイベントでをトリガーしますが、通常行われる方法ではありません。つまり、いずれかのイベントが発生した場合にをトリガーしautocmdます。両方のイベントが発生した場合にトリガーします。

例:
通常の方法

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

このコードは、BufWriteまたはBufReadでStripTrailingWhiteSpaces()を呼び出します

私は次のようなことをしたいです:

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

言い換えればautcmd、ファイルタイプがc、cpp、pythonのいずれかである場合にトリガーし、このバッファーへの書き込みが行われます。

どんな助けも大歓迎です。

回答:


14

1つのイベントが発生すると、autocommandコマンドが実行されます。一連のイベントが発生した後にコマンドを実行する必要があります。これを行う1つの方法は次のとおりです。

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

この<buffer>パターンにより、現在のバッファーが書き込まれたときに自動コマンドがトリガーされます。見る

:help autocmd-buflocal

更新

上記の解決策は非常に単純で、コメントで説明したいくつかの欠陥があります。これらの欠陥のいくつかに対処する、より完全なソリューションを次に示します。新しいコマンドを作成する前に、オートコマンドをグループに入れ、BufWritePreオートコマンドが存在する場合は削除します。バッファごとに1つの自動コマンドが作成されますが、1つだけです。

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

現在削除されているlcd047によって投稿された回答と同様の別の解決策は、FileTypeイベントが発生すると、「filetype」オプションが設定されることを認識することです。次に、次の例のように、 'filetype'の値でBufWritePostイベントへの応答を条件付けることができます。オートコマンドが1つしか作成されないという他のソリューションに勝る利点があります。

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

現在開いているすべてのファイルでこれを実行する場合、つまり:waを実行する場合はどうなりますか?
フラッシュバーン

ファイルが正しいファイルタイプで開かれた場合FileType、答えのautocmdは、BufWritePre保存時に起動する2番目のautocmd()をすでに設定しているでしょう。
ヴァンレーザー

1
上記のFileTypeautocmd は、正しいファイルタイプで開いたすべてのファイルに対して起動し、それらのファイルごとバッファローカルイベントをセットアップします。したがって、を実行すると、vimはファイルに保存する前に各バッファーの登録済みイベントを実行します。:wa
VanLaser

1
したがって、5つのPythonファイルを開くautocmdと、1つのファイルではなく5つのファイルがすべて書き込まれます。次に、たとえば、これらのファイルのうち3つが非表示になり、再び表示され、FileType再トリガーされるとautocmd、書き込み時にさらに3つのファイルが取得されます。これは素晴らしいです。なぜこの解決策を思い付かなかったのでしょうか。:)
lcd047

1
パフォーマンスは問題ではありません。stripTrailingWhiteSpaces()ただし、同じファイルに対して関数を数回実行すると、意図しない結果になる可能性があります。また、autocmd同じファイルの同じイベントに対してsが多いほど、実際の競合状態に陥る可能性が高くなります。アイデアを得るために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')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.