changeset 28978:3c3bdb8069f5 v8.2.5011

patch 8.2.5011: Replacing an autocommand requires several lines Commit: https://github.com/vim/vim/commit/971f6825ee845828bd5c8869487928a3f32cd467 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Tue May 24 11:40:11 2022 +0100 patch 8.2.5011: Replacing an autocommand requires several lines Problem: Replacing an autocommand requires several lines. Solution: Add the "replace" flag to autocmd_add(). (Yegappan Lakshmanan, closes #10473)
author Bram Moolenaar <Bram@vim.org>
date Tue, 24 May 2022 12:45:05 +0200
parents eee62403c898
children b49306ac0c96
files runtime/doc/autocmd.txt runtime/doc/builtin.txt src/autocmd.c src/testdir/test_autocmd.vim src/version.c
diffstat 5 files changed, 58 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -47,6 +47,28 @@ effects.  Be careful not to destroy your
   It's a good idea to use the same autocommands for the File* and Buf* events
   when possible.
 
+Recommended use:
+- Always use a group, so that it's easy to delete the autocommand.
+- Keep the command itself short, call a function to do more work.
+- Make it so that the script it is defined it can be sourced several times
+  without the autocommand being repeated.
+
+Example in Vim9 script: >
+   autocmd_add({replace: true,
+		group:   'DemoGroup',
+		event:   'BufEnter',
+		pattern: '*.txt',
+		cmd:     'call DemoBufEnter()'
+		})
+
+In legacy script: >
+   call autocmd_add(#{replace: v:true,
+		    \ group: 'DemoGroup',
+   		    \ event: 'BufEnter',
+		    \ pattern: '*.txt',
+		    \ cmd: 'call DemoBufEnter()'
+		    \ })
+
 ==============================================================================
 2. Defining autocommands				*autocmd-define*
 
@@ -83,7 +105,8 @@ triggered.
 		}
 
 The |autocmd_add()| function can be used to add a list of autocmds and autocmd
-groups from a Vim script.
+groups from a Vim script.  It is preferred if you have anything that would
+require using `:execute` with `:autocmd`.
 
 Note: The ":autocmd" command can only be followed by another command when the
 '|' appears where the pattern is expected.  This works: >
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -940,13 +940,19 @@ autocmd_add({acmds})					*autocmd_add()*
 				If this group doesn't exist then it is
 				created.  If not specified or empty, then the
 				default group is used.
-		    nested	set to v:true to add a nested autocmd.
-				Refer to |autocmd-nested|.
-		    once	set to v:true to add a autocmd which executes
-				only once. Refer to |autocmd-once|.
+		    nested	boolean flag, set to v:true to add a nested
+				autocmd.  Refer to |autocmd-nested|.
+		    once	boolean flag, set to v:true to add a autocmd
+				which executes only once. Refer to
+				|autocmd-once|.
 		    pattern	autocmd pattern string. Refer to
 				|autocmd-patterns|.  If "bufnr" item is
 				present, then this item is ignored.
+		    replace	boolean flag, set to v:true to remove all the
+				commands associated with the specified autocmd
+				event and group and add the {cmd}.  This is
+				useful to avoid adding the same command
+				multiple times for a autocmd event in a group.
 
 		Returns v:true on success and v:false on failure.
 		Examples: >
@@ -1037,10 +1043,10 @@ autocmd_get([{opts}])					*autocmd_get()
 		    cmd		Command executed for this autocmd.
 		    event	Autocmd event name.
 		    group	Autocmd group name.
-		    nested	Set to v:true for a nested autocmd. See
-				|autocmd-nested|.
-		    once	Set to v:true, if the autocmd will be executed
-				only once. See |autocmd-once|.
+		    nested	Boolean flag, set to v:true for a nested
+				autocmd. See |autocmd-nested|.
+		    once	Boolean flag, set to v:true, if the autocmd
+				will be executed only once. See |autocmd-once|.
 		    pattern	Autocmd pattern.  For a buffer-local
 				autocmd, this will be of the form "<buffer=n>".
 		If there are multiple commands for an autocmd event in a
--- a/src/autocmd.c
+++ b/src/autocmd.c
@@ -2766,6 +2766,7 @@ autocmd_add_or_delete(typval_T *argvars,
     char_u	*end;
     int		once;
     int		nested;
+    int		replace;		// replace the cmd for a group/event
     int		retval = VVAL_TRUE;
     int		save_augroup = current_augroup;
 
@@ -2877,6 +2878,9 @@ autocmd_add_or_delete(typval_T *argvars,
 
 	once = dict_get_bool(event_dict, (char_u *)"once", FALSE);
 	nested = dict_get_bool(event_dict, (char_u *)"nested", FALSE);
+	// if 'replace' is true, then remove all the commands associated with
+	// this autocmd event/group and add the new command.
+	replace = dict_get_bool(event_dict, (char_u *)"replace", FALSE);
 
 	cmd = dict_get_string(event_dict, (char_u *)"cmd", TRUE);
 	if (cmd == NULL)
@@ -2903,8 +2907,8 @@ autocmd_add_or_delete(typval_T *argvars,
 	}
 	else
 	{
-	    if (do_autocmd_event(event, pat, once, nested, cmd, delete, group,
-								    0) == FAIL)
+	    if (do_autocmd_event(event, pat, once, nested, cmd,
+					delete | replace, group, 0) == FAIL)
 	    {
 		retval = VVAL_FALSE;
 		break;
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -3413,6 +3413,18 @@ func Test_autocmd_add()
         \   nested: v:false,  once: v:false, event: 'BufHidden'}],
         \   autocmd_get(#{group: 'TestAcSet'}))
 
+  " Test for replacing a cmd for an event in a group
+  call autocmd_delete([#{group: 'TestAcSet'}])
+  call autocmd_add([#{replace: v:true, group: 'TestAcSet', event: 'BufEnter',
+        \ pattern: '*.py', cmd: 'echo "bufenter"'}])
+  call autocmd_add([#{replace: v:true, group: 'TestAcSet', event: 'BufEnter',
+        \ pattern: '*.py', cmd: 'echo "bufenter"'}])
+  call assert_equal([
+        \ #{cmd: 'echo "bufenter"', group: 'TestAcSet', pattern: '*.py',
+        \   nested: v:false,  once: v:false, event: 'BufEnter'}],
+        \   autocmd_get(#{group: 'TestAcSet'}))
+
+  " Test for adding a command for an unsupported autocmd event
   let l = [#{group: 'TestAcSet', event: 'abc', pattern: '*.sh',
         \ cmd: 'echo "bufadd"'}]
   call assert_fails('call autocmd_add(l)', 'E216:')
--- a/src/version.c
+++ b/src/version.c
@@ -735,6 +735,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    5011,
+/**/
     5010,
 /**/
     5009,