From 6c4ef7eca6f0b8547682561eb2b94f5cc0519de2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 23 Sep 2023 10:33:52 +0800 Subject: [PATCH] vim-patch:8.2.4609: :unhide does not check for failing to close a window Problem: :unhide does not check for failing to close a window. Solution: When closing a window fails continue with the next one. Do not try closing the autocmd window. (closes vim/vim#9984) https://github.com/vim/vim/commit/6f2465d336a9d4afe392db4084ef7e9db17e67c1 Co-authored-by: Bram Moolenaar --- src/nvim/autocmd.c | 3 +-- src/nvim/buffer.c | 19 +++++++++++-------- test/old/testdir/test_autocmd.vim | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 3fa20f4e48..ff0c2f063f 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -1341,7 +1341,6 @@ void aucmd_restbuf(aco_save_T *aco) if (aco->use_aucmd_win_idx >= 0) { win_T *awp = aucmd_win[aco->use_aucmd_win_idx].auc_win; - curbuf->b_nwindows--; // Find "awp", it can't be closed, but it may be in another tab page. // Do not trigger autocommands here. block_autocmds(); @@ -1357,7 +1356,7 @@ void aucmd_restbuf(aco_save_T *aco) } } win_found: - ; + curbuf->b_nwindows--; const bool save_stop_insert_mode = stop_insert_mode; // May need to stop Insert mode if we were in a prompt buffer. leaving_window(curwin); diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index d2a5eab0a5..0564b4305b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3625,12 +3625,15 @@ void ex_buffer_all(exarg_T *eap) : wp->w_width != Columns) || (had_tab > 0 && wp != firstwin)) && !ONE_WINDOW - && !(wp->w_closing - || wp->w_buffer->b_locked > 0)) { - win_close(wp, false, false); - wpnext = firstwin; // just in case an autocommand does - // something strange with windows - tpnext = first_tabpage; // start all over... + && !(wp->w_closing || wp->w_buffer->b_locked > 0) + && !is_aucmd_win(wp)) { + if (win_close(wp, false, false) == FAIL) { + break; + } + // Just in case an autocommand does something strange with + // windows: start all over... + wpnext = firstwin; + tpnext = first_tabpage; open_wins = 0; } else { open_wins++; @@ -3650,7 +3653,7 @@ void ex_buffer_all(exarg_T *eap) // // Don't execute Win/Buf Enter/Leave autocommands here. autocmd_no_enter++; - win_enter(lastwin, false); + win_enter(lastwin_nofloating(), false); autocmd_no_leave++; for (buf = firstbuf; buf != NULL && open_wins < count; buf = buf->b_next) { // Check if this buffer needs a window @@ -3742,7 +3745,7 @@ void ex_buffer_all(exarg_T *eap) // Close superfluous windows. for (wp = lastwin; open_wins > count;) { r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer) - || autowrite(wp->w_buffer, false) == OK); + || autowrite(wp->w_buffer, false) == OK) && !is_aucmd_win(wp); if (!win_valid(wp)) { // BufWrite Autocommands made the window invalid, start over wp = lastwin; diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim index 0afa3417ec..9da20e662e 100644 --- a/test/old/testdir/test_autocmd.vim +++ b/test/old/testdir/test_autocmd.vim @@ -4,6 +4,7 @@ source shared.vim source check.vim source term_util.vim source screendump.vim +source vim9.vim source load.vim func s:cleanup_buffers() abort @@ -3432,6 +3433,20 @@ func Test_autocmd_vimgrep() augroup END endfunc +func Test_closing_autocmd_window() + let lines =<< trim END + edit Xa.txt + tabnew Xb.txt + autocmd BufEnter Xa.txt unhide 1 + doautoall BufEnter + END + call CheckScriptFailure(lines, 'E814:') + au! BufEnter + only! + bwipe Xa.txt + bwipe Xb.txt +endfunc + func Test_bufwipeout_changes_window() " This should not crash, but we don't have any expectations about what " happens, changing window in BufWipeout has unpredictable results.