]> granicus.if.org Git - vim/commitdiff
patch 8.0.1595: no autocommand triggered before exiting v8.0.1595
authorBram Moolenaar <Bram@vim.org>
Sun, 11 Mar 2018 13:44:18 +0000 (14:44 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 11 Mar 2018 13:44:18 +0000 (14:44 +0100)
Problem:    No autocommand triggered before exiting.
Solution:   Add the ExitPre autocommand event.

runtime/doc/autocmd.txt
src/Makefile
src/ex_docmd.c
src/fileio.c
src/testdir/Make_all.mak
src/testdir/test_exit.vim [new file with mode: 0644]
src/version.c
src/vim.h

index 7c547df2323e5fb30f6d7731d06a9bb2253f5eaf..e08a7cbba33e045409b8b2c134ebb9157fc923c4 100644 (file)
@@ -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
index 1b13aa94cff1edf5212e0eb1b05d35c4984f2819..905e3f1c5fbc3a31bc3e6d743f098579fac940ad 100644 (file)
@@ -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 \
index 9994cb64eabbb37edd8550e2460d0fa998843093..97bbd042918cc4cc9dde1d8e4c8ebe96386d133c 100644 (file)
@@ -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;
 
     /*
index 7149a227b88cb19c4f45c88362f366577a084135..8331c08ab313dbe0f0d83a5b45e523331194450e 100644 (file)
@@ -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},
index e3230c5540c4bc2a4b0a3dbbee45776f95a1c426..159bf1ece6ac1c0929f656b577ad647e2f3f3f31 100644 (file)
@@ -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 (file)
index 0000000..8f02fd2
--- /dev/null
@@ -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
index a6c7279c031d61ca81a66ca9d09ac5ecccb6356a..4f1c001193305b7db6201e90d7035c633cba7932 100644 (file)
@@ -766,6 +766,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1595,
 /**/
     1594,
 /**/
index 563d3281f9a153cae6edd54caf85866eadc10791..3b458a027e047e27aeaca01d734ebf4082372aaf 100644 (file)
--- 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 */