From e51f5e17e18429b847be4e0d99698727dec47ca9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 17 Jan 2026 10:58:26 +0800 Subject: [PATCH] vim-patch:9.0.0909: error message for layout change does not match action (#37436) Problem: Error message for layout change does not match action. Solution: Pass the command to where the error is given. (closes vim/vim#11573) https://github.com/vim/vim/commit/9fda81515b26ecd3c1e99f95334aaed3f7b6fea3 Thinking about this again, it's actually OK to check split_disallowed in window_layout_locked(), so add the check. Also add missing window_layout_locked() in tabpage_close(). Co-authored-by: Bram Moolenaar --- src/nvim/ex_docmd.c | 14 +++++++++----- src/nvim/window.c | 17 +++++++++++------ src/nvim/window.h | 1 + test/functional/ui/float_spec.lua | 3 ++- test/old/testdir/test_autocmd.vim | 8 ++++++++ 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 125646e348..5ec510d17f 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5033,7 +5033,7 @@ void ex_win_close(int forceit, win_T *win, tabpage_T *tp) emsg(_(e_autocmd_close)); return; } - if (!win->w_floating && window_layout_locked()) { + if (!win->w_floating && window_layout_locked(CMD_close)) { return; } @@ -5077,7 +5077,7 @@ static void ex_tabclose(exarg_T *eap) return; } - if (window_layout_locked()) { + if (window_layout_locked(CMD_tabclose)) { return; } @@ -5112,7 +5112,7 @@ static void ex_tabonly(exarg_T *eap) return; } - if (window_layout_locked()) { + if (window_layout_locked(CMD_tabonly)) { return; } @@ -5146,6 +5146,10 @@ static void ex_tabonly(exarg_T *eap) /// Close the current tab page. void tabpage_close(int forceit) { + if (window_layout_locked(CMD_tabclose)) { + return; + } + // First close all the windows but the current one. If that worked then // close the last window in this tab, that will close it. while (curwin->w_floating) { @@ -5186,7 +5190,7 @@ void tabpage_close_other(tabpage_T *tp, int forceit) /// ":only". static void ex_only(exarg_T *eap) { - if (window_layout_locked()) { + if (window_layout_locked(CMD_only)) { return; } @@ -5231,7 +5235,7 @@ static void ex_hide(exarg_T *eap) } } - if (!win->w_floating && window_layout_locked()) { + if (!win->w_floating && window_layout_locked(CMD_hide)) { return; } diff --git a/src/nvim/window.c b/src/nvim/window.c index 6333eb1b2b..5383857051 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -139,11 +139,16 @@ bool frames_locked(void) } /// When the window layout cannot be changed give an error and return true. -bool window_layout_locked(void) +/// "cmd" indicates the action being performed and is used to pick the relevant +/// error message. +bool window_layout_locked(cmdidx_T cmd) { - // if (split_disallowed > 0 || close_disallowed > 0) { - if (close_disallowed > 0) { - emsg(_(e_not_allowed_to_change_window_layout_in_this_autocmd)); + if (split_disallowed > 0 || close_disallowed > 0) { + if (close_disallowed == 0 && cmd == CMD_tabnew) { + emsg(_(e_cannot_split_window_when_closing_buffer)); + } else { + emsg(_(e_not_allowed_to_change_window_layout_in_this_autocmd)); + } return true; } return false; @@ -2784,7 +2789,7 @@ int win_close(win_T *win, bool free_buf, bool force) emsg(_(e_cannot_close_last_window)); return FAIL; } - if (!win->w_floating && window_layout_locked()) { + if (!win->w_floating && window_layout_locked(CMD_close)) { return FAIL; } @@ -4378,7 +4383,7 @@ int win_new_tabpage(int after, char *filename) emsg(_(e_cmdwin)); return FAIL; } - if (window_layout_locked()) { + if (window_layout_locked(CMD_tabnew)) { return FAIL; } diff --git a/src/nvim/window.h b/src/nvim/window.h index c4199d6e0f..4cb9fe71ab 100644 --- a/src/nvim/window.h +++ b/src/nvim/window.h @@ -3,6 +3,7 @@ #include #include "nvim/buffer_defs.h" // IWYU pragma: keep +#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep #include "nvim/garray_defs.h" // IWYU pragma: keep #include "nvim/macros_defs.h" #include "nvim/option_defs.h" // IWYU pragma: keep diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 21b32a4278..a9216270ed 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -1075,7 +1075,8 @@ describe('float window', function() -- Try switching tab pages and moving windows between tab pages via nvim_win_set_config. -- Simplest if :fclose skips windows in non-current tabpages. local w5 = api.nvim_open_win(0, false, { relative = 'editor', row = 0, col = 0, width = 5, height = 5, zindex = 2 }) - command('autocmd WinEnter * ++once tabnew') + command('tabnew | tabprevious') + command('autocmd WinEnter * ++once tabnext') eq(w4, api.nvim_get_current_win()) local tp1 = api.nvim_get_current_tabpage() command('fclose!') diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim index 02bbd3368a..ac0e5d68fd 100644 --- a/test/old/testdir/test_autocmd.vim +++ b/test/old/testdir/test_autocmd.vim @@ -1083,6 +1083,14 @@ func Test_BufEnter() bwipe! au! BufEnter endfor + + new + new + autocmd BufEnter * ++once close + call assert_fails('close', 'E1312:') + + au! BufEnter + only endfunc " Closing a window might cause an endless loop