I have a BufWritePost autocmd that I want to run every time when a buffer is written but not when Vim is about to exit.

The variable v:dying does not really help as it only indicates if Vim exists due to a signal but I also want to detect normal shutdown. So I am looking for some thing along the lines of

au BufWritePost * if ! s:do_we_quit() | Neomake | endif

but as of now I have no idea how to write the s:do_we_quit() test.

Context: The autocmd just calls :Neomake to run syntax checks and linters on my files and load them into the quickfix/location list. But that does obviously only make sense on :w and not on :wq. Normally Neomake works asynchronously but on exit it seems to me that vim hangs and waits for Neomake and then somehow it ends up in an infinite loop.


You're looking for QuitPre:

let s:quitting = 0
autocmd QuitPre      * let s:quitting = 1
autocmd BufWritePost * if ! s:quitting | Neomake endif

This assumes you're running a decently recent Vim (QuitPre was added in Vim 7.3.544).

You should probably post a bug report about the infinite loop.

  • I was hoping for a less hancrafted version but I think it will do. – Lucas Feb 24 '17 at 15:58
  • @Lucas Not sure what you mean by "handcrafted". This is precisely the intended use of QuitPre. – Satō Katsura Feb 24 '17 at 16:20
  • I meant that the solution is dependent on my config (I have to set up the QuitPre autocmd). I was hoping for something like v:quitting analougus to v:dying and v:vim_did_enter which would make my BufWritePost autocmd only dependent on vim internals. Now I have to trust that QuitPre is triggered before Bufwritepost on :wq. I will accep the answer nontheless, also seeing that it is the best one available ;) – Lucas Feb 25 '17 at 16:36
  • Like I said, this is how you're supposed to do it. QuitPre is guaranteed to run before any BufWritePost. A hypothetical v:quitting would be useless for that purpose, since technically at that point Vim is not quitting yet. Yes, that isn't terribly coherent, but that's how Vim is. Which bit is useful for what is described in some detail in the manual, just not all in the same place, you have to hunt for it. – Satō Katsura Feb 26 '17 at 5:11
  • I came across a problem b/c s:quitting == 1 if I close one of several windows but then Neomake will not run on the next :w. More details in the answer below. – Lucas Feb 26 '17 at 8:50

Based on Sato's answer I came up with this:

let s:quitting = 0
autocmd BufWritePost *
    \ if ! s:quitting                             |
    \   Neomake                                   |
    \ elseif tabpagenr('$') > 1 || winnr('$') > 1 |
    \   let s:quitting = 0                        |
    \ endif
autocmd QuitPre * let s:quitting = 1
  • s:quitting has to be reset after closing a window, otherwise Neomake will not run on the next :w anywhere.
  • I can not check the window number in QuitPre as it could be anything if I :wqa
  • also I really don't want to run Neomake if I close a window as I might close all further windows shortly after (before Neomake is finished) and then Neovim will still hang

Update 1

NeoVim also provides v:exiting but that is not yet set at the time BufWritePost is triggered.

Update 2

Neomake now provides a command NeomakeCancelJobs so the original problem is solved by force canceling all running jobs in VimLeave:

augroup LucNeoMake
  autocmd BufWritePost * Neomake
  autocmd VimLeave * NeomakeCancelJobs
augroup END

(This is a solution to my original problem but not the the question.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.