mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 11:15:14 -07:00
Merge #5918 'vim-patch: 7.4.2006, 7.4.2075, 7.4.2077, 7.4.2117, 7.4.2300, 7.4.2313, 7.4.2314'.
This commit is contained in:
commit
3ba5e43d2e
@ -294,6 +294,7 @@ Name triggered by ~
|
||||
|CursorMoved| the cursor was moved in Normal mode
|
||||
|CursorMovedI| the cursor was moved in Insert mode
|
||||
|
||||
|WinNew| after creating a new window
|
||||
|WinEnter| after entering another window
|
||||
|WinLeave| before leaving a window
|
||||
|TabEnter| after entering another tab page
|
||||
@ -992,6 +993,11 @@ WinLeave Before leaving a window. If the window to be
|
||||
WinLeave autocommands (but not for ":new").
|
||||
Not used for ":qa" or ":q" when exiting Vim.
|
||||
|
||||
*WinNew*
|
||||
WinNew When a new window was created. Not done for
|
||||
the fist window, when Vim has just started.
|
||||
Before a WinEnter event.
|
||||
|
||||
==============================================================================
|
||||
6. Patterns *autocmd-patterns* *{pat}*
|
||||
|
||||
|
@ -89,6 +89,7 @@ return {
|
||||
'VimLeave', -- before exiting Vim
|
||||
'VimLeavePre', -- before exiting Vim and writing ShaDa file
|
||||
'VimResized', -- after Vim window was resized
|
||||
'WinNew', -- when entering a new window
|
||||
'WinEnter', -- after entering a window
|
||||
'WinLeave', -- before leaving a window
|
||||
},
|
||||
|
@ -409,9 +409,6 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last)
|
||||
buf->b_nwindows = nwindows;
|
||||
|
||||
buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0));
|
||||
if (win_valid_any_tab(win) && win->w_buffer == buf) {
|
||||
win->w_buffer = NULL; // make sure we don't use the buffer now
|
||||
}
|
||||
|
||||
/* Autocommands may have deleted the buffer. */
|
||||
if (!buf_valid(buf))
|
||||
@ -419,11 +416,6 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last)
|
||||
if (aborting()) /* autocmds may abort script processing */
|
||||
return;
|
||||
|
||||
/* Autocommands may have opened or closed windows for this buffer.
|
||||
* Decrement the count for the close we do here. */
|
||||
if (buf->b_nwindows > 0)
|
||||
--buf->b_nwindows;
|
||||
|
||||
/*
|
||||
* It's possible that autocommands change curbuf to the one being deleted.
|
||||
* This might cause the previous curbuf to be deleted unexpectedly. But
|
||||
@ -434,6 +426,16 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last)
|
||||
if (buf == curbuf && !is_curbuf)
|
||||
return;
|
||||
|
||||
if (win_valid_any_tab(win) && win->w_buffer == buf) {
|
||||
win->w_buffer = NULL; // make sure we don't use the buffer now
|
||||
}
|
||||
|
||||
// Autocommands may have opened or closed windows for this buffer.
|
||||
// Decrement the count for the close we do here.
|
||||
if (buf->b_nwindows > 0) {
|
||||
buf->b_nwindows--;
|
||||
}
|
||||
|
||||
/* Change directories when the 'acd' option is set. */
|
||||
do_autochdir();
|
||||
|
||||
|
@ -5373,6 +5373,8 @@ static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
|
||||
*/
|
||||
static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
|
||||
#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
|
||||
// use get_deleted_augroup() to get this
|
||||
static char_u *deleted_augroup = NULL;
|
||||
|
||||
/*
|
||||
* The ID of the current group. Group 0 is the default one.
|
||||
@ -5387,6 +5389,14 @@ static event_T last_event;
|
||||
static int last_group;
|
||||
static int autocmd_blocked = 0; /* block all autocmds */
|
||||
|
||||
static char_u *get_deleted_augroup(void)
|
||||
{
|
||||
if (deleted_augroup == NULL) {
|
||||
deleted_augroup = (char_u *)_("--Deleted--");
|
||||
}
|
||||
return deleted_augroup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Show the autocommands for one AutoPat.
|
||||
*/
|
||||
@ -5406,10 +5416,11 @@ static void show_autocmd(AutoPat *ap, event_T event)
|
||||
return;
|
||||
if (event != last_event || ap->group != last_group) {
|
||||
if (ap->group != AUGROUP_DEFAULT) {
|
||||
if (AUGROUP_NAME(ap->group) == NULL)
|
||||
msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
|
||||
else
|
||||
if (AUGROUP_NAME(ap->group) == NULL) {
|
||||
msg_puts_attr(get_deleted_augroup(), hl_attr(HLF_E));
|
||||
} else {
|
||||
msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
|
||||
}
|
||||
msg_puts((char_u *)" ");
|
||||
}
|
||||
msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
|
||||
@ -5575,11 +5586,33 @@ static void au_del_group(char_u *name)
|
||||
int i;
|
||||
|
||||
i = au_find_group(name);
|
||||
if (i == AUGROUP_ERROR) /* the group doesn't exist */
|
||||
if (i == AUGROUP_ERROR) { // the group doesn't exist
|
||||
EMSG2(_("E367: No such group: \"%s\""), name);
|
||||
else {
|
||||
} else if (i == current_augroup) {
|
||||
EMSG(_("E936: Cannot delete the current group"));
|
||||
} else {
|
||||
event_T event;
|
||||
AutoPat *ap;
|
||||
int in_use = false;
|
||||
|
||||
for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
|
||||
event = (event_T)((int)event + 1)) {
|
||||
for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
|
||||
if (ap->group == i && ap->pat != NULL) {
|
||||
give_warning((char_u *)
|
||||
_("W19: Deleting augroup that is still in use"), true);
|
||||
in_use = true;
|
||||
event = NUM_EVENTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
xfree(AUGROUP_NAME(i));
|
||||
AUGROUP_NAME(i) = NULL;
|
||||
if (in_use) {
|
||||
AUGROUP_NAME(i) = get_deleted_augroup();
|
||||
} else {
|
||||
AUGROUP_NAME(i) = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5591,8 +5624,9 @@ static void au_del_group(char_u *name)
|
||||
static int au_find_group(const char_u *name)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
for (int i = 0; i < augroups.ga_len; ++i) {
|
||||
if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0) {
|
||||
for (int i = 0; i < augroups.ga_len; i++) {
|
||||
if (AUGROUP_NAME(i) != NULL && AUGROUP_NAME(i) != get_deleted_augroup()
|
||||
&& STRCMP(AUGROUP_NAME(i), name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -5640,10 +5674,21 @@ void do_augroup(char_u *arg, int del_group)
|
||||
#if defined(EXITFREE)
|
||||
void free_all_autocmds(void)
|
||||
{
|
||||
int i;
|
||||
char_u *s;
|
||||
|
||||
for (current_augroup = -1; current_augroup < augroups.ga_len;
|
||||
++current_augroup)
|
||||
do_autocmd((char_u *)"", TRUE);
|
||||
ga_clear_strings(&augroups);
|
||||
current_augroup++) {
|
||||
do_autocmd((char_u *)"", true);
|
||||
}
|
||||
|
||||
for (i = 0; i < augroups.ga_len; i++) {
|
||||
s = ((char_u **)(augroups.ga_data))[i];
|
||||
if (s != get_deleted_augroup()) {
|
||||
xfree(s);
|
||||
}
|
||||
}
|
||||
ga_clear(&augroups);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -7105,9 +7150,11 @@ char_u *get_augroup_name(expand_T *xp, int idx)
|
||||
return (char_u *)"END";
|
||||
if (idx >= augroups.ga_len) /* end of list */
|
||||
return NULL;
|
||||
if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
|
||||
if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup()) {
|
||||
// skip deleted entries
|
||||
return (char_u *)"";
|
||||
return AUGROUP_NAME(idx); /* return a name */
|
||||
}
|
||||
return AUGROUP_NAME(idx); // return a name
|
||||
}
|
||||
|
||||
static int include_groups = FALSE;
|
||||
@ -7164,10 +7211,12 @@ set_context_in_autocmd (
|
||||
*/
|
||||
char_u *get_event_name(expand_T *xp, int idx)
|
||||
{
|
||||
if (idx < augroups.ga_len) { /* First list group names, if wanted */
|
||||
if (!include_groups || AUGROUP_NAME(idx) == NULL)
|
||||
return (char_u *)""; /* skip deleted entries */
|
||||
return AUGROUP_NAME(idx); /* return a name */
|
||||
if (idx < augroups.ga_len) { // First list group names, if wanted
|
||||
if (!include_groups || AUGROUP_NAME(idx) == NULL
|
||||
|| AUGROUP_NAME(idx) == get_deleted_augroup()) {
|
||||
return (char_u *)""; // skip deleted entries
|
||||
}
|
||||
return AUGROUP_NAME(idx); // return a name
|
||||
}
|
||||
return (char_u *)event_names[idx - augroups.ga_len].name;
|
||||
}
|
||||
|
@ -64,6 +64,66 @@ function Test_bufunload()
|
||||
augroup! test_bufunload_group
|
||||
endfunc
|
||||
|
||||
" SEGV occurs in older versions. (At least 7.4.2005 or older)
|
||||
function Test_autocmd_bufunload_with_tabnext()
|
||||
tabedit
|
||||
tabfirst
|
||||
|
||||
augroup test_autocmd_bufunload_with_tabnext_group
|
||||
autocmd!
|
||||
autocmd BufUnload <buffer> tabnext
|
||||
augroup END
|
||||
|
||||
quit
|
||||
call assert_equal(2, tabpagenr('$'))
|
||||
|
||||
augroup! test_autocmd_bufunload_with_tabnext_group
|
||||
tablast
|
||||
quit
|
||||
endfunc
|
||||
|
||||
func Test_win_tab_autocmd()
|
||||
let g:record = []
|
||||
|
||||
augroup testing
|
||||
au WinNew * call add(g:record, 'WinNew')
|
||||
au WinEnter * call add(g:record, 'WinEnter')
|
||||
au WinLeave * call add(g:record, 'WinLeave')
|
||||
au TabNew * call add(g:record, 'TabNew')
|
||||
au TabClosed * call add(g:record, 'TabClosed')
|
||||
au TabEnter * call add(g:record, 'TabEnter')
|
||||
au TabLeave * call add(g:record, 'TabLeave')
|
||||
augroup END
|
||||
|
||||
split
|
||||
tabnew
|
||||
close
|
||||
close
|
||||
|
||||
call assert_equal([
|
||||
\ 'WinLeave', 'WinNew', 'WinEnter',
|
||||
\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
|
||||
\ 'WinLeave', 'TabLeave', 'TabClosed', 'WinEnter', 'TabEnter',
|
||||
\ 'WinLeave', 'WinEnter'
|
||||
\ ], g:record)
|
||||
|
||||
let g:record = []
|
||||
tabnew somefile
|
||||
tabnext
|
||||
bwipe somefile
|
||||
|
||||
call assert_equal([
|
||||
\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
|
||||
\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
|
||||
\ 'TabClosed'
|
||||
\ ], g:record)
|
||||
|
||||
augroup testing
|
||||
au!
|
||||
augroup END
|
||||
unlet g:record
|
||||
endfunc
|
||||
|
||||
func s:AddAnAutocmd()
|
||||
augroup vimBarTest
|
||||
au BufReadCmd * echo 'hello'
|
||||
@ -91,3 +151,48 @@ func Test_early_bar()
|
||||
au! vimBarTest|echo 'hello'
|
||||
call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
|
||||
endfunc
|
||||
|
||||
func RemoveGroup()
|
||||
autocmd! StartOK
|
||||
augroup! StartOK
|
||||
endfunc
|
||||
|
||||
func Test_augroup_warning()
|
||||
augroup TheWarning
|
||||
au VimEnter * echo 'entering'
|
||||
augroup END
|
||||
call assert_true(match(execute('au VimEnter'), "TheWarning.*VimEnter") >= 0)
|
||||
redir => res
|
||||
augroup! TheWarning
|
||||
redir END
|
||||
call assert_true(match(res, "W19:") >= 0)
|
||||
call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
|
||||
|
||||
" check "Another" does not take the pace of the deleted entry
|
||||
augroup Another
|
||||
augroup END
|
||||
call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
|
||||
|
||||
" no warning for postpone aucmd delete
|
||||
augroup StartOK
|
||||
au VimEnter * call RemoveGroup()
|
||||
augroup END
|
||||
call assert_true(match(execute('au VimEnter'), "StartOK.*VimEnter") >= 0)
|
||||
redir => res
|
||||
doautocmd VimEnter
|
||||
redir END
|
||||
call assert_true(match(res, "W19:") < 0)
|
||||
au! VimEnter
|
||||
endfunc
|
||||
|
||||
func Test_augroup_deleted()
|
||||
" This caused a crash before E936 was introduced
|
||||
augroup x
|
||||
call assert_fails('augroup! x', 'E936:')
|
||||
au VimEnter * echo
|
||||
augroup end
|
||||
augroup! x
|
||||
call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
|
||||
au! VimEnter
|
||||
endfunc
|
||||
|
||||
|
@ -126,8 +126,8 @@ static int included_patches[] = {
|
||||
// 2317,
|
||||
// 2316 NA
|
||||
// 2315,
|
||||
// 2314,
|
||||
// 2313,
|
||||
2314,
|
||||
2313,
|
||||
2312,
|
||||
// 2311 NA
|
||||
// 2310 NA
|
||||
@ -140,7 +140,7 @@ static int included_patches[] = {
|
||||
// 2303,
|
||||
// 2302 NA
|
||||
// 2301 NA
|
||||
// 2300,
|
||||
2300,
|
||||
// 2299,
|
||||
// 2298 NA
|
||||
// 2297 NA
|
||||
@ -323,7 +323,7 @@ static int included_patches[] = {
|
||||
// 2120,
|
||||
// 2119,
|
||||
// 2118 NA
|
||||
// 2117,
|
||||
2117,
|
||||
// 2116 NA
|
||||
// 2115 NA
|
||||
// 2114 NA
|
||||
@ -363,9 +363,9 @@ static int included_patches[] = {
|
||||
// 2080,
|
||||
// 2079 NA
|
||||
// 2078 NA
|
||||
// 2077,
|
||||
2077,
|
||||
// 2076,
|
||||
// 2075,
|
||||
2075,
|
||||
// 2074,
|
||||
// 2073 NA
|
||||
// 2072,
|
||||
@ -434,7 +434,7 @@ static int included_patches[] = {
|
||||
2009,
|
||||
2008,
|
||||
2007,
|
||||
// 2006,
|
||||
2006,
|
||||
2005,
|
||||
// 2004 NA
|
||||
// 2003 NA
|
||||
|
@ -973,11 +973,12 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
/*
|
||||
* make the new window the current window
|
||||
*/
|
||||
win_enter(wp, false);
|
||||
if (flags & WSP_VERT)
|
||||
win_enter_ext(wp, false, false, true, true, true);
|
||||
if (flags & WSP_VERT) {
|
||||
p_wiw = i;
|
||||
else
|
||||
} else {
|
||||
p_wh = i;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -1718,6 +1719,7 @@ close_windows (
|
||||
{
|
||||
tabpage_T *tp, *nexttp;
|
||||
int h = tabline_height();
|
||||
int count = tabpage_index(NULL);
|
||||
|
||||
++RedrawingDisabled;
|
||||
|
||||
@ -1754,9 +1756,14 @@ close_windows (
|
||||
|
||||
--RedrawingDisabled;
|
||||
|
||||
redraw_tabline = TRUE;
|
||||
if (h != tabline_height())
|
||||
if (count != tabpage_index(NULL)) {
|
||||
apply_autocmds(EVENT_TABCLOSED, NULL, NULL, false, curbuf);
|
||||
}
|
||||
|
||||
redraw_tabline = true;
|
||||
if (h != tabline_height()) {
|
||||
shell_new_rows();
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that current window is the last one.
|
||||
@ -2014,10 +2021,11 @@ int win_close(win_T *win, int free_buf)
|
||||
}
|
||||
|
||||
if (close_curwin) {
|
||||
win_enter_ext(wp, false, TRUE, TRUE, TRUE);
|
||||
if (other_buffer)
|
||||
/* careful: after this wp and win may be invalid! */
|
||||
apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
|
||||
win_enter_ext(wp, false, true, false, true, true);
|
||||
if (other_buffer) {
|
||||
// careful: after this wp and win may be invalid!
|
||||
apply_autocmds(EVENT_BUFENTER, NULL, NULL, false, curbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3045,8 +3053,9 @@ int win_new_tabpage(int after, char_u *filename)
|
||||
|
||||
redraw_all_later(CLEAR);
|
||||
|
||||
apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf);
|
||||
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
|
||||
apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
|
||||
apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf);
|
||||
apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf);
|
||||
|
||||
return OK;
|
||||
@ -3204,8 +3213,8 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au
|
||||
/* We would like doing the TabEnter event first, but we don't have a
|
||||
* valid current window yet, which may break some commands.
|
||||
* This triggers autocommands, thus may make "tp" invalid. */
|
||||
win_enter_ext(tp->tp_curwin, false, TRUE,
|
||||
trigger_enter_autocmds, trigger_leave_autocmds);
|
||||
win_enter_ext(tp->tp_curwin, false, true, false,
|
||||
trigger_enter_autocmds, trigger_leave_autocmds);
|
||||
prevwin = next_prevwin;
|
||||
|
||||
last_status(FALSE); /* status line may appear or disappear */
|
||||
@ -3546,7 +3555,7 @@ end:
|
||||
*/
|
||||
void win_enter(win_T *wp, bool undo_sync)
|
||||
{
|
||||
win_enter_ext(wp, undo_sync, FALSE, TRUE, TRUE);
|
||||
win_enter_ext(wp, undo_sync, false, false, true, true);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3554,7 +3563,9 @@ void win_enter(win_T *wp, bool undo_sync)
|
||||
* Can be called with "curwin_invalid" TRUE, which means that curwin has just
|
||||
* been closed and isn't valid.
|
||||
*/
|
||||
static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, int trigger_enter_autocmds, int trigger_leave_autocmds)
|
||||
static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
|
||||
int trigger_new_autocmds, int trigger_enter_autocmds,
|
||||
int trigger_leave_autocmds)
|
||||
{
|
||||
int other_buffer = FALSE;
|
||||
|
||||
@ -3630,6 +3641,9 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, int tri
|
||||
shorten_fnames(TRUE);
|
||||
}
|
||||
|
||||
if (trigger_new_autocmds) {
|
||||
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
|
||||
}
|
||||
if (trigger_enter_autocmds) {
|
||||
apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
|
||||
if (other_buffer)
|
||||
|
@ -12,8 +12,8 @@ describe('autocmds:', function()
|
||||
local expected = {
|
||||
'WinLeave',
|
||||
'TabLeave',
|
||||
'TabNew',
|
||||
'WinEnter',
|
||||
'TabNew',
|
||||
'TabEnter',
|
||||
'BufLeave',
|
||||
'BufEnter'
|
||||
|
Loading…
Reference in New Issue
Block a user