diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/auevents.lua | 1 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 56 | ||||
-rw-r--r-- | src/nvim/testdir/test_exit.vim | 57 |
3 files changed, 95 insertions, 19 deletions
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index d0a3f38c6b..d002aaae43 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -34,6 +34,7 @@ return { 'CursorMovedI', -- cursor was moved in Insert mode 'DirChanged', -- directory changed 'EncodingChanged', -- after changing the 'encoding' option + 'ExitPre', -- before exiting 'FileAppendCmd', -- append to a file using command 'FileAppendPost', -- after appending to a file 'FileAppendPre', -- before appending to a file diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 71d411761b..0337b37cb2 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5964,9 +5964,35 @@ void not_exiting(void) exiting = FALSE; } -/* - * ":quit": quit current window, quit Vim if the last window is closed. - */ +static bool before_quit_autocmds(win_T *wp, bool quit_all, int forceit) +{ + apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, wp->w_buffer); + + // Bail out when autocommands closed the window. + // Refuse to quit when the buffer in the last window is being closed (can + // only happen in autocommands). + if (!win_valid(wp) + || curbuf_locked() + || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0)) { + return true; + } + + if (quit_all + || (check_more(false, forceit) == OK && only_one_window())) { + apply_autocmds(EVENT_EXITPRE, NULL, NULL, false, curbuf); + // Refuse to quit when locked or when the buffer in the last window is + // being closed (can only happen in autocommands). + if (curbuf_locked() + || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) { + return true; + } + } + + return false; +} + +// ":quit": quit current window, quit Vim if the last window is closed. +// ":{nr}quit": quit window {nr} static void ex_quit(exarg_T *eap) { if (cmdwin_type != 0) { @@ -5996,11 +6022,9 @@ static void ex_quit(exarg_T *eap) if (curbuf_locked()) { return; } - apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, wp->w_buffer); - // Refuse to quit when locked or when the buffer in the last window is - // being closed (can only happen in autocommands). - if (!win_valid(wp) - || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0)) { + + // Trigger QuitPre and maybe ExitPre + if (before_quit_autocmds(wp, false, eap->forceit)) { return; } @@ -6058,10 +6082,8 @@ static void ex_quit_all(exarg_T *eap) text_locked_msg(); return; } - apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf); - // Refuse to quit when locked or when the buffer in the last window is - // being closed (can only happen in autocommands). - if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) { + + if (before_quit_autocmds(curwin, true, eap->forceit)) { return; } @@ -6347,9 +6369,7 @@ static void ex_stop(exarg_T *eap) } } -/* - * ":exit", ":xit" and ":wq": Write file and exit Vim. - */ +// ":exit", ":xit" and ":wq": Write file and quite the current window. static void ex_exit(exarg_T *eap) { if (cmdwin_type != 0) { @@ -6361,10 +6381,8 @@ static void ex_exit(exarg_T *eap) text_locked_msg(); return; } - apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf); - // Refuse to quit when locked or when the buffer in the last window is - // being closed (can only happen in autocommands). - if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) { + + if (before_quit_autocmds(curwin, false, eap->forceit)) { return; } diff --git a/src/nvim/testdir/test_exit.vim b/src/nvim/testdir/test_exit.vim new file mode 100644 index 0000000000..8f02fd29e3 --- /dev/null +++ b/src/nvim/testdir/test_exit.vim @@ -0,0 +1,57 @@ +" Tests for exiting Vim. + +source shared.vim + +func Test_exiting() + let after = [ + \ 'au QuitPre * call writefile(["QuitPre"], "Xtestout")', + \ 'au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")', + \ 'quit', + \ ] + if RunVim([], after, '') + call assert_equal(['QuitPre', 'ExitPre'], readfile('Xtestout')) + endif + call delete('Xtestout') + + let after = [ + \ 'au QuitPre * call writefile(["QuitPre"], "Xtestout")', + \ 'au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")', + \ 'help', + \ 'wincmd w', + \ 'quit', + \ ] + if RunVim([], after, '') + call assert_equal(['QuitPre', 'ExitPre'], readfile('Xtestout')) + endif + call delete('Xtestout') + + let after = [ + \ 'au QuitPre * call writefile(["QuitPre"], "Xtestout")', + \ 'au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")', + \ 'split', + \ 'new', + \ 'qall', + \ ] + if RunVim([], after, '') + call assert_equal(['QuitPre', 'ExitPre'], readfile('Xtestout')) + endif + call delete('Xtestout') + + let after = [ + \ 'au QuitPre * call writefile(["QuitPre"], "Xtestout", "a")', + \ 'au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")', + \ 'augroup nasty', + \ ' au ExitPre * split', + \ 'augroup END', + \ 'quit', + \ 'augroup nasty', + \ ' au! ExitPre', + \ 'augroup END', + \ 'quit', + \ ] + if RunVim([], after, '') + call assert_equal(['QuitPre', 'ExitPre', 'QuitPre', 'ExitPre'], + \ readfile('Xtestout')) + endif + call delete('Xtestout') +endfunc |