changeset 31412:742b7bf2fefc v9.0.1039

patch 9.0.1039: using a <Cmd> mapping CmdlineChanged may be triggered twice Commit: https://github.com/vim/vim/commit/bb393d8259af8aec095e96d81624a16ed9f25005 Author: Bram Moolenaar <Bram@vim.org> Date: Fri Dec 9 12:21:50 2022 +0000 patch 9.0.1039: using a <Cmd> mapping CmdlineChanged may be triggered twice Problem: Using a <Cmd> mapping CmdlineChanged may be triggered twice. Solution: Count the number of times CmdlineChanged is triggered and avoid doing it twice. (closes #116820
author Bram Moolenaar <Bram@vim.org>
date Fri, 09 Dec 2022 13:30:05 +0100
parents 533370cc392d
children 989db125b24d
files src/autocmd.c src/ex_getln.c src/globals.h src/testdir/test_autocmd.vim src/version.c
diffstat 5 files changed, 23 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/autocmd.c
+++ b/src/autocmd.c
@@ -2068,6 +2068,9 @@ apply_autocmds_group(
 		&& (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
 	goto BYPASS_AU;
 
+    if (event == EVENT_CMDLINECHANGED)
+	++aucmd_cmdline_changed_count;
+
     /*
      * Save the autocmd_* variables and info about the current buffer.
      */
@@ -2088,8 +2091,8 @@ apply_autocmds_group(
     if (fname_io == NULL)
     {
 	if (event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE
-						   || event == EVENT_OPTIONSET
-						   || event == EVENT_MODECHANGED)
+						 || event == EVENT_OPTIONSET
+						 || event == EVENT_MODECHANGED)
 	    autocmd_fname = NULL;
 	else if (fname != NULL && !ends_excmd(*fname))
 	    autocmd_fname = fname;
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -1785,11 +1785,13 @@ getcmdline_int(
 
 	if (c == K_COMMAND || c == K_SCRIPT_COMMAND)
 	{
-	    int	    clen = ccline.cmdlen;
+	    int	    cc_count = aucmd_cmdline_changed_count;
 
 	    if (do_cmdkey_command(c, DOCMD_NOWAIT) == OK)
 	    {
-		if (clen == ccline.cmdlen)
+		// Do not trigger CmdlineChanged below if the <Cmd> mapping
+		// already did that.
+		if (cc_count != aucmd_cmdline_changed_count)
 		    trigger_cmdlinechanged = FALSE;
 		goto cmdline_changed;
 	    }
--- a/src/globals.h
+++ b/src/globals.h
@@ -1582,10 +1582,13 @@ EXTERN char_u	last_mode[MODE_MAX_LENGTH]
 EXTERN char_u	*last_cmdline INIT(= NULL); // last command line (for ":)
 EXTERN char_u	*repeat_cmdline INIT(= NULL); // command line for "."
 EXTERN char_u	*new_last_cmdline INIT(= NULL);	// new value for last_cmdline
+						//
 EXTERN char_u	*autocmd_fname INIT(= NULL); // fname for <afile> on cmdline
 EXTERN int	autocmd_fname_full;	     // autocmd_fname is full path
 EXTERN int	autocmd_bufnr INIT(= 0);     // fnum for <abuf> on cmdline
 EXTERN char_u	*autocmd_match INIT(= NULL); // name for <amatch> on cmdline
+EXTERN int	aucmd_cmdline_changed_count INIT(= 0);
+
 EXTERN int	did_cursorhold INIT(= FALSE); // set when CursorHold t'gerd
 EXTERN pos_T	last_cursormoved	      // for CursorMoved event
 # ifdef DO_INIT
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -1908,6 +1908,15 @@ func Test_Cmdline()
   call assert_equal(':', g:entered)
   au! CmdlineChanged
 
+  let g:log = []
+  cnoremap <F1> <Cmd>call setcmdline('ls')<CR>
+  autocmd CmdlineChanged : let g:log += [getcmdline()]
+  call feedkeys(":\<F1>", 'xt')
+  call assert_equal(['ls'], g:log)
+  unlet g:log
+  au! CmdlineChanged
+  cunmap <F1>
+
   au! CmdlineEnter : let g:entered = expand('<afile>')
   au! CmdlineLeave : let g:left = expand('<afile>')
   let g:entered = 0
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1039,
+/**/
     1038,
 /**/
     1037,