aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/auevents.lua1
-rw-r--r--src/nvim/ex_docmd.c56
-rw-r--r--src/nvim/testdir/test_exit.vim57
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