patch 9.2.0566: <C-w>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 `<C-w>f`
 3. In the warning dialogue, type `a` to abort
 4. Current window is duplicated

closes: #20382

Signed-off-by: Yohei Kojima <yk@y-koj.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yohei Kojima
2026-05-30 18:07:21 +00:00
committed by Christian Brabandt
parent 63680c6d3d
commit 113e507cdd
3 changed files with 46 additions and 0 deletions
+32
View File
@@ -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
+2
View File
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
566,
/**/
565,
/**/
+12
View File
@@ -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