Skip to content

Commit

Permalink
patch 8.0.1595: no autocommand triggered before exiting
Browse files Browse the repository at this point in the history
Problem:    No autocommand triggered before exiting.
Solution:   Add the ExitPre autocommand event.
  • Loading branch information
brammool committed Mar 11, 2018
1 parent 435acdb commit 12a96de
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 16 deletions.
9 changes: 8 additions & 1 deletion runtime/doc/autocmd.txt
Expand Up @@ -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

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/Makefile
Expand Up @@ -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 \
Expand Down
50 changes: 35 additions & 15 deletions src/ex_docmd.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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;

/*
Expand Down
1 change: 1 addition & 0 deletions src/fileio.c
Expand Up @@ -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},
Expand Down
1 change: 1 addition & 0 deletions src/testdir/Make_all.mak
Expand Up @@ -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 \
Expand Down
57 changes: 57 additions & 0 deletions 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
2 changes: 2 additions & 0 deletions src/version.c
Expand Up @@ -766,6 +766,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1595,
/**/
1594,
/**/
Expand Down
1 change: 1 addition & 0 deletions src/vim.h
Expand Up @@ -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 */
Expand Down

0 comments on commit 12a96de

Please sign in to comment.