Patch 8.2.3591

6 views
Skip to first unread message

Bram Moolenaar

unread,
Nov 13, 2021, 7:39:18 AM11/13/21
to vim...@googlegroups.com

Patch 8.2.3591
Problem: No event is triggered when closing a window.
Solution: Add the WinClosed event. (Naohiro Ono, closes #9110)
Files: runtime/doc/autocmd.txt, src/autocmd.c,
src/testdir/test_autocmd.vim, src/vim.h, src/window.c


*** ../vim-8.2.3590/runtime/doc/autocmd.txt 2021-10-22 18:55:40.818752232 +0100
--- runtime/doc/autocmd.txt 2021-11-13 12:34:43.507586594 +0000
***************
*** 348,353 ****
--- 348,354 ----

|WinNew| after creating a new window
|TabNew| after creating a new tab page
+ |WinClosed| after closing a window
|TabClosed| after closing a tab page
|WinEnter| after entering another window
|WinLeave| before leaving a window
***************
*** 1276,1281 ****
--- 1281,1292 ----
VimSuspend When the Vim instance is suspended. Only when
CTRL-Z was typed inside Vim, not when the
SIGSTOP or SIGTSTP signal was sent to Vim.
+ *WinClosed*
+ WinClosed After closing a window. The pattern is
+ matched against the |window-ID|. Both
+ <amatch> and <afile> are set to the
+ |window-ID|. Non-recursive (event cannot
+ trigger itself).
*WinEnter*
WinEnter After entering another window. Not done for
the first window, when Vim has just started.
*** ../vim-8.2.3590/src/autocmd.c 2021-10-22 18:55:40.818752232 +0100
--- src/autocmd.c 2021-11-13 12:34:43.507586594 +0000
***************
*** 186,191 ****
--- 186,192 ----
{"VimLeave", EVENT_VIMLEAVE},
{"VimLeavePre", EVENT_VIMLEAVEPRE},
{"WinNew", EVENT_WINNEW},
+ {"WinClosed", EVENT_WINCLOSED},
{"WinEnter", EVENT_WINENTER},
{"WinLeave", EVENT_WINLEAVE},
{"VimResized", EVENT_VIMRESIZED},
***************
*** 2042,2048 ****
|| event == EVENT_OPTIONSET
|| event == EVENT_QUICKFIXCMDPOST
|| event == EVENT_DIRCHANGED
! || event == EVENT_MODECHANGED)
{
fname = vim_strsave(fname);
autocmd_fname_full = TRUE; // don't expand it later
--- 2043,2050 ----
|| event == EVENT_OPTIONSET
|| event == EVENT_QUICKFIXCMDPOST
|| event == EVENT_DIRCHANGED
! || event == EVENT_MODECHANGED
! || event == EVENT_WINCLOSED)
{
fname = vim_strsave(fname);
autocmd_fname_full = TRUE; // don't expand it later
*** ../vim-8.2.3590/src/testdir/test_autocmd.vim 2021-10-21 10:50:36.636964245 +0100
--- src/testdir/test_autocmd.vim 2021-11-13 12:34:43.507586594 +0000
***************
*** 270,275 ****
--- 270,276 ----

augroup testing
au WinNew * call add(g:record, 'WinNew')
+ au WinClosed * call add(g:record, 'WinClosed')
au WinEnter * call add(g:record, 'WinEnter')
au WinLeave * call add(g:record, 'WinLeave')
au TabNew * call add(g:record, 'TabNew')
***************
*** 286,293 ****
call assert_equal([
\ 'WinLeave', 'WinNew', 'WinEnter',
\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
! \ 'WinLeave', 'TabLeave', 'TabClosed', 'WinEnter', 'TabEnter',
! \ 'WinLeave', 'WinEnter'
\ ], g:record)

let g:record = []
--- 287,294 ----
call assert_equal([
\ 'WinLeave', 'WinNew', 'WinEnter',
\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
! \ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter',
! \ 'WinLeave', 'WinClosed', 'WinEnter'
\ ], g:record)

let g:record = []
***************
*** 298,304 ****
call assert_equal([
\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
! \ 'TabClosed'
\ ], g:record)

augroup testing
--- 299,305 ----
call assert_equal([
\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
! \ 'WinClosed', 'TabClosed'
\ ], g:record)

augroup testing
***************
*** 307,312 ****
--- 308,352 ----
unlet g:record
endfunc

+ func Test_WinClosed()
+ " Test that the pattern is matched against the closed window's ID, and both
+ " <amatch> and <afile> are set to it.
+ new
+ let winid = win_getid()
+ let g:matched = v:false
+ augroup test-WinClosed
+ autocmd!
+ execute 'autocmd WinClosed' winid 'let g:matched = v:true'
+ autocmd WinClosed * let g:amatch = str2nr(expand('<amatch>'))
+ autocmd WinClosed * let g:afile = str2nr(expand('<afile>'))
+ augroup END
+ close
+ call assert_true(g:matched)
+ call assert_equal(winid, g:amatch)
+ call assert_equal(winid, g:afile)
+
+ " Test that WinClosed is non-recursive.
+ new
+ new
+ call assert_equal(3, winnr('$'))
+ let g:triggered = 0
+ augroup test-WinClosed
+ autocmd!
+ autocmd WinClosed * let g:triggered += 1
+ autocmd WinClosed * 2 wincmd c
+ augroup END
+ close
+ call assert_equal(1, winnr('$'))
+ call assert_equal(1, g:triggered)
+
+ autocmd! test-WinClosed
+ augroup! test-WinClosed
+ unlet g:matched
+ unlet g:amatch
+ unlet g:afile
+ unlet g:triggered
+ endfunc
+
func s:AddAnAutocmd()
augroup vimBarTest
au BufReadCmd * echo 'hello'
*** ../vim-8.2.3590/src/vim.h 2021-11-02 21:39:40.097064632 +0000
--- src/vim.h 2021-11-13 12:34:43.507586594 +0000
***************
*** 1379,1384 ****
--- 1379,1385 ----
EVENT_WINENTER, // after entering a window
EVENT_WINLEAVE, // before leaving a window
EVENT_WINNEW, // when entering a new window
+ EVENT_WINCLOSED, // after closing a window
EVENT_VIMSUSPEND, // before Vim is suspended
EVENT_VIMRESUME, // after Vim is resumed

*** ../vim-8.2.3590/src/window.c 2021-11-02 20:56:04.189640051 +0000
--- src/window.c 2021-11-13 12:34:43.511586582 +0000
***************
*** 19,24 ****
--- 19,25 ----
static void win_rotate(int, int);
static void win_totop(int size, int flags);
static void win_equal_rec(win_T *next_curwin, int current, frame_T *topfr, int dir, int col, int row, int width, int height);
+ static void trigger_winclosed(win_T *win);
static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp);
static frame_T *win_altframe(win_T *win, tabpage_T *tp);
static tabpage_T *alt_tabpage(void);
***************
*** 2566,2571 ****
--- 2567,2579 ----
if (popup_win_closed(win) && !win_valid(win))
return FAIL;
#endif
+
+ // Trigger WinClosed just before starting to free window-related resources.
+ trigger_winclosed(win);
+ // autocmd may have freed the window already.
+ if (!win_valid_any_tab(win))
+ return OK;
+
win_close_buffer(win, free_buf ? DOBUF_UNLOAD : 0, TRUE);

if (only_one_window() && win_valid(win) && win->w_buffer == NULL
***************
*** 2710,2715 ****
--- 2718,2737 ----
return OK;
}

+ static void
+ trigger_winclosed(win_T *win)
+ {
+ static int recursive = FALSE;
+ char_u winid[NUMBUFLEN];
+
+ if (recursive)
+ return;
+ recursive = TRUE;
+ vim_snprintf((char *)winid, sizeof(winid), "%i", win->w_id);
+ apply_autocmds(EVENT_WINCLOSED, winid, winid, FALSE, win->w_buffer);
+ recursive = FALSE;
+ }
+
/*
* Close window "win" in tab page "tp", which is not the current tab page.
* This may be the last window in that tab page and result in closing the tab,
***************
*** 2731,2736 ****
--- 2753,2764 ----
&& win->w_buffer->b_locked > 0))
return; // window is already being closed

+ // Trigger WinClosed just before starting to free window-related resources.
+ trigger_winclosed(win);
+ // autocmd may have freed the window already.
+ if (!win_valid_any_tab(win))
+ return;
+
if (win->w_buffer != NULL)
// Close the link to the buffer.
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0,
*** ../vim-8.2.3590/src/version.c 2021-11-13 10:49:26.833952428 +0000
--- src/version.c 2021-11-13 12:36:17.439292966 +0000
***************
*** 759,760 ****
--- 759,762 ----
{ /* Add new patch number below this line */
+ /**/
+ 3591,
/**/

--
Computers are not intelligent. They only think they are.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages