Existe uma maneira de eventos AND no autocmd?

21

Eu gostaria de acionar um autocmd em dois eventos, mas não da maneira que normalmente é feito, ou seja, se um dos eventos aconteceu, então acionar um autocmd. Quero acioná-lo se os dois eventos acontecerem.

Por exemplo:
A maneira usual de fazer isso

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

Esse código chamará StripTrailingWhiteSpaces () no BufWrite ou BufRead

Eu gostaria de fazer algo como:

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

Em outras palavras, dispara um autcmdquando o tipo de arquivo é um de c, cpp, python e a gravação nesse buffer ocorre.

Qualquer ajuda é apreciada.

queimadura
fonte

Respostas:

14

Um comando de comando automático é executado quando um evento ocorre. Você deseja que um comando seja executado após a ocorrência de uma sequência de eventos. Uma maneira de fazer isso é assim:

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

O <buffer>padrão faz com que o comando automático seja acionado quando o buffer atual for gravado. Vejo

:help autocmd-buflocal

Atualizar

A solução acima é bastante simples e possui algumas falhas que foram discutidas nos Comentários. Aqui está uma solução mais completa que aborda algumas dessas falhas. Ele coloca os comandos automáticos em um grupo e exclui o comando automático BufWritePre, se houver, antes de criar um novo. Ele ainda cria um comando automático por buffer, mas apenas um.

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

Outra solução, semelhante à resposta publicada por lcd047, agora excluída, é reconhecer que quando o evento FileType ocorre, a opção 'filetype' está definida. Em seguida, você pode condicionar a resposta ao evento BufWritePost no valor de 'tipo de arquivo', como no exemplo a seguir. Tem a vantagem sobre as outras soluções que apenas um autocommand é criado.

autocmd BufWritePre * if count(['c','cpp','python'],&filetype)
    \ | call SkipTrailingWhiteSpaces()
    \ | endif
garyjohn
fonte
E se eu quiser executar isso em todos os arquivos que estão abertos no momento, ou seja, eu executo: wa?
Flash17
Se os arquivos foram abertos com o tipo de arquivo correto, o FileTypeautocmd na resposta já teria configurado o segundo autocmd ( BufWritePre) para disparar quando você os salvar.
21415 VanLaser
1
O FileTypeautocmd acima será acionado para todos os arquivos abertos com o tipo de arquivo correto e configurará um evento local de buffer para cada um desses arquivos. Portanto, se você executar :wa, o vim executará eventos registrados para cada buffer, antes de salvar no arquivo.
21415 VanLaser
1
Portanto, se você abrir 5 arquivos Python, terá 5 autocmds em vez de um único, todos gravados . Então, se, digamos, três desses arquivos forem ocultados e exibidos novamente, forem FileTypeacionados novamente, você terá mais 3 autocmds, também na gravação. Isso é brilhante, eu me pergunto por que não criei esta solução. :)
lcd047 17/07/2015
1
O desempenho não é um problema. A execução da função stripTrailingWhiteSpaces()várias vezes no mesmo arquivo pode ter consequências indesejadas. Além disso, quanto mais autocmdvocê tiver para o mesmo evento para o mesmo arquivo, maior será a probabilidade de encontrar algumas condições de corrida. Tente pesquisar nos arquivos vim_dev para ter uma idéia. Então, novamente, o que eu sei, pode funcionar para você, certo?
Lcd047 17/07/2015
4

De maneira mais geral, se você não souber qual evento ocorrerá primeiro, poderá usar um auxiliar para rastrear quando cada um é acionado e apenas executar seu comando quando o último for acionado:

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
fonte