Patch 8.2.5030
Problem: autocmd_add() can only handle one event and pattern.
Solution: Support a list of events and patterns. (Yegappan Lakshmanan,
closes #10483)
Files: runtime/doc/builtin.txt, src/autocmd.c, src/errors.h,
src/testdir/test_autocmd.vim
*** ../vim-8.2.5029/runtime/doc/builtin.txt 2022-05-26 12:10:33.589893490
+0100
--- runtime/doc/builtin.txt 2022-05-27 17:57:45.760052327 +0100
***************
*** 938,944 ****
item is ignored.
cmd Ex command to execute for this autocmd event
event autocmd event name. Refer to |autocmd-events|.
! TODO: currently only accepts one event.
group autocmd group name. Refer to |autocmd-groups|.
If this group doesn't exist then it is
created. If not specified or empty, then the
--- 938,945 ----
item is ignored.
cmd Ex command to execute for this autocmd event
event autocmd event name. Refer to |autocmd-events|.
! This can be either a String with a single
! event name or a List of event names.
group autocmd group name. Refer to |autocmd-groups|.
If this group doesn't exist then it is
created. If not specified or empty, then the
***************
*** 950,956 ****
|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
--- 951,959 ----
|autocmd-once|.
pattern autocmd pattern string. Refer to
|autocmd-patterns|. If "bufnr" item is
! present, then this item is ignored. This can
! be a String with a single pattern or a List of
! patterns.
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
*** ../vim-8.2.5029/src/autocmd.c 2022-05-24 11:40:07.514685757 +0100
--- src/autocmd.c 2022-05-27 17:57:45.764052324 +0100
***************
*** 2754,2769 ****
static void
autocmd_add_or_delete(typval_T *argvars, typval_T *rettv, int delete)
{
! list_T *event_list;
listitem_T *li;
dict_T *event_dict;
char_u *event_name = NULL;
event_T event;
char_u *group_name = NULL;
int group;
char_u *pat = NULL;
char_u *cmd = NULL;
char_u *end;
int once;
int nested;
int replace; // replace the cmd for a
group/event
--- 2754,2775 ----
static void
autocmd_add_or_delete(typval_T *argvars, typval_T *rettv, int delete)
{
! list_T *aucmd_list;
listitem_T *li;
dict_T *event_dict;
+ dictitem_T *di;
char_u *event_name = NULL;
+ list_T *event_list;
+ listitem_T *eli;
event_T event;
char_u *group_name = NULL;
int group;
char_u *pat = NULL;
+ list_T *pat_list;
+ listitem_T *pli;
char_u *cmd = NULL;
char_u *end;
+ char_u *p;
int once;
int nested;
int replace; // replace the cmd for a
group/event
***************
*** 2776,2791 ****
if (check_for_list_arg(argvars, 0) == FAIL)
return;
! event_list = argvars[0].vval.v_list;
! if (event_list == NULL)
return;
! FOR_ALL_LIST_ITEMS(event_list, li)
{
- VIM_CLEAR(event_name);
VIM_CLEAR(group_name);
- VIM_CLEAR(pat);
VIM_CLEAR(cmd);
if (li->li_tv.v_type != VAR_DICT)
continue;
--- 2782,2799 ----
if (check_for_list_arg(argvars, 0) == FAIL)
return;
! aucmd_list = argvars[0].vval.v_list;
! if (aucmd_list == NULL)
return;
! FOR_ALL_LIST_ITEMS(aucmd_list, li)
{
VIM_CLEAR(group_name);
VIM_CLEAR(cmd);
+ event_name = NULL;
+ event_list = NULL;
+ pat = NULL;
+ pat_list = NULL;
if (li->li_tv.v_type != VAR_DICT)
continue;
***************
*** 2794,2823 ****
if (event_dict == NULL)
continue;
! event_name = dict_get_string(event_dict, (char_u *)"event", TRUE);
! if (event_name == NULL)
{
! if (delete)
! // if the event name is not specified, delete all the events
! event = NUM_EVENTS;
! else
! continue;
! }
! else
! {
! if (delete && event_name[0] == '*' && event_name[1] == NUL)
! // if the event name is '*', delete all the events
! event = NUM_EVENTS;
! else
{
! event = event_name2nr(event_name, &end);
! if (event == NUM_EVENTS)
{
! semsg(_(e_no_such_event_str), event_name);
! retval = VVAL_FALSE;
! break;
}
}
}
group_name = dict_get_string(event_dict, (char_u *)"group", TRUE);
--- 2802,2833 ----
if (event_dict == NULL)
continue;
! di = dict_find(event_dict, (char_u *)"event", -1);
! if (di != NULL)
{
! if (di->di_tv.v_type == VAR_STRING)
{
! event_name = di->di_tv.vval.v_string;
! if (event_name == NULL)
{
! emsg(_(e_string_required));
! continue;
! }
! }
! else if (di->di_tv.v_type == VAR_LIST)
! {
! event_list = di->di_tv.vval.v_list;
! if (event_list == NULL)
! {
! emsg(_(e_list_required));
! continue;
}
}
+ else
+ {
+ emsg(_(e_string_or_list_expected));
+ continue;
+ }
}
group_name = dict_get_string(event_dict, (char_u *)"group", TRUE);
***************
*** 2859,2879 ****
if (bnum == -1)
continue;
! pat = alloc(128 + 1);
! if (pat == NULL)
! continue;
! vim_snprintf((char *)pat, 128, "<buffer=%d>", (int)bnum);
}
else
{
! pat = dict_get_string(event_dict, (char_u *)"pattern", TRUE);
! if (pat == NULL)
{
! if (delete)
! pat = vim_strsave((char_u *)"");
else
continue;
}
}
once = dict_get_bool(event_dict, (char_u *)"once", FALSE);
--- 2869,2908 ----
if (bnum == -1)
continue;
! vim_snprintf((char *)IObuff, IOSIZE, "<buffer=%d>", (int)bnum);
! pat = IObuff;
}
else
{
! di = dict_find(event_dict, (char_u *)"pattern", -1);
! if (di != NULL)
{
! if (di->di_tv.v_type == VAR_STRING)
! {
! pat = di->di_tv.vval.v_string;
! if (pat == NULL)
! {
! emsg(_(e_string_required));
! continue;
! }
! }
! else if (di->di_tv.v_type == VAR_LIST)
! {
! pat_list = di->di_tv.vval.v_list;
! if (pat_list == NULL)
! {
! emsg(_(e_list_required));
! continue;
! }
! }
else
+ {
+ emsg(_(e_string_or_list_expected));
continue;
+ }
}
+ else if (delete)
+ pat = (char_u *)"";
}
once = dict_get_bool(event_dict, (char_u *)"once", FALSE);
***************
*** 2891,2899 ****
continue;
}
! if (event == NUM_EVENTS)
{
! // event is '*', apply for all the events
for (event = (event_T)0; (int)event < NUM_EVENTS;
event = (event_T)((int)event + 1))
{
--- 2920,2929 ----
continue;
}
! if (delete && (event_name == NULL
! || (event_name[0] == '*' && event_name[1] == NUL)))
{
! // if the event name is not specified or '*', delete all the events
for (event = (event_T)0; (int)event < NUM_EVENTS;
event = (event_T)((int)event + 1))
{
***************
*** 2907,2917 ****
}
else
{
! if (do_autocmd_event(event, pat, once, nested, cmd,
! delete | replace, group, 0) == FAIL)
{
! retval = VVAL_FALSE;
! break;
}
}
--- 2937,3012 ----
}
else
{
! eli = NULL;
! end = NULL;
! while (TRUE)
{
! if (event_list != NULL)
! {
! if (eli == NULL)
! eli = event_list->lv_first;
! else
! eli = eli->li_next;
! if (eli == NULL)
! break;
! if (eli->li_tv.v_type != VAR_STRING
! || eli->li_tv.vval.v_string == NULL)
! {
! emsg(_(e_string_required));
! continue;
! }
! p = eli->li_tv.vval.v_string;
! }
! else
! {
! if (end == NULL)
! p = end = event_name;
! if (end == NULL || *end == NUL)
! break;
! }
! if (p == NULL)
! continue;
!
! event = event_name2nr(p, &end);
! if (event == NUM_EVENTS || *end != NUL)
! {
! semsg(_(e_no_such_event_str), p);
! retval = VVAL_FALSE;
! break;
! }
! if (pat != NULL)
! {
! if (do_autocmd_event(event, pat, once, nested, cmd,
! delete | replace, group, 0) == FAIL)
! {
! retval = VVAL_FALSE;
! break;
! }
! }
! else if (pat_list != NULL)
! {
! FOR_ALL_LIST_ITEMS(pat_list, pli)
! {
! if (pli->li_tv.v_type != VAR_STRING
! || pli->li_tv.vval.v_string == NULL)
! {
! emsg(_(e_string_required));
! continue;
! }
! if (do_autocmd_event(event,
! pli->li_tv.vval.v_string, once, nested,
! cmd, delete | replace, group, 0) ==
! FAIL)
! {
! retval = VVAL_FALSE;
! break;
! }
! }
! if (retval == VVAL_FALSE)
! break;
! }
! if (event_name != NULL)
! p = end;
}
}
***************
*** 2925,2933 ****
au_del_group(group_name);
}
- VIM_CLEAR(event_name);
VIM_CLEAR(group_name);
- VIM_CLEAR(pat);
VIM_CLEAR(cmd);
current_augroup = save_augroup;
--- 3020,3026 ----
*** ../vim-8.2.5029/src/errors.h 2022-05-27 17:26:50.538119977 +0100
--- src/errors.h 2022-05-27 17:57:45.764052324 +0100
***************
*** 1184,1190 ****
INIT(= N_("E475: Invalid argument: %s"));
EXTERN char e_invalid_value_for_argument_str[]
INIT(= N_("E475: Invalid value for argument %s"));
! #if defined(FEAT_JOB_CHANNEL) || defined(FEAT_PROP_POPUP)
EXTERN char e_invalid_value_for_argument_str_str[]
INIT(= N_("E475: Invalid value for argument %s: %s"));
#endif
--- 1184,1190 ----
INIT(= N_("E475: Invalid argument: %s"));
EXTERN char e_invalid_value_for_argument_str[]
INIT(= N_("E475: Invalid value for argument %s"));
! #if defined(FEAT_JOB_CHANNEL) || defined(FEAT_PROP_POPUP) ||
defined(FEAT_EVAL)
EXTERN char e_invalid_value_for_argument_str_str[]
INIT(= N_("E475: Invalid value for argument %s: %s"));
#endif
***************
*** 3280,3286 ****
INIT(= N_("E1281: Atom '\\%%#=%c' must be at the start of the
pattern"));
#ifdef FEAT_EVAL
EXTERN char e_bitshift_ops_must_be_number[]
! INIT(= N_("E1282: bitshift operands must be numbers"));
EXTERN char e_bitshift_ops_must_be_postive[]
! INIT(= N_("E1283: bitshift amount must be a positive number"));
#endif
--- 3280,3286 ----
INIT(= N_("E1281: Atom '\\%%#=%c' must be at the start of the
pattern"));
#ifdef FEAT_EVAL
EXTERN char e_bitshift_ops_must_be_number[]
! INIT(= N_("E1282: Bitshift operands must be numbers"));
EXTERN char e_bitshift_ops_must_be_postive[]
! INIT(= N_("E1283: Bitshift amount must be a positive number"));
#endif
*** ../vim-8.2.5029/src/testdir/test_autocmd.vim 2022-05-24
11:40:07.518685751 +0100
--- src/testdir/test_autocmd.vim 2022-05-27 17:57:45.764052324 +0100
***************
*** 3429,3434 ****
--- 3429,3511 ----
\ cmd: 'echo "bufadd"'}]
call assert_fails('call autocmd_add(l)', 'E216:')
+ " Test for using a list of events and patterns
+ call autocmd_delete([#{group: 'TestAcSet'}])
+ let l = [#{group: 'TestAcSet', event: ['BufEnter', 'BufLeave'],
+ \ pattern: ['*.py', '*.sh'], cmd: 'echo "bufcmds"'}]
+ call autocmd_add(l)
+ call assert_equal([
+ \ #{cmd: 'echo "bufcmds"', group: 'TestAcSet', pattern: '*.py',
+ \ nested: v:false, once: v:false, event: 'BufEnter'},
+ \ #{cmd: 'echo "bufcmds"', group: 'TestAcSet', pattern: '*.sh',
+ \ nested: v:false, once: v:false, event: 'BufEnter'},
+ \ #{cmd: 'echo "bufcmds"', group: 'TestAcSet', pattern: '*.py',
+ \ nested: v:false, once: v:false, event: 'BufLeave'},
+ \ #{cmd: 'echo "bufcmds"', group: 'TestAcSet', pattern: '*.sh',
+ \ nested: v:false, once: v:false, event: 'BufLeave'}],
+ \ autocmd_get(#{group: 'TestAcSet'}))
+
+ " Test for invalid values for 'event' item
+ call autocmd_delete([#{group: 'TestAcSet'}])
+ let l = [#{group: 'TestAcSet', event: test_null_string(),
+ \ pattern: "*.py", cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E928:')
+ let l = [#{group: 'TestAcSet', event: test_null_list(),
+ \ pattern: "*.py", cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E714:')
+ let l = [#{group: 'TestAcSet', event: {},
+ \ pattern: "*.py", cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E777:')
+ let l = [#{group: 'TestAcSet', event: [{}],
+ \ pattern: "*.py", cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E928:')
+ let l = [#{group: 'TestAcSet', event: [test_null_string()],
+ \ pattern: "*.py", cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E928:')
+ let l = [#{group: 'TestAcSet', event: 'BufEnter,BufLeave',
+ \ pattern: '*.py', cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E216:')
+ let l = [#{group: 'TestAcSet', event: [],
+ \ pattern: "*.py", cmd: 'echo "bufcmds"'}]
+ call autocmd_add(l)
+ let l = [#{group: 'TestAcSet', event: [""],
+ \ pattern: "*.py", cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E216:')
+ let l = [#{group: 'TestAcSet', event: "",
+ \ pattern: "*.py", cmd: 'echo "bufcmds"'}]
+ call autocmd_add(l)
+ call assert_equal([], autocmd_get(#{group: 'TestAcSet'}))
+
+ " Test for invalid values for 'pattern' item
+ let l = [#{group: 'TestAcSet', event: "BufEnter",
+ \ pattern: test_null_string(), cmd: 'echo "bufcmds"'}]
+ let l = [#{group: 'TestAcSet', event: "BufEnter",
+ \ pattern: test_null_list(), cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E714:')
+ let l = [#{group: 'TestAcSet', event: "BufEnter",
+ \ pattern: {}, cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E777:')
+ let l = [#{group: 'TestAcSet', event: "BufEnter",
+ \ pattern: [{}], cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E928:')
+ let l = [#{group: 'TestAcSet', event: "BufEnter",
+ \ pattern: [test_null_string()], cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E928:')
+ let l = [#{group: 'TestAcSet', event: "BufEnter",
+ \ pattern: [], cmd: 'echo "bufcmds"'}]
+ call autocmd_add(l)
+ let l = [#{group: 'TestAcSet', event: "BufEnter",
+ \ pattern: [""], cmd: 'echo "bufcmds"'}]
+ call autocmd_add(l)
+ let l = [#{group: 'TestAcSet', event: "BufEnter",
+ \ pattern: "", cmd: 'echo "bufcmds"'}]
+ call autocmd_add(l)
+ call assert_equal([], autocmd_get(#{group: 'TestAcSet'}))
+
+ let l = [#{group: 'TestAcSet', event: 'BufEnter,abc,BufLeave',
+ \ pattern: '*.py', cmd: 'echo "bufcmds"'}]
+ call assert_fails('call autocmd_add(l)', 'E216:')
+
call assert_fails("call autocmd_add({})", 'E1211:')
call assert_equal(v:false, autocmd_add(test_null_list()))
call assert_true(autocmd_add([[]]))
*** ../vim-8.2.5029/src/version.c 2022-05-27 17:26:50.546119970 +0100
--- src/version.c 2022-05-27 18:04:38.939665812 +0100
***************
*** 736,737 ****
--- 736,739 ----
{ /* Add new patch number below this line */
+ /**/
+ 5030,
/**/
--
LAUNCELOT: At last! A call! A cry of distress ...
(he draws his sword, and turns to CONCORDE)
Concorde! Brave, Concorde ... you shall not have died in vain!
CONCORDE: I'm not quite dead, sir ...
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/20220527170644.0AD341C1929%40moolenaar.net.