diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 189e9d558b..90ce68410d 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -145,6 +145,7 @@ static void au_show_for_all_events(int group, const char *pat) } static void au_show_for_event(int group, event_T event, const char *pat) + FUNC_ATTR_NONNULL_ALL { AutoCmdVec *const acs = &autocmds[(int)event]; // Return early if there are no autocmds for this event @@ -152,10 +153,23 @@ static void au_show_for_event(int group, event_T event, const char *pat) return; } - char buflocal_pat[BUFLOCAL_PAT_LEN]; // for "" - int patlen; + // Empty pattern shows all autocommands for this event + int patlen = 0; if (*pat != NUL) { patlen = (int)aucmd_pattern_length(pat); + if (patlen == 0) { // Don't show if it contains only commas + return; + } + } + + char buflocal_pat[BUFLOCAL_PAT_LEN]; // for "" + int last_group = AUGROUP_ERROR; + const char *last_group_name = NULL; + + // Loop through all the specified patterns. + do { + AutoPat *last_ap = NULL; + const char *endpat = pat + patlen; // detect special buffer-local patterns if (aupat_is_buflocal(pat, patlen)) { @@ -165,21 +179,6 @@ static void au_show_for_event(int group, event_T event, const char *pat) patlen = (int)strlen(buflocal_pat); } - if (patlen == 0) { - return; - } - assert(*pat != NUL); - } else { - pat = NULL; - patlen = 0; - } - - // Loop through all the specified patterns. - while (true) { - AutoPat *last_ap = NULL; - int last_group = AUGROUP_ERROR; - const char *last_group_name = NULL; - for (size_t i = 0; i < kv_size(*acs); i++) { AutoCmd *const ac = &kv_A(*acs, i); @@ -195,7 +194,7 @@ static void au_show_for_event(int group, event_T event, const char *pat) // For , this condition works because we normalize // all buffer-local patterns. if ((group != AUGROUP_ALL && ac->pat->group != group) - || (pat != NULL + || (patlen && (ac->pat->patlen != patlen || strncmp(pat, ac->pat->pat, (size_t)patlen) != 0))) { continue; } @@ -280,17 +279,9 @@ static void au_show_for_event(int group, event_T event, const char *pat) } } - // If a pattern is provided, find next pattern. Otherwise exit after single iteration. - if (pat != NULL) { - pat = aucmd_next_pattern(pat, (size_t)patlen); - patlen = (int)aucmd_pattern_length(pat); - if (patlen == 0) { - break; - } - } else { - break; - } - } + pat = aucmd_next_pattern(endpat, 0); + patlen = (int)aucmd_pattern_length(pat); + } while (patlen); } // Delete autocommand. @@ -917,6 +908,8 @@ int do_autocmd_event(event_T event, const char *pat, bool once, int nested, cons // Loop through all the specified patterns. int patlen = (int)aucmd_pattern_length(pat); while (patlen) { + const char *endpat = pat + patlen; + // detect special buffer-local patterns bool is_buflocal = aupat_is_buflocal(pat, patlen); if (is_buflocal) { @@ -959,7 +952,7 @@ int do_autocmd_event(event_T event, const char *pat, bool once, int nested, cons autocmd_register(0, event, pat, patlen, group, once, nested, NULL, cmd, &handler_fn); } - pat = aucmd_next_pattern(pat, (size_t)patlen); + pat = aucmd_next_pattern(endpat, 0); patlen = (int)aucmd_pattern_length(pat); } diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 9b5c1b5250..bd9cf872cf 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -712,4 +712,73 @@ describe('autocmd', function() ]] eq('flarb', fn.bufname()) end) + + it('does not ignore comma-separated patterns after a buffer-local pattern', function() + exec [[ + edit baz " reuses buffer 1 + edit bazinga + edit bar + edit boop + edit foo + edit floob + + let g:events1 = [] + autocmd BufEnter ,,boop,bar let g:events1 += [expand('')] + let g:events2 = [] + augroup flobby + autocmd BufEnter ,foo let g:events2 += [expand('')] + autocmd BufEnter foo, let g:events2 += ['flobby ' .. expand('')] + augroup END + ]] + eq( + dedent([=[ + + --- Autocommands --- + BufEnter + + let g:events1 += [expand('')] + + let g:events1 += [expand('')] + boop let g:events1 += [expand('')] + bar let g:events1 += [expand('')] + flobby BufEnter + + let g:events2 += [expand('')] + foo let g:events2 += [expand('')] + let g:events2 += ['flobby ' .. expand('')] + + let g:events2 += ['flobby ' .. expand('')]]=]), + fn.execute('autocmd BufEnter') + ) + command('bufdo "') + eq({ 'baz', 'bar', 'boop', 'floob' }, eval('g:events1')) + eq({ 'bazinga', 'flobby bar', 'foo', 'flobby foo' }, eval('g:events2')) + + -- Also make sure it doesn't repeat the group/event name or pattern for each printed event. + -- Do however repeat the pattern if the user specified it multiple times to be printed. + -- These conditions aim to make the output consistent with Vim. + eq( + dedent([=[ + + --- Autocommands --- + BufEnter + + let g:events1 += [expand('')] + bar let g:events1 += [expand('')] + bar let g:events1 += [expand('')] + flobby BufEnter + foo let g:events2 += [expand('')] + let g:events2 += ['flobby ' .. expand('')] + foo let g:events2 += [expand('')] + let g:events2 += ['flobby ' .. expand('')] + BufEnter + + let g:events1 += [expand('')] + + let g:events1 += [expand('')] + + let g:events1 += [expand('')]]=]), + fn.execute('autocmd BufEnter ,bar,bar,foo,foo,,,') + ) + end) end) diff --git a/test/functional/autocmd/show_spec.lua b/test/functional/autocmd/show_spec.lua index fcac706349..395e6d5144 100644 --- a/test/functional/autocmd/show_spec.lua +++ b/test/functional/autocmd/show_spec.lua @@ -188,6 +188,18 @@ describe(':autocmd', function() B echo "B3"]]), fn.execute('autocmd test_3 * B') ) + eq( + dedent([[ + + --- Autocommands ---]]), + fn.execute('autocmd * ,') + ) + eq( + dedent([[ + + --- Autocommands ---]]), + fn.execute('autocmd * ,,,') + ) end) it('should skip consecutive patterns', function()