Có cách nào để VÀ các sự kiện trong autocmd không?


21

Tôi muốn kích hoạt một autocmd trong hai sự kiện nhưng không phải theo cách nó thường được thực hiện, tức là nếu một trong hai sự kiện xảy ra thì kích hoạt một sự kiện autocmd. Tôi muốn kích hoạt nó nếu cả hai sự kiện đã xảy ra.

Ví dụ:
Cách thông thường để làm điều đó

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

Mã này sẽ gọi StripTrailingWhiteSpaces () trên BufWrite hoặc BufRead

Tôi muốn làm một cái gì đó như:

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

Nói cách khác, kích hoạt một autcmdkhi filetype là một trong các c, cpp, python và ghi trên bộ đệm này xảy ra.

Bất kỳ trợ giúp được đánh giá cao.

Câu trả lời:


14

Lệnh autocommand được thực thi khi một sự kiện xảy ra. Bạn muốn một lệnh được thực thi sau khi một chuỗi các sự kiện đã xảy ra. Một cách để làm điều đó là như thế này:

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

Các <buffer>mô hình làm cho autocommand được được kích hoạt khi bộ đệm hiện nay được viết. Xem

:help autocmd-buflocal

Cập nhật

Giải pháp trên khá đơn giản và có một số sai sót đã được thảo luận trong phần Nhận xét. Đây là một giải pháp đầy đủ hơn để giải quyết một số sai sót. Nó đặt autocommands trong một nhóm và xóa autocommand BufWritePre, nếu có, trước khi tạo một cái mới. Nó vẫn tạo một autocommand cho mỗi bộ đệm, nhưng chỉ có một.

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

Một giải pháp khác, tương tự như câu trả lời được đăng bởi lcd047, hiện đã bị xóa, là nhận ra rằng khi sự kiện FileType xảy ra, tùy chọn 'filetype' được đặt. Sau đó, bạn có thể điều kiện phản hồi cho sự kiện BufWritePost về giá trị của 'filetype', như trong ví dụ sau. Nó có lợi thế hơn các giải pháp khác mà chỉ có một chế độ tự động được tạo.

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

Điều gì xảy ra nếu tôi muốn chạy cái này trên tất cả các tệp hiện đang mở, tức là tôi thực thi: wa?
flashburn

Nếu các tệp được mở với kiểu tệp chính xác, FileTypeautocmd trong câu trả lời sẽ thiết lập autocmd ( BufWritePre) thứ hai để kích hoạt khi bạn lưu chúng.
VanLaser

1
Các FileTypeautocmd trên ý chí lửa cho mỗi tập tin bạn mở ra với filetype chính xác, và sẽ thiết lập một bộ đệm cục bộ sự kiện cho mỗi của các tập tin. Vì vậy, nếu bạn chạy :wa, vim sẽ chạy các sự kiện đã đăng ký cho mỗi bộ đệm, trước khi lưu vào tệp.
VanLaser

1
Vì vậy, nếu bạn mở 5 tệp Python, bạn sẽ có 5 autocmdgiây thay vì một tệp duy nhất, tất cả đều được ghi. Sau đó, nếu, giả sử, 3 trong số các tệp này bị ẩn, sau đó được hiển thị lại, FileTypeđược kích hoạt lại để bạn có thêm 3 autocmdgiây, cũng được ghi. Điều này thật tuyệt vời, tôi tự hỏi tại sao tôi không nghĩ ra giải pháp này. :)
lcd047

1
Hiệu suất không phải là một vấn đề. Chạy chức năng stripTrailingWhiteSpaces()nhiều lần đối với cùng một tệp có thể có những hậu quả không lường trước được. Ngoài ra, bạn càng có nhiều autocmdsự kiện cho cùng một tệp cho cùng một tệp, bạn càng có nhiều khả năng gặp phải một số điều kiện thực sự của cuộc đua. Hãy thử tìm kiếm tài liệu lưu trữ vim_dev để có ý tưởng. Sau đó, một lần nữa, những gì tôi biết, nó có thể chỉ làm việc cho bạn, phải không?
lcd047

4

Tổng quát hơn, nếu bạn không biết sự kiện nào sẽ xảy ra trước, bạn có thể sử dụng trình trợ giúp để theo dõi khi mỗi người bắn và chỉ thực hiện lệnh của mình khi lần cuối cùng bắn:

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')
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.