]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0566: <C-w>f duplicates window if do_ecmd() is aborted v9.2.0566
authorYohei Kojima <yk@y-koj.net>
Sat, 30 May 2026 18:07:21 +0000 (18:07 +0000)
committerChristian Brabandt <cb@256bit.org>
Sat, 30 May 2026 18:07:21 +0000 (18:07 +0000)
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>
src/testdir/test_window_cmd.vim
src/version.c
src/window.c

index b5ec9e5e75473a23a5ed2da27c223aa83ed27f48..e7f391ed9c984d509f5c2f64efb61b4bf77795ed 100644 (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
 
index 7c9c18a7db45155acb56a922d55ff5839f632714..cf4cf4f2dc2f8848f0c0cedbdf490057efb8e3ca 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    566,
 /**/
     565,
 /**/
index 46302b848dc6e0ee52b70150b89536ab2e48f2a7..bd5688500872113f59f0a1c3c465465afba7efe5 100644 (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