C'è un modo per gli eventi AND nell'autocmd?


21

Vorrei innescare un autocmd evento su due, ma non in un modo in cui di solito viene fatto, ovvero se uno degli eventi si è verificato, quindi innescare un autocmd. Voglio attivarlo se si verificano entrambi gli eventi.

Ad esempio:
il solito modo di farlo

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

Questo codice chiamerà StripTrailingWhiteSpaces () su BufWrite o BufRead

Vorrei fare qualcosa del tipo:

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

In altre parole, attiva un autcmdquando il tipo di file è uno di c, cpp, python e avviene la scrittura su questo buffer.

Qualsiasi aiuto è apprezzato.

Risposte:


14

Un comando autocommand viene eseguito quando si verifica un evento. Si desidera eseguire un comando dopo che si è verificata una sequenza di eventi. Un modo per farlo è così:

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

Il <buffer>modello provoca l'attivazione del comando automatico quando viene scritto il buffer corrente. Vedere

:help autocmd-buflocal

Aggiornare

La soluzione sopra è piuttosto semplice e presenta alcuni difetti che sono stati discussi nei commenti. Ecco una soluzione più completa che risolve alcuni di questi difetti. Inserisce i comandi automatici in un gruppo ed elimina il comando automatico BufWritePre, se presente, prima di crearne uno nuovo. Crea ancora un comando automatico per buffer, ma solo uno.

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

Un'altra soluzione, simile alla risposta pubblicata da lcd047, ora eliminata, è riconoscere che quando si verifica l'evento FileType, viene impostata l'opzione 'filetype'. Quindi puoi condizionare la risposta all'evento BufWritePost sul valore di 'filetype', come nell'esempio seguente. Ha il vantaggio rispetto alle altre soluzioni che viene creato un solo autocomando.

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

Cosa succede se voglio eseguirlo su tutti i file attualmente aperti, ovvero eseguo: wa?
flashburn

Se i file fossero stati aperti con il tipo di file corretto, FileTypeautocmd nella risposta avrebbe già impostato la seconda autocmd ( BufWritePre) in modo che si attivasse quando li si salva.
VanLaser,

1
L' FileTypeautocmd sopra verrà generato per ogni file aperto con il tipo di file corretto e imposterà un evento buffer-local per ciascuno di quei file. Quindi, se si esegue :wa, vim eseguirà gli eventi registrati per ciascun buffer, prima di salvare su file.
VanLaser,

1
Quindi se apri 5 file Python avrai 5 autocmds anziché uno singolo, tutto in scrittura. Quindi, se, diciamo, 3 di questi file vengono nascosti, quindi vengono mostrati di nuovo, FileTypeviene riattivato in modo da ottenere altri 3 autocmds, anche in scrittura. Questo è geniale, mi chiedo perché non ho trovato questa soluzione. :)
lcd047

1
Le prestazioni non sono un problema. L'esecuzione della funzione stripTrailingWhiteSpaces()più volte sullo stesso file potrebbe tuttavia avere conseguenze indesiderate. Inoltre, più autocmds hai per lo stesso evento per lo stesso file, più è probabile che ti imbatti in alcune condizioni di gara. Prova a cercare negli archivi vim_dev per avere un'idea. Poi di nuovo, che ne so, potrebbe funzionare solo per te, giusto?
lcd047,

4

Più in generale, se non sai quale evento accadrà per primo, puoi usare un aiutante per tracciare quando ognuno spara ed eseguire il tuo comando solo quando l'ultimo spara:

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')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.