# HG changeset patch # User Bram Moolenaar # Date 1653389105 -7200 # Node ID 3c3bdb8069f59539e22d2bf8e57867cd087ad998 # Parent eee62403c898bc3374975a4d9954e43bda22e81e patch 8.2.5011: Replacing an autocommand requires several lines Commit: https://github.com/vim/vim/commit/971f6825ee845828bd5c8869487928a3f32cd467 Author: Yegappan Lakshmanan 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) diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt --- 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: > diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt --- 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 "". If there are multiple commands for an autocmd event in a diff --git a/src/autocmd.c b/src/autocmd.c --- 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; diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim --- 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:') diff --git a/src/version.c b/src/version.c --- 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,