]> granicus.if.org Git - vim/commitdiff
patch 8.2.2596: :doautocmd may confuse scripts listening to WinEnter v8.2.2596
authorBram Moolenaar <Bram@vim.org>
Sat, 13 Mar 2021 14:47:56 +0000 (15:47 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 13 Mar 2021 14:47:56 +0000 (15:47 +0100)
Problem:    :doautocmd may confuse scripts listening to WinEnter.
Solution:   Do the current buffer last. (closes #7958)

src/autocmd.c
src/testdir/test_autocmd.vim
src/version.c

index 2f6001c267edac5540604d92e76c3d0dfd3c0021..ede8e7dbe0b7d3ceaae9717cf815cd7e689c89fa 100644 (file)
@@ -1336,7 +1336,7 @@ do_doautocmd(
     void
 ex_doautoall(exarg_T *eap)
 {
-    int                retval;
+    int                retval = OK;
     aco_save_T aco;
     buf_T      *buf;
     bufref_T   bufref;
@@ -1353,7 +1353,8 @@ ex_doautoall(exarg_T *eap)
      */
     FOR_ALL_BUFFERS(buf)
     {
-       if (buf->b_ml.ml_mfp != NULL)
+       // Only do loaded buffers and skip the current buffer, it's done last.
+       if (buf->b_ml.ml_mfp != NULL && buf != curbuf)
        {
            // find a window for this buffer and save some values
            aucmd_prepbuf(&aco, buf);
@@ -1363,22 +1364,31 @@ ex_doautoall(exarg_T *eap)
            retval = do_doautocmd(arg, FALSE, &did_aucmd);
 
            if (call_do_modelines && did_aucmd)
-           {
                // Execute the modeline settings, but don't set window-local
                // options if we are using the current window for another
                // buffer.
                do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
-           }
 
            // restore the current window
            aucmd_restbuf(&aco);
 
            // stop if there is some error or buffer was deleted
            if (retval == FAIL || !bufref_valid(&bufref))
+           {
+               retval = FAIL;
                break;
+           }
        }
     }
 
+    // Execute autocommands for the current buffer last.
+    if (retval == OK)
+    {
+       do_doautocmd(arg, FALSE, &did_aucmd);
+       if (call_do_modelines && did_aucmd)
+           do_modelines(0);
+    }
+
     check_cursor();        // just in case lines got deleted
 }
 
@@ -2166,12 +2176,14 @@ apply_autocmds_group(
        while (au_pending_free_buf != NULL)
        {
            buf_T *b = au_pending_free_buf->b_next;
+
            vim_free(au_pending_free_buf);
            au_pending_free_buf = b;
        }
        while (au_pending_free_win != NULL)
        {
            win_T *w = au_pending_free_win->w_next;
+
            vim_free(au_pending_free_win);
            au_pending_free_win = w;
        }
index e4f67f4fc61ed72fa3a1558a4a965b5e72fd9c2f..8abf911fa8cb7f0bfb4e3ff7a70455d901cf232a 100644 (file)
@@ -2670,6 +2670,9 @@ func Test_autocmd_window()
   %bw!
   edit one.txt
   tabnew two.txt
+  vnew three.txt
+  tabnew four.txt
+  tabprevious
   let g:blist = []
   augroup aucmd_win_test1
     au!
@@ -2678,7 +2681,12 @@ func Test_autocmd_window()
   augroup END
 
   doautoall BufEnter
-  call assert_equal([['one.txt', 'autocmd'], ['two.txt', '']], g:blist)
+  call assert_equal([
+        \ ['one.txt', 'autocmd'],
+        \ ['two.txt', ''],
+        \ ['four.txt', 'autocmd'],
+        \ ['three.txt', ''],
+        \ ], g:blist)
 
   augroup aucmd_win_test1
     au!
index 3981323f85068fcea88c54ec9b8d29343f42f99f..fbcf57e3645a988f273d18fa3a839d68830eb454 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2596,
 /**/
     2595,
 /**/