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 -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20211113123912.8DA2B1C5232%40moolenaar.net.

Raspunde prin e-mail lui