vim-patch:8.0.1595: no autocommand triggered before exiting

Problem:    No autocommand triggered before exiting.
Solution:   Add the ExitPre autocommand event.
12a96de430
This commit is contained in:
Jan Edmund Lazo
2018-09-04 21:57:45 -04:00
parent b6e83ba284
commit 9584674569
4 changed files with 103 additions and 20 deletions

View File

@@ -274,7 +274,8 @@ Name triggered by ~
|GUIEnter| after starting the GUI successfully |GUIEnter| after starting the GUI successfully
|GUIFailed| after starting the GUI failed |GUIFailed| after starting the GUI failed
|TermResponse| after the terminal response to |t_RV| is received |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 Nvim, before writing the shada file |VimLeavePre| before exiting Nvim, before writing the shada file
|VimLeave| before exiting Nvim, after writing the shada file |VimLeave| before exiting Nvim, after writing the shada file
|VimResume| after Nvim is resumed |VimResume| after Nvim is resumed
@@ -646,6 +647,11 @@ FileChangedRO Before making the first change to a read-only
*E881* *E881*
If the number of lines changes saving for undo If the number of lines changes saving for undo
may fail and the change will be aborted. may fail and the change will be aborted.
*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*
FileChangedShell When Vim notices that the modification time of FileChangedShell When Vim notices that the modification time of
a file has changed since editing started. a file has changed since editing started.
@@ -862,6 +868,7 @@ QuitPre When using `:quit`, `:wq` or `:qall`, before
or quits Vim. Can be used to close any or quits Vim. Can be used to close any
non-essential window if the current window is non-essential window if the current window is
the last ordinary window. the last ordinary window.
Also see |ExitPre|.
*RemoteReply* *RemoteReply*
RemoteReply When a reply from a Vim that functions as RemoteReply When a reply from a Vim that functions as
server was received |server2client()|. The server was received |server2client()|. The

View File

@@ -34,6 +34,7 @@ return {
'CursorMovedI', -- cursor was moved in Insert mode 'CursorMovedI', -- cursor was moved in Insert mode
'DirChanged', -- directory changed 'DirChanged', -- directory changed
'EncodingChanged', -- after changing the 'encoding' option 'EncodingChanged', -- after changing the 'encoding' option
'ExitPre', -- before exiting
'FileAppendCmd', -- append to a file using command 'FileAppendCmd', -- append to a file using command
'FileAppendPost', -- after appending to a file 'FileAppendPost', -- after appending to a file
'FileAppendPre', -- before appending to a file 'FileAppendPre', -- before appending to a file

View File

@@ -5964,9 +5964,35 @@ void not_exiting(void)
exiting = FALSE; exiting = FALSE;
} }
/* static bool before_quit_autocmds(win_T *wp, bool quit_all, int forceit)
* ":quit": quit current window, quit Vim if the last window is closed. {
*/ 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) static void ex_quit(exarg_T *eap)
{ {
if (cmdwin_type != 0) { if (cmdwin_type != 0) {
@@ -5996,11 +6022,9 @@ static void ex_quit(exarg_T *eap)
if (curbuf_locked()) { if (curbuf_locked()) {
return; 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 // Trigger QuitPre and maybe ExitPre
// being closed (can only happen in autocommands). if (before_quit_autocmds(wp, false, eap->forceit)) {
if (!win_valid(wp)
|| (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0)) {
return; return;
} }
@@ -6058,10 +6082,8 @@ static void ex_quit_all(exarg_T *eap)
text_locked_msg(); text_locked_msg();
return; return;
} }
apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf);
// Refuse to quit when locked or when the buffer in the last window is if (before_quit_autocmds(curwin, true, eap->forceit)) {
// being closed (can only happen in autocommands).
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) {
return; return;
} }
@@ -6347,9 +6369,7 @@ static void ex_stop(exarg_T *eap)
} }
} }
/* // ":exit", ":xit" and ":wq": Write file and quite the current window.
* ":exit", ":xit" and ":wq": Write file and exit Vim.
*/
static void ex_exit(exarg_T *eap) static void ex_exit(exarg_T *eap)
{ {
if (cmdwin_type != 0) { if (cmdwin_type != 0) {
@@ -6361,10 +6381,8 @@ static void ex_exit(exarg_T *eap)
text_locked_msg(); text_locked_msg();
return; return;
} }
apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf);
// Refuse to quit when locked or when the buffer in the last window is if (before_quit_autocmds(curwin, false, eap->forceit)) {
// being closed (can only happen in autocommands).
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) {
return; return;
} }

View File

@@ -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