commit e51f5e17e18429b847be4e0d99698727dec47ca9
parent 8754118213d79d316f740e739201b34639b4c8f6
Author: zeertzjq <zeertzjq@outlook.com>
Date: Sat, 17 Jan 2026 10:58:26 +0800
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 <Bram@vim.org>
Diffstat:
5 files changed, 31 insertions(+), 12 deletions(-)
diff --git 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
@@ -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
@@ -3,6 +3,7 @@
#include <stdbool.h>
#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
@@ -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
@@ -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