1
0
forked from aniani/vim

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 <jimzhouzzy@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Jim Zhou
2025-03-16 20:24:57 +01:00
committed by Christian Brabandt
parent 21ac3a49b5
commit bcf66e0141
5 changed files with 53 additions and 4 deletions

View File

@@ -6536,6 +6536,8 @@ tabpage_close(int forceit)
if (window_layout_locked(CMD_tabclose)) if (window_layout_locked(CMD_tabclose))
return; return;
trigger_tabclosedpre(curtab, TRUE);
// First close all the windows but the current one. If that worked then // First close all the windows but the current one. If that worked then
// close the last window in this tab, that will close it. // close the last window in this tab, that will close it.
if (!ONE_WINDOW) if (!ONE_WINDOW)
@@ -6559,6 +6561,8 @@ tabpage_close_other(tabpage_T *tp, int forceit)
int done = 0; int done = 0;
win_T *wp; win_T *wp;
trigger_tabclosedpre(tp, TRUE);
// Limit to 1000 windows, autocommands may add a window while we close // Limit to 1000 windows, autocommands may add a window while we close
// one. OK, so I'm paranoid... // one. OK, so I'm paranoid...
while (++done < 1000) while (++done < 1000)

View File

@@ -102,4 +102,5 @@ int get_tab_number(tabpage_T *tp);
char *check_colorcolumn(char_u *cc, win_T *wp); char *check_colorcolumn(char_u *cc, win_T *wp);
int get_last_winid(void); int get_last_winid(void);
int win_locked(win_T *wp); int win_locked(win_T *wp);
void trigger_tabclosedpre(tabpage_T *tp, int directly);
/* vim: set ft=c : */ /* vim: set ft=c : */

View File

@@ -5109,7 +5109,7 @@ func Test_autocmd_tabclosedpre()
call ClearAutomcdAndCreateTabs() call ClearAutomcdAndCreateTabs()
au TabClosedPre * tabmove 0 au TabClosedPre * tabmove 0
tabclose tabclose
call assert_equal('1Z2A3>B', GetTabs()) call assert_equal('1>Z2A3B', GetTabs())
call ClearAutomcdAndCreateTabs() call ClearAutomcdAndCreateTabs()
au TabClosedPre * tabmove 0 au TabClosedPre * tabmove 0
tabclose 1 tabclose 1
@@ -5137,7 +5137,33 @@ func Test_autocmd_tabclosedpre()
au TabClosedPre * new X | new Y | new Z au TabClosedPre * new X | new Y | new Z
call assert_fails('tabclose 1', 'E242') 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 " Clean up
call delete('Session.vim')
au! au!
only only
tabonly tabonly

View File

@@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1211,
/**/ /**/
1210, 1210,
/**/ /**/

View File

@@ -2978,10 +2978,15 @@ trigger_winclosed(win_T *win)
recursive = FALSE; 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 recursive = FALSE;
static int skip = FALSE;
tabpage_T *ptp = curtab; tabpage_T *ptp = curtab;
// Quickly return when no TabClosedPre autocommands to be executed or // Quickly return when no TabClosedPre autocommands to be executed or
@@ -2989,8 +2994,19 @@ trigger_tabclosedpre(tabpage_T *tp)
if (!has_tabclosedpre() || recursive) if (!has_tabclosedpre() || recursive)
return; return;
// Skip if the event have been triggered by ':tabclose' recently
if (skip)
{
skip = FALSE;
return;
}
if (valid_tabpage(tp)) if (valid_tabpage(tp))
{
goto_tabpage_tp(tp, FALSE, FALSE); goto_tabpage_tp(tp, FALSE, FALSE);
if (directly)
skip = TRUE;
}
recursive = TRUE; recursive = TRUE;
window_layout_lock(); window_layout_lock();
apply_autocmds(EVENT_TABCLOSEDPRE, NULL, NULL, FALSE, NULL); 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) if (tp->tp_firstwin == tp->tp_lastwin)
{ {
trigger_tabclosedpre(tp); trigger_tabclosedpre(tp, FALSE);
// autocmd may have freed the window already. // autocmd may have freed the window already.
if (!win_valid_any_tab(win)) if (!win_valid_any_tab(win))
return; return;