I'm trying to create a commit buffer: write text, save to commit, show errors in new buffer on failure.


I'm having trouble with the last step.

I figured I'd use bufhidden=wipe and BufDelete so the user can save and close the file and then my command is executed. However, sometimes the failures are verbose and I need somewhere to show the output.

:help BufDelete warns:

Don't change to another buffer, it will cause problems.

Seems like I cannot create a buffer and switch back:

" ~/.vim/buftest.vim
setlocal bufhidden=wipe
augroup buftest
    au buftest BufDelete <buffer> new | wincmd p
augroup END
" List our active autocmd
au * <buffer>

edit ~/smell and source ~/.vim/buftest.vim. Then ZZ to save and close which wipes the file and invokes BufDelete. I get error:

|| Error detected while processing BufDelete Autocommands for "<buffer=220>":
|| E937: Attempt to delete a buffer that is in use: smell

Maybe I need to use an autocmd that doesn't warn about changing buffers?

I tried this variant using BufWinLeave, but I can't delete the original commit buffer without getting errors:

" ~/.vim/buftest.vim
function! Cmd(msg_buf)
    " Since the buffer sticks around, don't execute anything next time we
    " close it.
    au! buftest * <buffer>

    " Always cause error for testing.
    "~ let r = system('svn status ~/code/svntest/checkout/') " succeeds
    let r = system('svn status ~') " fails
    if r =~# '\v^svn: (warning|error)'
        " Make scratch buffer
        setlocal buftype=nofile bufhidden=hide noswapfile buflisted
        0put =r
        " Work is done, want to remove the message buffer.

        " Uncommenting causes E937: Attempt to delete a buffer that is in use: smell
        "~ execute a:msg_buf ..'bwipe'
        " Doesn't delete buffer until it's viewed and closed again.
        call setbufvar(str2nr(a:msg_buf), '&bufhidden', 'wipe')
        " I guess unlist it so it doesn't clutter up?
        call setbufvar(str2nr(a:msg_buf), '&buflisted', 0)

augroup buftest
    au BufWinLeave <buffer> call Cmd(expand('<abuf>'))
augroup END

au * <buffer>
  • 1
    I dont know if fugitive’s commit or status buffer are relevant (ie do similar things), but you might take a look at that code – D. Ben Knoble Mar 2 at 14:52
  • @D.BenKnoble: fugitive's commit buffer is the behaviour I'm after. Unfortunately I have a hard time understanding tpope's code. The commit buffer has no buffer-local autocmd. I think it might be s:RunBufDelete and :checktime, but I don't understand how fugitive is invoked after bdelete completes. Besides, I've never seen a big error pop up from git or fugitive whereas svn errors are enormous. Likely, fugitive just :echomsgs errors. – idbrii Mar 2 at 21:04
  • I wonder if you have to fill the buffer contents and set variables, and only later (via feedkeys) open the split? Or perhaps you can do the whole thing with feedkeys. The effect would be that the buffer changing happens after the delete is finished, so you are no longer restricted, but you’ve programmed the response during the event as desired. – D. Ben Knoble Mar 2 at 23:27

Your Answer

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

Browse other questions tagged or ask your own question.