summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-03-11 14:44:18 +0100
committerBram Moolenaar <Bram@vim.org>2018-03-11 14:44:18 +0100
commit12a96de430779b88795fac87a2be666d9f661d1e (patch)
tree141184af18ba4ae4f2c61dd1a2aa4961446ba370
parent435acdb88c849c6bac44ef30f24f29618b36af50 (diff)
downloadvim-git-12a96de430779b88795fac87a2be666d9f661d1e.tar.gz
patch 8.0.1595: no autocommand triggered before exitingv8.0.1595
Problem: No autocommand triggered before exiting. Solution: Add the ExitPre autocommand event.
-rw-r--r--runtime/doc/autocmd.txt9
-rw-r--r--src/Makefile1
-rw-r--r--src/ex_docmd.c50
-rw-r--r--src/fileio.c1
-rw-r--r--src/testdir/Make_all.mak1
-rw-r--r--src/testdir/test_exit.vim57
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h1
8 files changed, 106 insertions, 16 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 7c547df23..e08a7cbba 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -285,7 +285,8 @@ Name triggered by ~
|GUIFailed| after starting the GUI failed
|TermResponse| after the terminal response to |t_RV| is received
-|QuitPre| when using `:quit`, before deciding whether to quit
+|QuitPre| when using `:quit`, before deciding whether to exit
+|ExitPre| when using a command that may make Vim exit
|VimLeavePre| before exiting Vim, before writing the viminfo file
|VimLeave| before exiting Vim, after writing the viminfo file
@@ -651,6 +652,11 @@ DirChanged The working directory has changed in response
"auto" to trigger on 'autochdir'.
"drop" to trigger on editing a file
<afile> is set to the new directory name.
+ *ExitPre*
+ExitPre When using `:quit`, `:wq` in a way it makes
+ Vim exit, or using `:qall`, just after
+ |QuitPre|. Can be used to close any
+ non-essential window.
*FileChangedShell*
FileChangedShell When Vim notices that the modification time of
a file has changed since editing started.
@@ -866,6 +872,7 @@ QuitPre When using `:quit`, `:wq` or `:qall`, before
or quits Vim. Can be used to close any
non-essential window if the current window is
the last ordinary window.
+ Also see |ExitPre|.
*RemoteReply*
RemoteReply When a reply from a Vim that functions as
server was received |server2client()|. The
diff --git a/src/Makefile b/src/Makefile
index 1b13aa94c..905e3f1c5 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2155,6 +2155,7 @@ test_arglist \
test_eval_stuff \
test_ex_undo \
test_ex_z \
+ test_exit \
test_exec_while_if \
test_execute_func \
test_exists \
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 9994cb64e..97bbd0429 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -7187,8 +7187,35 @@ not_exiting(void)
settmode(TMODE_RAW);
}
+ static int
+before_quit_autocmds(win_T *wp, int 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)
@@ -7222,12 +7249,9 @@ ex_quit(exarg_T *eap)
/* Refuse to quit when locked. */
if (curbuf_locked())
return;
- 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)
- || (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;
#ifdef FEAT_NETBEANS_INTG
@@ -7301,10 +7325,8 @@ 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;
exiting = TRUE;
@@ -7743,7 +7765,7 @@ 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)
@@ -7761,10 +7783,8 @@ 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/fileio.c b/src/fileio.c
index 7149a227b..8331c08ab 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -7724,6 +7724,7 @@ static struct event_name
{"CursorMovedI", EVENT_CURSORMOVEDI},
{"DirChanged", EVENT_DIRCHANGED},
{"EncodingChanged", EVENT_ENCODINGCHANGED},
+ {"ExitPre", EVENT_EXITPRE},
{"FileEncoding", EVENT_ENCODINGCHANGED},
{"FileAppendPost", EVENT_FILEAPPENDPOST},
{"FileAppendPre", EVENT_FILEAPPENDPRE},
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index e3230c554..159bf1ece 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -97,6 +97,7 @@ NEW_TESTS = test_arabic.res \
test_exec_while_if.res \
test_exists.res \
test_exists_autocmd.res \
+ test_exit.res \
test_farsi.res \
test_file_size.res \
test_find_complete.res \
diff --git a/src/testdir/test_exit.vim b/src/testdir/test_exit.vim
new file mode 100644
index 000000000..8f02fd29e
--- /dev/null
+++ b/src/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
diff --git a/src/version.c b/src/version.c
index a6c7279c0..4f1c00119 100644
--- a/src/version.c
+++ b/src/version.c
@@ -767,6 +767,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1595,
+/**/
1594,
/**/
1593,
diff --git a/src/vim.h b/src/vim.h
index 563d3281f..3b458a027 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -1277,6 +1277,7 @@ enum auto_event
EVENT_COLORSCHEME, /* after loading a colorscheme */
EVENT_COMPLETEDONE, /* after finishing insert complete */
EVENT_DIRCHANGED, /* after changing directory as a result of user cmd */
+ EVENT_EXITPRE, /* before exiting */
EVENT_FILEAPPENDPOST, /* after appending to a file */
EVENT_FILEAPPENDPRE, /* before appending to a file */
EVENT_FILEAPPENDCMD, /* append to a file using command */