From: Yohei Kojima Date: Sat, 30 May 2026 18:07:21 +0000 (+0000) Subject: patch 9.2.0566: f duplicates window if do_ecmd() is aborted X-Git-Tag: v9.2.0566^0 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=113e507cdd7be13607db81dcd6cd09aaedf93540;p=thirdparty%2Fvim.git patch 9.2.0566: f duplicates window if do_ecmd() is aborted Problem: If got_int is true when win_close() is called, it unexpectedly fails in the branch that detects failure in apply_autocmds(). This causes wingotofile in do_window() to duplicate current window when do_ecmd() is aborted with got_int. Solution: Fix do_window() to save the got_int value before trying to close the split window (Yohei Kojima). Steps to reproduce: 1. run `touch a && touch .a.swp && echo a > b && vim b` 2. Type `f` 3. In the warning dialogue, type `a` to abort 4. Current window is duplicated closes: #20382 Signed-off-by: Yohei Kojima Signed-off-by: Christian Brabandt --- diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index b5ec9e5e75..e7f391ed9c 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -113,7 +113,39 @@ func Test_window_cmd_wincmd_gf() call assert_notequal(fname, bufname("%")) new | only! + au! test_window_cmd_wincmd_gf augroup! test_window_cmd_wincmd_gf + delfunc s:swap_exists + bw! +endfunc + +func Test_abort_in_wincmd_f() + let fname = 'test_f.txt' + let swp_fname = $'.{fname}.swp' + call writefile([], fname, 'D') + call writefile([], swp_fname, 'D') + " Remove the catch-all that runtest.vim adds + au! SwapExists + augroup test_window_cmd_wincmd_f + autocmd! + " (A)bort + autocmd SwapExists test_f.txt let v:swapchoice = 'a' + augroup END + + call setline(1, fname) + call assert_equal(1, winnr('$')) + try + wincmd f + catch /^Vim:Interrupt$/ + " expected interrupt by abort + endtry + call assert_equal(1, winnr('$')) + new | only! + + " See :h W19 for the background of this au!. Ideally other tests + " should also follow this. + au! test_window_cmd_wincmd_f + augroup! test_window_cmd_wincmd_f bw! endfunc diff --git a/src/version.c b/src/version.c index 7c9c18a7db..cf4cf4f2dc 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 566, /**/ 565, /**/ diff --git a/src/window.c b/src/window.c index 46302b848d..bd56885008 100644 --- a/src/window.c +++ b/src/window.c @@ -682,9 +682,21 @@ wingotofile: if (do_ecmd(0, ptr, NULL, NULL, ECMD_LASTL, ECMD_HIDE, NULL) == FAIL) { + /* + * Note: if FEAT_EVAL is defined and do_ecmd() is aborted resulting + * in got_int be true, win_close() unconditionally fails. In such + * case, the window split for do_ecmd() is left unclosed, i.e. the + * current window is just duplicated. To avoid this, save and load + * got_int value before and after closing the window. + */ + sig_atomic_t old_got_int = got_int; + got_int = FALSE; + // Failed to open the file, close the window // opened for it. win_close(curwin, FALSE); + got_int = got_int || old_got_int; + goto_tabpage_win(oldtab, oldwin); } else