patch 9.1.1211: TabClosedPre is triggered just before the tab is being freed
Commit: https://github.com/vim/vim/commit/bcf66e014141982192e2743829bceef60ce77727 Author: Jim Zhou <jimzhou...@gmail.com> Date: Sun Mar 16 20:24:57 2025 +0100 patch 9.1.1211: TabClosedPre is triggered just before the tab is being freed 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 <jimzhou...@gmail.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 443883490..80ec8a1a6 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -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) diff --git a/src/proto/window.pro b/src/proto/window.pro index 9a2661d96..f1e129d6e 100644 --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -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 : */ diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index 138b852f0..2519e60a1 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -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 diff --git a/src/version.c b/src/version.c index d293eba6a..812941804 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1211, /**/ 1210, /**/ diff --git a/src/window.c b/src/window.c index cce7f4c79..55168d53f 100644 --- a/src/window.c +++ b/src/window.c @@ -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; -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1tttgS-00EXsQ-4b%40256bit.org.