]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1211: TabClosedPre is triggered just before the tab is being freed v9.1.1211
authorJim Zhou <jimzhouzzy@gmail.com>
Sun, 16 Mar 2025 19:24:57 +0000 (20:24 +0100)
committerChristian Brabandt <cb@256bit.org>
Sun, 16 Mar 2025 19:24:57 +0000 (20:24 +0100)
Problem:  TabClosedPre is triggered just before the tab is being freed,
          which limited its functionality.
Solution: Trigger it a bit earlier and also on :tabclose and :tabonly
          (Jim Zhou)

closes: #16890

Signed-off-by: Jim Zhou <jimzhouzzy@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/ex_docmd.c
src/proto/window.pro
src/testdir/test_autocmd.vim
src/version.c
src/window.c

index 44388349043567c8398337fa9a586d9f2e152bfb..80ec8a1a6fd7a1cf18361aa5d4cb83aa1cb69802 100644 (file)
@@ -6536,6 +6536,8 @@ tabpage_close(int forceit)
     if (window_layout_locked(CMD_tabclose))
        return;
 
+    trigger_tabclosedpre(curtab, TRUE);
+
     // First close all the windows but the current one.  If that worked then
     // close the last window in this tab, that will close it.
     if (!ONE_WINDOW)
@@ -6559,6 +6561,8 @@ tabpage_close_other(tabpage_T *tp, int forceit)
     int                done = 0;
     win_T      *wp;
 
+    trigger_tabclosedpre(tp, TRUE);
+
     // Limit to 1000 windows, autocommands may add a window while we close
     // one.  OK, so I'm paranoid...
     while (++done < 1000)
index 9a2661d96eff5292f45ec820dfb592d94f8c3930..f1e129d6e9d6ab2915c3d3b48c88b66154e1ebe3 100644 (file)
@@ -102,4 +102,5 @@ int get_tab_number(tabpage_T *tp);
 char *check_colorcolumn(char_u *cc, win_T *wp);
 int get_last_winid(void);
 int win_locked(win_T *wp);
+void trigger_tabclosedpre(tabpage_T *tp, int directly);
 /* vim: set ft=c : */
index 138b852f095e8d882cfc77c2ab4e1b8f0bf66e59..2519e60a179a087811e6c4f9df9e76e37c57eee1 100644 (file)
@@ -5109,7 +5109,7 @@ func Test_autocmd_tabclosedpre()
   call ClearAutomcdAndCreateTabs()
   au TabClosedPre * tabmove 0
   tabclose
-  call assert_equal('1Z2A3>B', GetTabs())
+  call assert_equal('1>Z2A3B', GetTabs())
   call ClearAutomcdAndCreateTabs()
   au TabClosedPre * tabmove 0
   tabclose 1
@@ -5137,7 +5137,33 @@ func Test_autocmd_tabclosedpre()
   au TabClosedPre * new X | new Y | new Z
   call assert_fails('tabclose 1', 'E242')
 
+  " Test directly closing the tab page with ':tabclose'
+  au!
+  tabonly
+  bw!
+  e Z
+  au TabClosedPre * mksession!
+  tabnew A
+  sp
+  tabclose
+  source Session.vim
+  call assert_equal('1Z2>AA', GetTabs())
+
+  " Test directly closing the tab page with ':tabonly'
+  " Z is closed before A. Hence A overwrites the session.
+  au!
+  tabonly
+  bw!
+  e Z
+  au TabClosedPre * mksession!
+  tabnew A
+  tabnew B
+  tabonly
+  source Session.vim
+  call assert_equal('1>A2B', GetTabs())
+
   " Clean up
+  call delete('Session.vim')
   au!
   only
   tabonly
index d293eba6aabce094da2814f1a695f18e28945e5b..812941804560ac81a469c686257c458048069b23 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1211,
 /**/
     1210,
 /**/
index cce7f4c797a85d13f9f933c402ddb2d2432888ec..55168d53fe8831fc15f7a4896f86dbc797b29fdb 100644 (file)
@@ -2978,10 +2978,15 @@ trigger_winclosed(win_T *win)
     recursive = FALSE;
 }
 
-    static void
-trigger_tabclosedpre(tabpage_T *tp)
+/*
+ * directly is TRUE if the window is closed by ':tabclose' or ':tabonly'.
+ * This allows saving the session before closing multi-window tab.
+ */
+    void
+trigger_tabclosedpre(tabpage_T *tp, int directly)
 {
     static int recursive = FALSE;
+    static int skip = FALSE;
     tabpage_T  *ptp = curtab;
 
     // Quickly return when no TabClosedPre autocommands to be executed or
@@ -2989,8 +2994,19 @@ trigger_tabclosedpre(tabpage_T *tp)
     if (!has_tabclosedpre() || recursive)
        return;
 
+    // Skip if the event have been triggered by ':tabclose' recently
+    if (skip)
+    {
+       skip = FALSE;
+       return;
+    }
+
     if (valid_tabpage(tp))
+    {
        goto_tabpage_tp(tp, FALSE, FALSE);
+       if (directly)
+           skip = TRUE;
+    }
     recursive = TRUE;
     window_layout_lock();
     apply_autocmds(EVENT_TABCLOSEDPRE, NULL, NULL, FALSE, NULL);
@@ -3382,7 +3398,7 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
 
     if (tp->tp_firstwin == tp->tp_lastwin)
     {
-       trigger_tabclosedpre(tp);
+       trigger_tabclosedpre(tp, FALSE);
        // autocmd may have freed the window already.
        if (!win_valid_any_tab(win))
            return;