1 // This is an open source non-commercial project. Dear PVS-Studio, please check
2 // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3
4 // autocmd.c: Autocommand related functions
5
6 #include "nvim/api/private/helpers.h"
7 #include "nvim/ascii.h"
8 #include "nvim/autocmd.h"
9 #include "nvim/buffer.h"
10 #include "nvim/charset.h"
11 #include "nvim/cursor.h"
12 #include "nvim/edit.h"
13 #include "nvim/eval.h"
14 #include "nvim/eval/userfunc.h"
15 #include "nvim/ex_docmd.h"
16 #include "nvim/fileio.h"
17 #include "nvim/getchar.h"
18 #include "nvim/misc1.h"
19 #include "nvim/option.h"
20 #include "nvim/regexp.h"
21 #include "nvim/search.h"
22 #include "nvim/state.h"
23 #include "nvim/ui_compositor.h"
24 #include "nvim/vim.h"
25
26 #ifdef INCLUDE_GENERATED_DECLARATIONS
27 # include "auevents_name_map.generated.h"
28 # include "autocmd.c.generated.h"
29 #endif
30
31 //
32 // The autocommands are stored in a list for each event.
33 // Autocommands for the same pattern, that are consecutive, are joined
34 // together, to avoid having to match the pattern too often.
35 // The result is an array of Autopat lists, which point to AutoCmd lists:
36 //
37 // last_autopat[0] -----------------------------+
38 // V
39 // first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
40 // Autopat.cmds Autopat.cmds
41 // | |
42 // V V
43 // AutoCmd.next AutoCmd.next
44 // | |
45 // V V
46 // AutoCmd.next NULL
47 // |
48 // V
49 // NULL
50 //
51 // last_autopat[1] --------+
52 // V
53 // first_autopat[1] --> Autopat.next --> NULL
54 // Autopat.cmds
55 // |
56 // V
57 // AutoCmd.next
58 // |
59 // V
60 // NULL
61 // etc.
62 //
63 // The order of AutoCmds is important, this is the order in which they were
64 // defined and will have to be executed.
65 //
66
67 // Code for automatic commands.
68 static AutoPatCmd *active_apc_list = NULL; // stack of active autocommands
69
70 /// List of autocmd group names
71 static garray_T augroups = { 0, 0, sizeof(char_u *), 10, NULL };
72 #define AUGROUP_NAME(i) (((char **)augroups.ga_data)[i])
73 #define BUFLOCAL_PAT_LEN 25
74
75 // use get_deleted_augroup() to get this
76 static const char *deleted_augroup = NULL;
77
78 // The ID of the current group. Group 0 is the default one.
79 static int current_augroup = AUGROUP_DEFAULT;
80
81 static int au_need_clean = false; // need to delete marked patterns
82
83 static event_T last_event;
84 static int last_group;
85 static int autocmd_blocked = 0; // block all autocmds
86
87 static bool autocmd_nested = false;
88 static bool autocmd_include_groups = false;
89
90 static char_u *old_termresponse = NULL;
91
get_deleted_augroup(void)92 static inline const char *get_deleted_augroup(void) FUNC_ATTR_ALWAYS_INLINE
93 {
94 if (deleted_augroup == NULL) {
95 deleted_augroup = _("--Deleted--");
96 }
97 return deleted_augroup;
98 }
99
100 // Show the autocommands for one AutoPat.
show_autocmd(AutoPat * ap,event_T event)101 static void show_autocmd(AutoPat *ap, event_T event)
102 {
103 AutoCmd *ac;
104
105 // Check for "got_int" (here and at various places below), which is set
106 // when "q" has been hit for the "--more--" prompt
107 if (got_int) {
108 return;
109 }
110 // pattern has been removed
111 if (ap->pat == NULL) {
112 return;
113 }
114
115 msg_putchar('\n');
116 if (got_int) {
117 return;
118 }
119 if (event != last_event || ap->group != last_group) {
120 if (ap->group != AUGROUP_DEFAULT) {
121 if (AUGROUP_NAME(ap->group) == NULL) {
122 msg_puts_attr(get_deleted_augroup(), HL_ATTR(HLF_E));
123 } else {
124 msg_puts_attr(AUGROUP_NAME(ap->group), HL_ATTR(HLF_T));
125 }
126 msg_puts(" ");
127 }
128 msg_puts_attr(event_nr2name(event), HL_ATTR(HLF_T));
129 last_event = event;
130 last_group = ap->group;
131 msg_putchar('\n');
132 if (got_int) {
133 return;
134 }
135 }
136 msg_col = 4;
137 msg_outtrans(ap->pat);
138
139 for (ac = ap->cmds; ac != NULL; ac = ac->next) {
140 if (ac->cmd == NULL) { // skip removed commands
141 continue;
142 }
143 if (msg_col >= 14) {
144 msg_putchar('\n');
145 }
146 msg_col = 14;
147 if (got_int) {
148 return;
149 }
150 msg_outtrans(ac->cmd);
151 if (p_verbose > 0) {
152 last_set_msg(ac->script_ctx);
153 }
154 if (got_int) {
155 return;
156 }
157 if (ac->next != NULL) {
158 msg_putchar('\n');
159 if (got_int) {
160 return;
161 }
162 }
163 }
164 }
165
166 // Mark an autocommand handler for deletion.
au_remove_pat(AutoPat * ap)167 static void au_remove_pat(AutoPat *ap)
168 {
169 XFREE_CLEAR(ap->pat);
170 ap->buflocal_nr = -1;
171 au_need_clean = true;
172 }
173
174 // Mark all commands for a pattern for deletion.
au_remove_cmds(AutoPat * ap)175 static void au_remove_cmds(AutoPat *ap)
176 {
177 for (AutoCmd *ac = ap->cmds; ac != NULL; ac = ac->next) {
178 XFREE_CLEAR(ac->cmd);
179 }
180 au_need_clean = true;
181 }
182
183 // Delete one command from an autocmd pattern.
au_del_cmd(AutoCmd * ac)184 static void au_del_cmd(AutoCmd *ac)
185 {
186 XFREE_CLEAR(ac->cmd);
187 au_need_clean = true;
188 }
189
190 /// Cleanup autocommands and patterns that have been deleted.
191 /// This is only done when not executing autocommands.
au_cleanup(void)192 static void au_cleanup(void)
193 {
194 AutoPat *ap, **prev_ap;
195 event_T event;
196
197 if (autocmd_busy || !au_need_clean) {
198 return;
199 }
200
201 // Loop over all events.
202 for (event = (event_T)0; (int)event < NUM_EVENTS;
203 event = (event_T)((int)event + 1)) {
204 // Loop over all autocommand patterns.
205 prev_ap = &(first_autopat[(int)event]);
206 for (ap = *prev_ap; ap != NULL; ap = *prev_ap) {
207 bool has_cmd = false;
208
209 // Loop over all commands for this pattern.
210 AutoCmd **prev_ac = &(ap->cmds);
211 for (AutoCmd *ac = *prev_ac; ac != NULL; ac = *prev_ac) {
212 // Remove the command if the pattern is to be deleted or when
213 // the command has been marked for deletion.
214 if (ap->pat == NULL || ac->cmd == NULL) {
215 *prev_ac = ac->next;
216 xfree(ac->cmd);
217 xfree(ac);
218 } else {
219 has_cmd = true;
220 prev_ac = &(ac->next);
221 }
222 }
223
224 if (ap->pat != NULL && !has_cmd) {
225 // Pattern was not marked for deletion, but all of its commands were.
226 // So mark the pattern for deletion.
227 au_remove_pat(ap);
228 }
229
230 // Remove the pattern if it has been marked for deletion.
231 if (ap->pat == NULL) {
232 if (ap->next == NULL) {
233 if (prev_ap == &(first_autopat[(int)event])) {
234 last_autopat[(int)event] = NULL;
235 } else {
236 // this depends on the "next" field being the first in
237 // the struct
238 last_autopat[(int)event] = (AutoPat *)prev_ap;
239 }
240 }
241 *prev_ap = ap->next;
242 vim_regfree(ap->reg_prog);
243 xfree(ap);
244 } else {
245 prev_ap = &(ap->next);
246 }
247 }
248 }
249
250 au_need_clean = false;
251 }
252
253 // Called when buffer is freed, to remove/invalidate related buffer-local
254 // autocmds.
aubuflocal_remove(buf_T * buf)255 void aubuflocal_remove(buf_T *buf)
256 {
257 AutoPat *ap;
258 event_T event;
259 AutoPatCmd *apc;
260
261 // invalidate currently executing autocommands
262 for (apc = active_apc_list; apc; apc = apc->next) {
263 if (buf->b_fnum == apc->arg_bufnr) {
264 apc->arg_bufnr = 0;
265 }
266 }
267
268 // invalidate buflocals looping through events
269 for (event = (event_T)0; (int)event < NUM_EVENTS;
270 event = (event_T)((int)event + 1)) {
271 // loop over all autocommand patterns
272 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
273 if (ap->buflocal_nr == buf->b_fnum) {
274 au_remove_pat(ap);
275 if (p_verbose >= 6) {
276 verbose_enter();
277 smsg(_("auto-removing autocommand: %s <buffer=%d>"),
278 event_nr2name(event), buf->b_fnum);
279 verbose_leave();
280 }
281 }
282 }
283 }
284 au_cleanup();
285 }
286
287 // Add an autocmd group name.
288 // Return its ID. Returns AUGROUP_ERROR (< 0) for error.
au_new_group(char_u * name)289 static int au_new_group(char_u *name)
290 {
291 int i = au_find_group(name);
292 if (i == AUGROUP_ERROR) { // the group doesn't exist yet, add it.
293 // First try using a free entry.
294 for (i = 0; i < augroups.ga_len; i++) {
295 if (AUGROUP_NAME(i) == NULL) {
296 break;
297 }
298 }
299 if (i == augroups.ga_len) {
300 ga_grow(&augroups, 1);
301 }
302
303 AUGROUP_NAME(i) = xstrdup((char *)name);
304 if (i == augroups.ga_len) {
305 augroups.ga_len++;
306 }
307 }
308
309 return i;
310 }
311
au_del_group(char_u * name)312 static void au_del_group(char_u *name)
313 {
314 int i = au_find_group(name);
315 if (i == AUGROUP_ERROR) { // the group doesn't exist
316 semsg(_("E367: No such group: \"%s\""), name);
317 } else if (i == current_augroup) {
318 emsg(_("E936: Cannot delete the current group"));
319 } else {
320 event_T event;
321 AutoPat *ap;
322 int in_use = false;
323
324 for (event = (event_T)0; (int)event < NUM_EVENTS;
325 event = (event_T)((int)event + 1)) {
326 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
327 if (ap->group == i && ap->pat != NULL) {
328 give_warning((char_u *)_("W19: Deleting augroup that is still in use"), true);
329 in_use = true;
330 event = NUM_EVENTS;
331 break;
332 }
333 }
334 }
335 xfree(AUGROUP_NAME(i));
336 if (in_use) {
337 AUGROUP_NAME(i) = (char *)get_deleted_augroup();
338 } else {
339 AUGROUP_NAME(i) = NULL;
340 }
341 }
342 }
343
344 /// Find the ID of an autocmd group name.
345 ///
346 /// @param name augroup name
347 ///
348 /// @return the ID or AUGROUP_ERROR (< 0) for error.
au_find_group(const char_u * name)349 static int au_find_group(const char_u *name)
350 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
351 {
352 for (int i = 0; i < augroups.ga_len; i++) {
353 if (AUGROUP_NAME(i) != NULL && AUGROUP_NAME(i) != get_deleted_augroup()
354 && STRCMP(AUGROUP_NAME(i), name) == 0) {
355 return i;
356 }
357 }
358 return AUGROUP_ERROR;
359 }
360
361 /// Return true if augroup "name" exists.
362 ///
363 /// @param name augroup name
au_has_group(const char_u * name)364 bool au_has_group(const char_u *name)
365 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
366 {
367 return au_find_group(name) != AUGROUP_ERROR;
368 }
369
370 /// ":augroup {name}".
do_augroup(char_u * arg,int del_group)371 void do_augroup(char_u *arg, int del_group)
372 {
373 if (del_group) {
374 if (*arg == NUL) {
375 emsg(_(e_argreq));
376 } else {
377 au_del_group(arg);
378 }
379 } else if (STRICMP(arg, "end") == 0) { // ":aug end": back to group 0
380 current_augroup = AUGROUP_DEFAULT;
381 } else if (*arg) { // ":aug xxx": switch to group xxx
382 int i = au_new_group(arg);
383 if (i != AUGROUP_ERROR) {
384 current_augroup = i;
385 }
386 } else { // ":aug": list the group names
387 msg_start();
388 for (int i = 0; i < augroups.ga_len; i++) {
389 if (AUGROUP_NAME(i) != NULL) {
390 msg_puts(AUGROUP_NAME(i));
391 msg_puts(" ");
392 }
393 }
394 msg_clr_eos();
395 msg_end();
396 }
397 }
398
399 #if defined(EXITFREE)
free_all_autocmds(void)400 void free_all_autocmds(void)
401 {
402 for (current_augroup = -1; current_augroup < augroups.ga_len;
403 current_augroup++) {
404 do_autocmd((char_u *)"", true);
405 }
406
407 for (int i = 0; i < augroups.ga_len; i++) {
408 char *const s = ((char **)(augroups.ga_data))[i];
409 if ((const char *)s != get_deleted_augroup()) {
410 xfree(s);
411 }
412 }
413 ga_clear(&augroups);
414 }
415 #endif
416
417 // Return the event number for event name "start".
418 // Return NUM_EVENTS if the event name was not found.
419 // Return a pointer to the next event name in "end".
event_name2nr(const char_u * start,char_u ** end)420 static event_T event_name2nr(const char_u *start, char_u **end)
421 {
422 const char_u *p;
423 int i;
424 int len;
425
426 // the event name ends with end of line, '|', a blank or a comma
427 for (p = start; *p && !ascii_iswhite(*p) && *p != ',' && *p != '|'; p++) {
428 }
429 for (i = 0; event_names[i].name != NULL; i++) {
430 len = (int)event_names[i].len;
431 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0) {
432 break;
433 }
434 }
435 if (*p == ',') {
436 p++;
437 }
438 *end = (char_u *)p;
439 if (event_names[i].name == NULL) {
440 return NUM_EVENTS;
441 }
442 return event_names[i].event;
443 }
444
445 /// Return the name for event
446 ///
447 /// @param[in] event Event to return name for.
448 ///
449 /// @return Event name, static string. Returns "Unknown" for unknown events.
event_nr2name(event_T event)450 static const char *event_nr2name(event_T event)
451 FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST
452 {
453 int i;
454
455 for (i = 0; event_names[i].name != NULL; i++) {
456 if (event_names[i].event == event) {
457 return event_names[i].name;
458 }
459 }
460 return "Unknown";
461 }
462
463 /// Scan over the events. "*" stands for all events.
464 /// true when group name was found
find_end_event(char_u * arg,int have_group)465 static char_u *find_end_event(char_u *arg, int have_group)
466 {
467 char_u *pat;
468 char_u *p;
469
470 if (*arg == '*') {
471 if (arg[1] && !ascii_iswhite(arg[1])) {
472 semsg(_("E215: Illegal character after *: %s"), arg);
473 return NULL;
474 }
475 pat = arg + 1;
476 } else {
477 for (pat = arg; *pat && *pat != '|' && !ascii_iswhite(*pat); pat = p) {
478 if ((int)event_name2nr(pat, &p) >= NUM_EVENTS) {
479 if (have_group) {
480 semsg(_("E216: No such event: %s"), pat);
481 } else {
482 semsg(_("E216: No such group or event: %s"), pat);
483 }
484 return NULL;
485 }
486 }
487 }
488 return pat;
489 }
490
491 /// Return true if "event" is included in 'eventignore'.
492 ///
493 /// @param event event to check
event_ignored(event_T event)494 static bool event_ignored(event_T event)
495 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
496 {
497 char_u *p = p_ei;
498
499 while (*p != NUL) {
500 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ',')) {
501 return true;
502 }
503 if (event_name2nr(p, &p) == event) {
504 return true;
505 }
506 }
507
508 return false;
509 }
510
511 // Return OK when the contents of p_ei is valid, FAIL otherwise.
check_ei(void)512 int check_ei(void)
513 {
514 char_u *p = p_ei;
515
516 while (*p) {
517 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ',')) {
518 p += 3;
519 if (*p == ',') {
520 p++;
521 }
522 } else if (event_name2nr(p, &p) == NUM_EVENTS) {
523 return FAIL;
524 }
525 }
526
527 return OK;
528 }
529
530 // Add "what" to 'eventignore' to skip loading syntax highlighting for every
531 // buffer loaded into the window. "what" must start with a comma.
532 // Returns the old value of 'eventignore' in allocated memory.
au_event_disable(char * what)533 char_u *au_event_disable(char *what)
534 {
535 char_u *new_ei;
536 char_u *save_ei;
537
538 save_ei = vim_strsave(p_ei);
539 new_ei = vim_strnsave(p_ei, STRLEN(p_ei) + STRLEN(what));
540 if (*what == ',' && *p_ei == NUL) {
541 STRCPY(new_ei, what + 1);
542 } else {
543 STRCAT(new_ei, what);
544 }
545 set_string_option_direct("ei", -1, new_ei, OPT_FREE, SID_NONE);
546 xfree(new_ei);
547
548 return save_ei;
549 }
550
au_event_restore(char_u * old_ei)551 void au_event_restore(char_u *old_ei)
552 {
553 if (old_ei != NULL) {
554 set_string_option_direct("ei", -1, old_ei, OPT_FREE, SID_NONE);
555 xfree(old_ei);
556 }
557 }
558
559 // Implements :autocmd.
560 // Defines an autocmd (does not execute; cf. apply_autocmds_group).
561 //
562 // Can be used in the following ways:
563 //
564 // :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
565 // will be automatically executed for <event>
566 // when editing a file matching <pat>, in
567 // the current group.
568 // :autocmd <event> <pat> Show the autocommands associated with
569 // <event> and <pat>.
570 // :autocmd <event> Show the autocommands associated with
571 // <event>.
572 // :autocmd Show all autocommands.
573 // :autocmd! <event> <pat> <cmd> Remove all autocommands associated with
574 // <event> and <pat>, and add the command
575 // <cmd>, for the current group.
576 // :autocmd! <event> <pat> Remove all autocommands associated with
577 // <event> and <pat> for the current group.
578 // :autocmd! <event> Remove all autocommands associated with
579 // <event> for the current group.
580 // :autocmd! Remove ALL autocommands for the current
581 // group.
582 //
583 // Multiple events and patterns may be given separated by commas. Here are
584 // some examples:
585 // :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
586 // :autocmd bufleave * set tw=79 nosmartindent ic infercase
587 //
588 // :autocmd * *.c show all autocommands for *.c files.
589 //
590 // Mostly a {group} argument can optionally appear before <event>.
do_autocmd(char_u * arg_in,int forceit)591 void do_autocmd(char_u *arg_in, int forceit)
592 {
593 char_u *arg = arg_in;
594 char_u *pat;
595 char_u *envpat = NULL;
596 char_u *cmd;
597 int need_free = false;
598 int nested = false;
599 bool once = false;
600 int group;
601
602 if (*arg == '|') {
603 arg = (char_u *)"";
604 group = AUGROUP_ALL; // no argument, use all groups
605 } else {
606 // Check for a legal group name. If not, use AUGROUP_ALL.
607 group = au_get_grouparg(&arg);
608 }
609
610 // Scan over the events.
611 // If we find an illegal name, return here, don't do anything.
612 pat = find_end_event(arg, group != AUGROUP_ALL);
613 if (pat == NULL) {
614 return;
615 }
616
617 pat = skipwhite(pat);
618 if (*pat == '|') {
619 pat = (char_u *)"";
620 cmd = (char_u *)"";
621 } else {
622 // Scan over the pattern. Put a NUL at the end.
623 cmd = pat;
624 while (*cmd && (!ascii_iswhite(*cmd) || cmd[-1] == '\\')) {
625 cmd++;
626 }
627 if (*cmd) {
628 *cmd++ = NUL;
629 }
630
631 // Expand environment variables in the pattern. Set 'shellslash', we want
632 // forward slashes here.
633 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL) {
634 #ifdef BACKSLASH_IN_FILENAME
635 int p_ssl_save = p_ssl;
636
637 p_ssl = true;
638 #endif
639 envpat = expand_env_save(pat);
640 #ifdef BACKSLASH_IN_FILENAME
641 p_ssl = p_ssl_save;
642 #endif
643 if (envpat != NULL) {
644 pat = envpat;
645 }
646 }
647
648 cmd = skipwhite(cmd);
649 for (size_t i = 0; i < 2; i++) {
650 if (*cmd != NUL) {
651 // Check for "++once" flag.
652 if (STRNCMP(cmd, "++once", 6) == 0 && ascii_iswhite(cmd[6])) {
653 if (once) {
654 semsg(_(e_duparg2), "++once");
655 }
656 once = true;
657 cmd = skipwhite(cmd + 6);
658 }
659
660 // Check for "++nested" flag.
661 if ((STRNCMP(cmd, "++nested", 8) == 0 && ascii_iswhite(cmd[8]))) {
662 if (nested) {
663 semsg(_(e_duparg2), "++nested");
664 }
665 nested = true;
666 cmd = skipwhite(cmd + 8);
667 }
668
669 // Check for the old (deprecated) "nested" flag.
670 if (STRNCMP(cmd, "nested", 6) == 0 && ascii_iswhite(cmd[6])) {
671 if (nested) {
672 semsg(_(e_duparg2), "nested");
673 }
674 nested = true;
675 cmd = skipwhite(cmd + 6);
676 }
677 }
678 }
679
680 // Find the start of the commands.
681 // Expand <sfile> in it.
682 if (*cmd != NUL) {
683 cmd = expand_sfile(cmd);
684 if (cmd == NULL) { // some error
685 return;
686 }
687 need_free = true;
688 }
689 }
690
691 // Print header when showing autocommands.
692 if (!forceit && *cmd == NUL) {
693 // Highlight title
694 msg_puts_title(_("\n--- Autocommands ---"));
695 }
696
697 // Loop over the events.
698 last_event = (event_T)-1; // for listing the event name
699 last_group = AUGROUP_ERROR; // for listing the group name
700 if (*arg == '*' || *arg == NUL || *arg == '|') {
701 if (!forceit && *cmd != NUL) {
702 emsg(_(e_cannot_define_autocommands_for_all_events));
703 } else {
704 for (event_T event = (event_T)0; event < NUM_EVENTS;
705 event = (event_T)(event + 1)) {
706 if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group)
707 == FAIL) {
708 break;
709 }
710 }
711 }
712 } else {
713 while (*arg && *arg != '|' && !ascii_iswhite(*arg)) {
714 event_T event = event_name2nr(arg, &arg);
715 assert(event < NUM_EVENTS);
716 if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group)
717 == FAIL) {
718 break;
719 }
720 }
721 }
722
723 if (need_free) {
724 xfree(cmd);
725 }
726 xfree(envpat);
727 }
728
729 // Find the group ID in a ":autocmd" or ":doautocmd" argument.
730 // The "argp" argument is advanced to the following argument.
731 //
732 // Returns the group ID or AUGROUP_ALL.
au_get_grouparg(char_u ** argp)733 static int au_get_grouparg(char_u **argp)
734 {
735 char_u *group_name;
736 char_u *p;
737 char_u *arg = *argp;
738 int group = AUGROUP_ALL;
739
740 for (p = arg; *p && !ascii_iswhite(*p) && *p != '|'; p++) {
741 }
742 if (p > arg) {
743 group_name = vim_strnsave(arg, (size_t)(p - arg));
744 group = au_find_group(group_name);
745 if (group == AUGROUP_ERROR) {
746 group = AUGROUP_ALL; // no match, use all groups
747 } else {
748 *argp = skipwhite(p); // match, skip over group name
749 }
750 xfree(group_name);
751 }
752 return group;
753 }
754
755 // do_autocmd() for one event.
756 // Defines an autocmd (does not execute; cf. apply_autocmds_group).
757 //
758 // If *pat == NUL: do for all patterns.
759 // If *cmd == NUL: show entries.
760 // If forceit == true: delete entries.
761 // If group is not AUGROUP_ALL: only use this group.
do_autocmd_event(event_T event,char_u * pat,bool once,int nested,char_u * cmd,int forceit,int group)762 static int do_autocmd_event(event_T event, char_u *pat, bool once, int nested, char_u *cmd,
763 int forceit, int group)
764 {
765 AutoPat *ap;
766 AutoPat **prev_ap;
767 AutoCmd *ac;
768 AutoCmd **prev_ac;
769 int brace_level;
770 char_u *endpat;
771 int findgroup;
772 int allgroups;
773 int patlen;
774 int is_buflocal;
775 int buflocal_nr;
776 char_u buflocal_pat[BUFLOCAL_PAT_LEN]; // for "<buffer=X>"
777
778 if (group == AUGROUP_ALL) {
779 findgroup = current_augroup;
780 } else {
781 findgroup = group;
782 }
783 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
784
785 // Show or delete all patterns for an event.
786 if (*pat == NUL) {
787 for (ap = first_autopat[event]; ap != NULL; ap = ap->next) {
788 if (forceit) { // delete the AutoPat, if it's in the current group
789 if (ap->group == findgroup) {
790 au_remove_pat(ap);
791 }
792 } else if (group == AUGROUP_ALL || ap->group == group) {
793 show_autocmd(ap, event);
794 }
795 }
796 }
797
798 // Loop through all the specified patterns.
799 for (; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat)) {
800 // Find end of the pattern.
801 // Watch out for a comma in braces, like "*.\{obj,o\}".
802 endpat = pat;
803 // ignore single comma
804 if (*endpat == ',') {
805 continue;
806 }
807 brace_level = 0;
808 for (; *endpat && (*endpat != ',' || brace_level || endpat[-1] == '\\');
809 endpat++) {
810 if (*endpat == '{') {
811 brace_level++;
812 } else if (*endpat == '}') {
813 brace_level--;
814 }
815 }
816 patlen = (int)(endpat - pat);
817
818 // detect special <buflocal[=X]> buffer-local patterns
819 is_buflocal = false;
820 buflocal_nr = 0;
821
822 if (patlen >= 8 && STRNCMP(pat, "<buffer", 7) == 0
823 && pat[patlen - 1] == '>') {
824 // "<buffer...>": Error will be printed only for addition.
825 // printing and removing will proceed silently.
826 is_buflocal = true;
827 if (patlen == 8) {
828 // "<buffer>"
829 buflocal_nr = curbuf->b_fnum;
830 } else if (patlen > 9 && pat[7] == '=') {
831 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13) == 0) {
832 // "<buffer=abuf>"
833 buflocal_nr = autocmd_bufnr;
834 } else if (skipdigits(pat + 8) == pat + patlen - 1) {
835 // "<buffer=123>"
836 buflocal_nr = atoi((char *)pat + 8);
837 }
838 }
839 }
840
841 if (is_buflocal) {
842 // normalize pat into standard "<buffer>#N" form
843 snprintf((char *)buflocal_pat,
844 BUFLOCAL_PAT_LEN,
845 "<buffer=%d>",
846 buflocal_nr);
847
848 pat = buflocal_pat; // can modify pat and patlen
849 patlen = (int)STRLEN(buflocal_pat); // but not endpat
850 }
851
852 // Find AutoPat entries with this pattern. When adding a command it
853 // always goes at or after the last one, so start at the end.
854 if (!forceit && *cmd != NUL && last_autopat[(int)event] != NULL) {
855 prev_ap = &last_autopat[(int)event];
856 } else {
857 prev_ap = &first_autopat[(int)event];
858 }
859 while ((ap = *prev_ap) != NULL) {
860 if (ap->pat != NULL) {
861 // Accept a pattern when:
862 // - a group was specified and it's that group, or a group was
863 // not specified and it's the current group, or a group was
864 // not specified and we are listing
865 // - the length of the pattern matches
866 // - the pattern matches.
867 // For <buffer[=X]>, this condition works because we normalize
868 // all buffer-local patterns.
869 if ((allgroups || ap->group == findgroup) && ap->patlen == patlen
870 && STRNCMP(pat, ap->pat, patlen) == 0) {
871 // Remove existing autocommands.
872 // If adding any new autocmd's for this AutoPat, don't
873 // delete the pattern from the autopat list, append to
874 // this list.
875 if (forceit) {
876 if (*cmd != NUL && ap->next == NULL) {
877 au_remove_cmds(ap);
878 break;
879 }
880 au_remove_pat(ap);
881 } else if (*cmd == NUL) {
882 // Show autocmd's for this autopat, or buflocals <buffer=X>
883 show_autocmd(ap, event);
884 } else if (ap->next == NULL) {
885 // Add autocmd to this autopat, if it's the last one.
886 break;
887 }
888 }
889 }
890 prev_ap = &ap->next;
891 }
892
893 // Add a new command.
894 if (*cmd != NUL) {
895 // If the pattern we want to add a command to does appear at the
896 // end of the list (or not is not in the list at all), add the
897 // pattern at the end of the list.
898 if (ap == NULL) {
899 // refuse to add buffer-local ap if buffer number is invalid
900 if (is_buflocal
901 && (buflocal_nr == 0 || buflist_findnr(buflocal_nr) == NULL)) {
902 semsg(_("E680: <buffer=%d>: invalid buffer number "), buflocal_nr);
903 return FAIL;
904 }
905
906 ap = xmalloc(sizeof(AutoPat));
907 ap->pat = vim_strnsave(pat, (size_t)patlen);
908 ap->patlen = patlen;
909
910 if (is_buflocal) {
911 ap->buflocal_nr = buflocal_nr;
912 ap->reg_prog = NULL;
913 } else {
914 char_u *reg_pat;
915
916 ap->buflocal_nr = 0;
917 reg_pat = file_pat_to_reg_pat(pat, endpat, &ap->allow_dirs, true);
918 if (reg_pat != NULL) {
919 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
920 }
921 xfree(reg_pat);
922 if (reg_pat == NULL || ap->reg_prog == NULL) {
923 xfree(ap->pat);
924 xfree(ap);
925 return FAIL;
926 }
927 }
928 ap->cmds = NULL;
929 *prev_ap = ap;
930 last_autopat[(int)event] = ap;
931 ap->next = NULL;
932 if (group == AUGROUP_ALL) {
933 ap->group = current_augroup;
934 } else {
935 ap->group = group;
936 }
937 }
938
939 // Add the autocmd at the end of the AutoCmd list.
940 prev_ac = &(ap->cmds);
941 while ((ac = *prev_ac) != NULL) {
942 prev_ac = &ac->next;
943 }
944 ac = xmalloc(sizeof(AutoCmd));
945 ac->cmd = vim_strsave(cmd);
946 ac->script_ctx = current_sctx;
947 ac->script_ctx.sc_lnum += sourcing_lnum;
948 ac->next = NULL;
949 *prev_ac = ac;
950 ac->once = once;
951 ac->nested = nested;
952 }
953 }
954
955 au_cleanup(); // may really delete removed patterns/commands now
956 return OK;
957 }
958
959 /// Implementation of ":doautocmd [group] event [fname]".
960 /// Return OK for success, FAIL for failure;
961 ///
962 /// @param do_msg give message for no matching autocmds?
do_doautocmd(char_u * arg,bool do_msg,bool * did_something)963 int do_doautocmd(char_u *arg, bool do_msg, bool *did_something)
964 {
965 char_u *fname;
966 int nothing_done = true;
967 int group;
968
969 if (did_something != NULL) {
970 *did_something = false;
971 }
972
973 // Check for a legal group name. If not, use AUGROUP_ALL.
974 group = au_get_grouparg(&arg);
975
976 if (*arg == '*') {
977 emsg(_("E217: Can't execute autocommands for ALL events"));
978 return FAIL;
979 }
980
981 // Scan over the events.
982 // If we find an illegal name, return here, don't do anything.
983 fname = find_end_event(arg, group != AUGROUP_ALL);
984 if (fname == NULL) {
985 return FAIL;
986 }
987
988 fname = skipwhite(fname);
989
990 // Loop over the events.
991 while (*arg && !ends_excmd(*arg) && !ascii_iswhite(*arg)) {
992 if (apply_autocmds_group(event_name2nr(arg, &arg), fname, NULL, true, group,
993 curbuf, NULL)) {
994 nothing_done = false;
995 }
996 }
997
998 if (nothing_done && do_msg) {
999 msg(_("No matching autocommands"));
1000 }
1001 if (did_something != NULL) {
1002 *did_something = !nothing_done;
1003 }
1004
1005 return aborting() ? FAIL : OK;
1006 }
1007
1008 // ":doautoall": execute autocommands for each loaded buffer.
ex_doautoall(exarg_T * eap)1009 void ex_doautoall(exarg_T *eap)
1010 {
1011 int retval = OK;
1012 aco_save_T aco;
1013 char_u *arg = eap->arg;
1014 int call_do_modelines = check_nomodeline(&arg);
1015 bufref_T bufref;
1016 bool did_aucmd;
1017
1018 // This is a bit tricky: For some commands curwin->w_buffer needs to be
1019 // equal to curbuf, but for some buffers there may not be a window.
1020 // So we change the buffer for the current window for a moment. This
1021 // gives problems when the autocommands make changes to the list of
1022 // buffers or windows...
1023 FOR_ALL_BUFFERS(buf) {
1024 // Only do loaded buffers and skip the current buffer, it's done last.
1025 if (buf->b_ml.ml_mfp == NULL || buf == curbuf) {
1026 continue;
1027 }
1028 // Find a window for this buffer and save some values.
1029 aucmd_prepbuf(&aco, buf);
1030 set_bufref(&bufref, buf);
1031
1032 // execute the autocommands for this buffer
1033 retval = do_doautocmd(arg, false, &did_aucmd);
1034
1035 if (call_do_modelines && did_aucmd) {
1036 // Execute the modeline settings, but don't set window-local
1037 // options if we are using the current window for another
1038 // buffer.
1039 do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
1040 }
1041
1042 // restore the current window
1043 aucmd_restbuf(&aco);
1044
1045 // Stop if there is some error or buffer was deleted.
1046 if (retval == FAIL || !bufref_valid(&bufref)) {
1047 retval = FAIL;
1048 break;
1049 }
1050 }
1051
1052 // Execute autocommands for the current buffer last.
1053 if (retval == OK) {
1054 (void)do_doautocmd(arg, false, &did_aucmd);
1055 if (call_do_modelines && did_aucmd) {
1056 do_modelines(0);
1057 }
1058 }
1059
1060 check_cursor(); // just in case lines got deleted
1061 }
1062
1063 /// Check *argp for <nomodeline>. When it is present return false, otherwise
1064 /// return true and advance *argp to after it. Thus do_modelines() should be
1065 /// called when true is returned.
1066 ///
1067 /// @param[in,out] argp argument string
check_nomodeline(char_u ** argp)1068 bool check_nomodeline(char_u **argp)
1069 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
1070 {
1071 if (STRNCMP(*argp, "<nomodeline>", 12) == 0) {
1072 *argp = skipwhite(*argp + 12);
1073 return false;
1074 }
1075 return true;
1076 }
1077
1078 /// Prepare for executing autocommands for (hidden) buffer `buf`.
1079 /// If the current buffer is not in any visible window, put it in a temporary
1080 /// floating window `aucmd_win`.
1081 /// Set `curbuf` and `curwin` to match `buf`.
1082 ///
1083 /// @param aco structure to save values in
1084 /// @param buf new curbuf
aucmd_prepbuf(aco_save_T * aco,buf_T * buf)1085 void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
1086 {
1087 win_T *win;
1088 bool need_append = true; // Append `aucmd_win` to the window list.
1089
1090 // Find a window that is for the new buffer
1091 if (buf == curbuf) { // be quick when buf is curbuf
1092 win = curwin;
1093 } else {
1094 win = NULL;
1095 FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
1096 if (wp->w_buffer == buf) {
1097 win = wp;
1098 break;
1099 }
1100 }
1101 }
1102
1103 // Allocate the `aucmd_win` dummy floating window.
1104 if (win == NULL && aucmd_win == NULL) {
1105 win_alloc_aucmd_win();
1106 need_append = false;
1107 }
1108 if (win == NULL && aucmd_win_used) {
1109 // Strange recursive autocommand, fall back to using the current
1110 // window. Expect a few side effects...
1111 win = curwin;
1112 }
1113
1114 aco->save_curwin_handle = curwin->handle;
1115 aco->save_curbuf = curbuf;
1116 aco->save_prevwin_handle = prevwin == NULL ? 0 : prevwin->handle;
1117 if (win != NULL) {
1118 // There is a window for "buf" in the current tab page, make it the
1119 // curwin. This is preferred, it has the least side effects (esp. if
1120 // "buf" is curbuf).
1121 aco->use_aucmd_win = false;
1122 curwin = win;
1123 } else {
1124 // There is no window for "buf", use "aucmd_win". To minimize the side
1125 // effects, insert it in the current tab page.
1126 // Anything related to a window (e.g., setting folds) may have
1127 // unexpected results.
1128 aco->use_aucmd_win = true;
1129 aucmd_win_used = true;
1130 aucmd_win->w_buffer = buf;
1131 aucmd_win->w_s = &buf->b_s;
1132 buf->b_nwindows++;
1133 win_init_empty(aucmd_win); // set cursor and topline to safe values
1134
1135 // Make sure w_localdir and globaldir are NULL to avoid a chdir() in
1136 // win_enter_ext().
1137 XFREE_CLEAR(aucmd_win->w_localdir);
1138 aco->globaldir = globaldir;
1139 globaldir = NULL;
1140
1141 block_autocmds(); // We don't want BufEnter/WinEnter autocommands.
1142 if (need_append) {
1143 win_append(lastwin, aucmd_win);
1144 pmap_put(handle_T)(&window_handles, aucmd_win->handle, aucmd_win);
1145 win_config_float(aucmd_win, aucmd_win->w_float_config);
1146 }
1147 // Prevent chdir() call in win_enter_ext(), through do_autochdir()
1148 int save_acd = p_acd;
1149 p_acd = false;
1150 win_enter(aucmd_win, false);
1151 p_acd = save_acd;
1152 unblock_autocmds();
1153 curwin = aucmd_win;
1154 }
1155 curbuf = buf;
1156 aco->new_curwin_handle = curwin->handle;
1157 set_bufref(&aco->new_curbuf, curbuf);
1158 }
1159
1160 /// Cleanup after executing autocommands for a (hidden) buffer.
1161 /// Restore the window as it was (if possible).
1162 ///
1163 /// @param aco structure holding saved values
aucmd_restbuf(aco_save_T * aco)1164 void aucmd_restbuf(aco_save_T *aco)
1165 {
1166 if (aco->use_aucmd_win) {
1167 curbuf->b_nwindows--;
1168 // Find "aucmd_win", it can't be closed, but it may be in another tab page.
1169 // Do not trigger autocommands here.
1170 block_autocmds();
1171 if (curwin != aucmd_win) {
1172 FOR_ALL_TAB_WINDOWS(tp, wp) {
1173 if (wp == aucmd_win) {
1174 if (tp != curtab) {
1175 goto_tabpage_tp(tp, true, true);
1176 }
1177 win_goto(aucmd_win);
1178 goto win_found;
1179 }
1180 }
1181 }
1182 win_found:
1183
1184 win_remove(curwin, NULL);
1185 pmap_del(handle_T)(&window_handles, curwin->handle);
1186 if (curwin->w_grid_alloc.chars != NULL) {
1187 ui_comp_remove_grid(&curwin->w_grid_alloc);
1188 ui_call_win_hide(curwin->w_grid_alloc.handle);
1189 grid_free(&curwin->w_grid_alloc);
1190 }
1191
1192 aucmd_win_used = false;
1193 last_status(false); // may need to remove last status line
1194
1195 if (!valid_tabpage_win(curtab)) {
1196 // no valid window in current tabpage
1197 close_tabpage(curtab);
1198 }
1199
1200 unblock_autocmds();
1201
1202 win_T *const save_curwin = win_find_by_handle(aco->save_curwin_handle);
1203 if (save_curwin != NULL) {
1204 curwin = save_curwin;
1205 } else {
1206 // Hmm, original window disappeared. Just use the first one.
1207 curwin = firstwin;
1208 }
1209 prevwin = win_find_by_handle(aco->save_prevwin_handle);
1210 vars_clear(&aucmd_win->w_vars->dv_hashtab); // free all w: variables
1211 hash_init(&aucmd_win->w_vars->dv_hashtab); // re-use the hashtab
1212 curbuf = curwin->w_buffer;
1213
1214 xfree(globaldir);
1215 globaldir = aco->globaldir;
1216
1217 // the buffer contents may have changed
1218 check_cursor();
1219 if (curwin->w_topline > curbuf->b_ml.ml_line_count) {
1220 curwin->w_topline = curbuf->b_ml.ml_line_count;
1221 curwin->w_topfill = 0;
1222 }
1223 } else {
1224 // Restore curwin. Use the window ID, a window may have been closed
1225 // and the memory re-used for another one.
1226 win_T *const save_curwin = win_find_by_handle(aco->save_curwin_handle);
1227 if (save_curwin != NULL) {
1228 // Restore the buffer which was previously edited by curwin, if it was
1229 // changed, we are still the same window and the buffer is valid.
1230 if (curwin->handle == aco->new_curwin_handle
1231 && curbuf != aco->new_curbuf.br_buf
1232 && bufref_valid(&aco->new_curbuf)
1233 && aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL) {
1234 if (curwin->w_s == &curbuf->b_s) {
1235 curwin->w_s = &aco->new_curbuf.br_buf->b_s;
1236 }
1237 curbuf->b_nwindows--;
1238 curbuf = aco->new_curbuf.br_buf;
1239 curwin->w_buffer = curbuf;
1240 curbuf->b_nwindows++;
1241 }
1242
1243 curwin = save_curwin;
1244 curbuf = curwin->w_buffer;
1245 prevwin = win_find_by_handle(aco->save_prevwin_handle);
1246 // In case the autocommand moves the cursor to a position that does not
1247 // exist in curbuf
1248 check_cursor();
1249 }
1250 }
1251 }
1252
1253 /// Execute autocommands for "event" and file name "fname".
1254 ///
1255 /// @param event event that occurred
1256 /// @param fname filename, NULL or empty means use actual file name
1257 /// @param fname_io filename to use for <afile> on cmdline
1258 /// @param force When true, ignore autocmd_busy
1259 /// @param buf Buffer for <abuf>
1260 ///
1261 /// @return true if some commands were executed.
apply_autocmds(event_T event,char_u * fname,char_u * fname_io,bool force,buf_T * buf)1262 bool apply_autocmds(event_T event, char_u *fname, char_u *fname_io, bool force, buf_T *buf)
1263 {
1264 return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf,
1265 NULL);
1266 }
1267
1268 /// Like apply_autocmds(), but with extra "eap" argument. This takes care of
1269 /// setting v:filearg.
1270 ///
1271 /// @param event event that occurred
1272 /// @param fname NULL or empty means use actual file name
1273 /// @param fname_io fname to use for <afile> on cmdline
1274 /// @param force When true, ignore autocmd_busy
1275 /// @param buf Buffer for <abuf>
1276 /// @param exarg Ex command arguments
1277 ///
1278 /// @return true if some commands were executed.
apply_autocmds_exarg(event_T event,char_u * fname,char_u * fname_io,bool force,buf_T * buf,exarg_T * eap)1279 bool apply_autocmds_exarg(event_T event, char_u *fname, char_u *fname_io, bool force, buf_T *buf,
1280 exarg_T *eap)
1281 {
1282 return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf,
1283 eap);
1284 }
1285
1286 /// Like apply_autocmds(), but handles the caller's retval. If the script
1287 /// processing is being aborted or if retval is FAIL when inside a try
1288 /// conditional, no autocommands are executed. If otherwise the autocommands
1289 /// cause the script to be aborted, retval is set to FAIL.
1290 ///
1291 /// @param event event that occurred
1292 /// @param fname NULL or empty means use actual file name
1293 /// @param fname_io fname to use for <afile> on cmdline
1294 /// @param force When true, ignore autocmd_busy
1295 /// @param buf Buffer for <abuf>
1296 /// @param[in,out] retval caller's retval
1297 ///
1298 /// @return true if some autocommands were executed
apply_autocmds_retval(event_T event,char_u * fname,char_u * fname_io,bool force,buf_T * buf,int * retval)1299 bool apply_autocmds_retval(event_T event, char_u *fname, char_u *fname_io, bool force, buf_T *buf,
1300 int *retval)
1301 {
1302 if (should_abort(*retval)) {
1303 return false;
1304 }
1305
1306 bool did_cmd = apply_autocmds_group(event, fname, fname_io, force,
1307 AUGROUP_ALL, buf, NULL);
1308 if (did_cmd && aborting()) {
1309 *retval = FAIL;
1310 }
1311 return did_cmd;
1312 }
1313
1314 /// Return true if "event" autocommand is defined.
1315 ///
1316 /// @param event the autocommand to check
has_event(event_T event)1317 bool has_event(event_T event) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
1318 {
1319 return first_autopat[event] != NULL;
1320 }
1321
1322 /// Return true when there is a CursorHold/CursorHoldI autocommand defined for
1323 /// the current mode.
has_cursorhold(void)1324 bool has_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
1325 {
1326 return has_event((get_real_state() == NORMAL_BUSY ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI));
1327 // return first_autopat[] != NULL;
1328 }
1329
1330 /// Return true if the CursorHold/CursorHoldI event can be triggered.
trigger_cursorhold(void)1331 bool trigger_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
1332 {
1333 int state;
1334
1335 if (!did_cursorhold && has_cursorhold() && reg_recording == 0
1336 && typebuf.tb_len == 0 && !ins_compl_active()) {
1337 state = get_real_state();
1338 if (state == NORMAL_BUSY || (state & INSERT) != 0) {
1339 return true;
1340 }
1341 }
1342 return false;
1343 }
1344
1345 /// Execute autocommands for "event" and file name "fname".
1346 ///
1347 /// @param event event that occurred
1348 /// @param fname filename, NULL or empty means use actual file name
1349 /// @param fname_io filename to use for <afile> on cmdline,
1350 /// NULL means use `fname`.
1351 /// @param force When true, ignore autocmd_busy
1352 /// @param group autocmd group ID or AUGROUP_ALL
1353 /// @param buf Buffer for <abuf>
1354 /// @param eap Ex command arguments
1355 ///
1356 /// @return true if some commands were executed.
apply_autocmds_group(event_T event,char_u * fname,char_u * fname_io,bool force,int group,buf_T * buf,exarg_T * eap)1357 static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, bool force,
1358 int group, buf_T *buf, exarg_T *eap)
1359 {
1360 char_u *sfname = NULL; // short file name
1361 char_u *tail;
1362 bool save_changed;
1363 buf_T *old_curbuf;
1364 bool retval = false;
1365 char_u *save_sourcing_name;
1366 linenr_T save_sourcing_lnum;
1367 char_u *save_autocmd_fname;
1368 int save_autocmd_bufnr;
1369 char_u *save_autocmd_match;
1370 int save_autocmd_busy;
1371 int save_autocmd_nested;
1372 static int nesting = 0;
1373 AutoPatCmd patcmd;
1374 AutoPat *ap;
1375 char_u *save_cmdarg;
1376 long save_cmdbang;
1377 static int filechangeshell_busy = false;
1378 proftime_T wait_time;
1379 bool did_save_redobuff = false;
1380 save_redo_T save_redo;
1381 const bool save_KeyTyped = KeyTyped;
1382
1383 // Quickly return if there are no autocommands for this event or
1384 // autocommands are blocked.
1385 if (event == NUM_EVENTS || first_autopat[(int)event] == NULL
1386 || is_autocmd_blocked()) {
1387 goto BYPASS_AU;
1388 }
1389
1390 // When autocommands are busy, new autocommands are only executed when
1391 // explicitly enabled with the "nested" flag.
1392 if (autocmd_busy && !(force || autocmd_nested)) {
1393 goto BYPASS_AU;
1394 }
1395
1396 // Quickly return when immediately aborting on error, or when an interrupt
1397 // occurred or an exception was thrown but not caught.
1398 if (aborting()) {
1399 goto BYPASS_AU;
1400 }
1401
1402 // FileChangedShell never nests, because it can create an endless loop.
1403 if (filechangeshell_busy
1404 && (event == EVENT_FILECHANGEDSHELL
1405 || event == EVENT_FILECHANGEDSHELLPOST)) {
1406 goto BYPASS_AU;
1407 }
1408
1409 // Ignore events in 'eventignore'.
1410 if (event_ignored(event)) {
1411 goto BYPASS_AU;
1412 }
1413
1414 // Allow nesting of autocommands, but restrict the depth, because it's
1415 // possible to create an endless loop.
1416 if (nesting == 10) {
1417 emsg(_("E218: autocommand nesting too deep"));
1418 goto BYPASS_AU;
1419 }
1420
1421 // Check if these autocommands are disabled. Used when doing ":all" or
1422 // ":ball".
1423 if ((autocmd_no_enter && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
1424 || (autocmd_no_leave
1425 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE))) {
1426 goto BYPASS_AU;
1427 }
1428
1429 // Save the autocmd_* variables and info about the current buffer.
1430 save_autocmd_fname = autocmd_fname;
1431 save_autocmd_bufnr = autocmd_bufnr;
1432 save_autocmd_match = autocmd_match;
1433 save_autocmd_busy = autocmd_busy;
1434 save_autocmd_nested = autocmd_nested;
1435 save_changed = curbuf->b_changed;
1436 old_curbuf = curbuf;
1437
1438 // Set the file name to be used for <afile>.
1439 // Make a copy to avoid that changing a buffer name or directory makes it
1440 // invalid.
1441 if (fname_io == NULL) {
1442 if (event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE
1443 || event == EVENT_OPTIONSET) {
1444 autocmd_fname = NULL;
1445 } else if (fname != NULL && !ends_excmd(*fname)) {
1446 autocmd_fname = fname;
1447 } else if (buf != NULL) {
1448 autocmd_fname = buf->b_ffname;
1449 } else {
1450 autocmd_fname = NULL;
1451 }
1452 } else {
1453 autocmd_fname = fname_io;
1454 }
1455 if (autocmd_fname != NULL) {
1456 // Allocate MAXPATHL for when eval_vars() resolves the fullpath.
1457 autocmd_fname = vim_strnsave(autocmd_fname, MAXPATHL);
1458 }
1459
1460 // Set the buffer number to be used for <abuf>.
1461 if (buf == NULL) {
1462 autocmd_bufnr = 0;
1463 } else {
1464 autocmd_bufnr = buf->b_fnum;
1465 }
1466
1467 // When the file name is NULL or empty, use the file name of buffer "buf".
1468 // Always use the full path of the file name to match with, in case
1469 // "allow_dirs" is set.
1470 if (fname == NULL || *fname == NUL) {
1471 if (buf == NULL) {
1472 fname = NULL;
1473 } else {
1474 if (event == EVENT_SYNTAX) {
1475 fname = buf->b_p_syn;
1476 } else if (event == EVENT_FILETYPE) {
1477 fname = buf->b_p_ft;
1478 } else {
1479 if (buf->b_sfname != NULL) {
1480 sfname = vim_strsave(buf->b_sfname);
1481 }
1482 fname = buf->b_ffname;
1483 }
1484 }
1485 if (fname == NULL) {
1486 fname = (char_u *)"";
1487 }
1488 fname = vim_strsave(fname); // make a copy, so we can change it
1489 } else {
1490 sfname = vim_strsave(fname);
1491 // Don't try expanding the following events.
1492 if (event == EVENT_CMDLINECHANGED || event == EVENT_CMDLINEENTER
1493 || event == EVENT_CMDLINELEAVE || event == EVENT_CMDWINENTER
1494 || event == EVENT_CMDWINLEAVE || event == EVENT_CMDUNDEFINED
1495 || event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE
1496 || event == EVENT_DIRCHANGED || event == EVENT_FILETYPE
1497 || event == EVENT_FUNCUNDEFINED || event == EVENT_OPTIONSET
1498 || event == EVENT_QUICKFIXCMDPOST || event == EVENT_QUICKFIXCMDPRE
1499 || event == EVENT_REMOTEREPLY || event == EVENT_SPELLFILEMISSING
1500 || event == EVENT_SYNTAX || event == EVENT_SIGNAL
1501 || event == EVENT_TABCLOSED || event == EVENT_WINCLOSED) {
1502 fname = vim_strsave(fname);
1503 } else {
1504 fname = (char_u *)FullName_save((char *)fname, false);
1505 }
1506 }
1507 if (fname == NULL) { // out of memory
1508 xfree(sfname);
1509 retval = false;
1510 goto BYPASS_AU;
1511 }
1512
1513 #ifdef BACKSLASH_IN_FILENAME
1514 // Replace all backslashes with forward slashes. This makes the
1515 // autocommand patterns portable between Unix and Windows.
1516 if (sfname != NULL) {
1517 forward_slash(sfname);
1518 }
1519 forward_slash(fname);
1520 #endif
1521
1522 // Set the name to be used for <amatch>.
1523 autocmd_match = fname;
1524
1525 // Don't redraw while doing autocommands.
1526 RedrawingDisabled++;
1527 save_sourcing_name = sourcing_name;
1528 sourcing_name = NULL; // don't free this one
1529 save_sourcing_lnum = sourcing_lnum;
1530 sourcing_lnum = 0; // no line number here
1531
1532 const sctx_T save_current_sctx = current_sctx;
1533
1534 if (do_profiling == PROF_YES) {
1535 prof_child_enter(&wait_time); // doesn't count for the caller itself
1536 }
1537
1538 // Don't use local function variables, if called from a function.
1539 funccal_entry_T funccal_entry;
1540 save_funccal(&funccal_entry);
1541
1542 // When starting to execute autocommands, save the search patterns.
1543 if (!autocmd_busy) {
1544 save_search_patterns();
1545 if (!ins_compl_active()) {
1546 saveRedobuff(&save_redo);
1547 did_save_redobuff = true;
1548 }
1549 did_filetype = keep_filetype;
1550 }
1551
1552 // Note that we are applying autocmds. Some commands need to know.
1553 autocmd_busy = true;
1554 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
1555 nesting++; // see matching decrement below
1556
1557 // Remember that FileType was triggered. Used for did_filetype().
1558 if (event == EVENT_FILETYPE) {
1559 did_filetype = true;
1560 }
1561
1562 tail = path_tail(fname);
1563
1564 // Find first autocommand that matches
1565 patcmd.curpat = first_autopat[(int)event];
1566 patcmd.nextcmd = NULL;
1567 patcmd.group = group;
1568 patcmd.fname = fname;
1569 patcmd.sfname = sfname;
1570 patcmd.tail = tail;
1571 patcmd.event = event;
1572 patcmd.arg_bufnr = autocmd_bufnr;
1573 patcmd.next = NULL;
1574 auto_next_pat(&patcmd, false);
1575
1576 // found one, start executing the autocommands
1577 if (patcmd.curpat != NULL) {
1578 // add to active_apc_list
1579 patcmd.next = active_apc_list;
1580 active_apc_list = &patcmd;
1581
1582 // set v:cmdarg (only when there is a matching pattern)
1583 save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG);
1584 if (eap != NULL) {
1585 save_cmdarg = set_cmdarg(eap, NULL);
1586 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
1587 } else {
1588 save_cmdarg = NULL; // avoid gcc warning
1589 }
1590 retval = true;
1591 // mark the last pattern, to avoid an endless loop when more patterns
1592 // are added when executing autocommands
1593 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next) {
1594 ap->last = false;
1595 }
1596 ap->last = true;
1597
1598 if (nesting == 1) {
1599 // make sure cursor and topline are valid
1600 check_lnums(true);
1601 }
1602
1603 // Execute the autocmd. The `getnextac` callback handles iteration.
1604 do_cmdline(NULL, getnextac, (void *)&patcmd,
1605 DOCMD_NOWAIT | DOCMD_VERBOSE | DOCMD_REPEAT);
1606
1607 if (nesting == 1) {
1608 // restore cursor and topline, unless they were changed
1609 reset_lnums();
1610 }
1611
1612
1613 if (eap != NULL) {
1614 (void)set_cmdarg(NULL, save_cmdarg);
1615 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
1616 }
1617 // delete from active_apc_list
1618 if (active_apc_list == &patcmd) { // just in case
1619 active_apc_list = patcmd.next;
1620 }
1621 }
1622
1623 RedrawingDisabled--;
1624 autocmd_busy = save_autocmd_busy;
1625 filechangeshell_busy = false;
1626 autocmd_nested = save_autocmd_nested;
1627 xfree(sourcing_name);
1628 sourcing_name = save_sourcing_name;
1629 sourcing_lnum = save_sourcing_lnum;
1630 xfree(autocmd_fname);
1631 autocmd_fname = save_autocmd_fname;
1632 autocmd_bufnr = save_autocmd_bufnr;
1633 autocmd_match = save_autocmd_match;
1634 current_sctx = save_current_sctx;
1635 restore_funccal();
1636 if (do_profiling == PROF_YES) {
1637 prof_child_exit(&wait_time);
1638 }
1639 KeyTyped = save_KeyTyped;
1640 xfree(fname);
1641 xfree(sfname);
1642 nesting--; // see matching increment above
1643
1644 // When stopping to execute autocommands, restore the search patterns and
1645 // the redo buffer. Free any buffers in the au_pending_free_buf list and
1646 // free any windows in the au_pending_free_win list.
1647 if (!autocmd_busy) {
1648 restore_search_patterns();
1649 if (did_save_redobuff) {
1650 restoreRedobuff(&save_redo);
1651 }
1652 did_filetype = false;
1653 while (au_pending_free_buf != NULL) {
1654 buf_T *b = au_pending_free_buf->b_next;
1655
1656 xfree(au_pending_free_buf);
1657 au_pending_free_buf = b;
1658 }
1659 while (au_pending_free_win != NULL) {
1660 win_T *w = au_pending_free_win->w_next;
1661
1662 xfree(au_pending_free_win);
1663 au_pending_free_win = w;
1664 }
1665 }
1666
1667 // Some events don't set or reset the Changed flag.
1668 // Check if still in the same buffer!
1669 if (curbuf == old_curbuf
1670 && (event == EVENT_BUFREADPOST || event == EVENT_BUFWRITEPOST
1671 || event == EVENT_FILEAPPENDPOST || event == EVENT_VIMLEAVE
1672 || event == EVENT_VIMLEAVEPRE)) {
1673 if (curbuf->b_changed != save_changed) {
1674 need_maketitle = true;
1675 }
1676 curbuf->b_changed = save_changed;
1677 }
1678
1679 au_cleanup(); // may really delete removed patterns/commands now
1680
1681 BYPASS_AU:
1682 // When wiping out a buffer make sure all its buffer-local autocommands
1683 // are deleted.
1684 if (event == EVENT_BUFWIPEOUT && buf != NULL) {
1685 aubuflocal_remove(buf);
1686 }
1687
1688 if (retval == OK && event == EVENT_FILETYPE) {
1689 au_did_filetype = true;
1690 }
1691
1692 return retval;
1693 }
1694
1695 // Block triggering autocommands until unblock_autocmd() is called.
1696 // Can be used recursively, so long as it's symmetric.
block_autocmds(void)1697 void block_autocmds(void)
1698 {
1699 // Remember the value of v:termresponse.
1700 if (!is_autocmd_blocked()) {
1701 old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
1702 }
1703 autocmd_blocked++;
1704 }
1705
unblock_autocmds(void)1706 void unblock_autocmds(void)
1707 {
1708 autocmd_blocked--;
1709
1710 // When v:termresponse was set while autocommands were blocked, trigger
1711 // the autocommands now. Esp. useful when executing a shell command
1712 // during startup (nvim -d).
1713 if (!is_autocmd_blocked()
1714 && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse) {
1715 apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, false, curbuf);
1716 }
1717 }
1718
is_autocmd_blocked(void)1719 bool is_autocmd_blocked(void)
1720 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
1721 {
1722 return autocmd_blocked != 0;
1723 }
1724
1725 /// Find next autocommand pattern that matches.
1726 /// stop when 'last' flag is set
auto_next_pat(AutoPatCmd * apc,int stop_at_last)1727 void auto_next_pat(AutoPatCmd *apc, int stop_at_last)
1728 {
1729 AutoPat *ap;
1730 AutoCmd *cp;
1731 char *s;
1732
1733 XFREE_CLEAR(sourcing_name);
1734
1735 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next) {
1736 apc->curpat = NULL;
1737
1738 // Only use a pattern when it has not been removed, has commands and
1739 // the group matches. For buffer-local autocommands only check the
1740 // buffer number.
1741 if (ap->pat != NULL && ap->cmds != NULL
1742 && (apc->group == AUGROUP_ALL || apc->group == ap->group)) {
1743 // execution-condition
1744 if (ap->buflocal_nr == 0
1745 ? match_file_pat(NULL,
1746 &ap->reg_prog,
1747 apc->fname,
1748 apc->sfname,
1749 apc->tail,
1750 ap->allow_dirs)
1751 : ap->buflocal_nr == apc->arg_bufnr) {
1752 const char *const name = event_nr2name(apc->event);
1753 s = _("%s Autocommands for \"%s\"");
1754
1755 const size_t sourcing_name_len
1756 = (STRLEN(s) + strlen(name) + (size_t)ap->patlen + 1);
1757
1758 sourcing_name = xmalloc(sourcing_name_len);
1759 snprintf((char *)sourcing_name, sourcing_name_len, s, name,
1760 (char *)ap->pat);
1761 if (p_verbose >= 8) {
1762 verbose_enter();
1763 smsg(_("Executing %s"), sourcing_name);
1764 verbose_leave();
1765 }
1766
1767 apc->curpat = ap;
1768 apc->nextcmd = ap->cmds;
1769 // mark last command
1770 for (cp = ap->cmds; cp->next != NULL; cp = cp->next) {
1771 cp->last = false;
1772 }
1773 cp->last = true;
1774 }
1775 line_breakcheck();
1776 if (apc->curpat != NULL) { // found a match
1777 break;
1778 }
1779 }
1780 if (stop_at_last && ap->last) {
1781 break;
1782 }
1783 }
1784 }
1785
1786 /// Get next autocommand command.
1787 /// Called by do_cmdline() to get the next line for ":if".
1788 /// @return allocated string, or NULL for end of autocommands.
getnextac(int c,void * cookie,int indent,bool do_concat)1789 char_u *getnextac(int c, void *cookie, int indent, bool do_concat)
1790 {
1791 AutoPatCmd *acp = (AutoPatCmd *)cookie;
1792 char_u *retval;
1793 AutoCmd *ac;
1794
1795 // Can be called again after returning the last line.
1796 if (acp->curpat == NULL) {
1797 return NULL;
1798 }
1799
1800 // repeat until we find an autocommand to execute
1801 for (;;) {
1802 // skip removed commands
1803 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL) {
1804 if (acp->nextcmd->last) {
1805 acp->nextcmd = NULL;
1806 } else {
1807 acp->nextcmd = acp->nextcmd->next;
1808 }
1809 }
1810
1811 if (acp->nextcmd != NULL) {
1812 break;
1813 }
1814
1815 // at end of commands, find next pattern that matches
1816 if (acp->curpat->last) {
1817 acp->curpat = NULL;
1818 } else {
1819 acp->curpat = acp->curpat->next;
1820 }
1821 if (acp->curpat != NULL) {
1822 auto_next_pat(acp, true);
1823 }
1824 if (acp->curpat == NULL) {
1825 return NULL;
1826 }
1827 }
1828
1829 ac = acp->nextcmd;
1830
1831 if (p_verbose >= 9) {
1832 verbose_enter_scroll();
1833 smsg(_("autocommand %s"), ac->cmd);
1834 msg_puts("\n"); // don't overwrite this either
1835 verbose_leave_scroll();
1836 }
1837 retval = vim_strsave(ac->cmd);
1838 // Remove one-shot ("once") autocmd in anticipation of its execution.
1839 if (ac->once) {
1840 au_del_cmd(ac);
1841 }
1842 autocmd_nested = ac->nested;
1843 current_sctx = ac->script_ctx;
1844 if (ac->last) {
1845 acp->nextcmd = NULL;
1846 } else {
1847 acp->nextcmd = ac->next;
1848 }
1849
1850 return retval;
1851 }
1852
1853 /// Return true if there is a matching autocommand for "fname".
1854 /// To account for buffer-local autocommands, function needs to know
1855 /// in which buffer the file will be opened.
1856 ///
1857 /// @param event event that occurred.
1858 /// @param sfname filename the event occurred in.
1859 /// @param buf buffer the file is open in
has_autocmd(event_T event,char_u * sfname,buf_T * buf)1860 bool has_autocmd(event_T event, char_u *sfname, buf_T *buf) FUNC_ATTR_WARN_UNUSED_RESULT
1861 {
1862 AutoPat *ap;
1863 char_u *fname;
1864 char_u *tail = path_tail(sfname);
1865 bool retval = false;
1866
1867 fname = (char_u *)FullName_save((char *)sfname, false);
1868 if (fname == NULL) {
1869 return false;
1870 }
1871
1872 #ifdef BACKSLASH_IN_FILENAME
1873 // Replace all backslashes with forward slashes. This makes the
1874 // autocommand patterns portable between Unix and Windows.
1875 sfname = vim_strsave(sfname);
1876 forward_slash(sfname);
1877 forward_slash(fname);
1878 #endif
1879
1880 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
1881 if (ap->pat != NULL && ap->cmds != NULL
1882 && (ap->buflocal_nr == 0
1883 ? match_file_pat(NULL,
1884 &ap->reg_prog,
1885 fname,
1886 sfname,
1887 tail,
1888 ap->allow_dirs)
1889 : buf != NULL && ap->buflocal_nr == buf->b_fnum)) {
1890 retval = true;
1891 break;
1892 }
1893 }
1894
1895 xfree(fname);
1896 #ifdef BACKSLASH_IN_FILENAME
1897 xfree(sfname);
1898 #endif
1899
1900 return retval;
1901 }
1902
1903 // Function given to ExpandGeneric() to obtain the list of autocommand group
1904 // names.
get_augroup_name(expand_T * xp,int idx)1905 char_u *get_augroup_name(expand_T *xp, int idx)
1906 {
1907 if (idx == augroups.ga_len) { // add "END" add the end
1908 return (char_u *)"END";
1909 }
1910 if (idx >= augroups.ga_len) { // end of list
1911 return NULL;
1912 }
1913 if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup()) {
1914 // skip deleted entries
1915 return (char_u *)"";
1916 }
1917 return (char_u *)AUGROUP_NAME(idx);
1918 }
1919
1920 /// @param doautocmd true for :doauto*, false for :autocmd
set_context_in_autocmd(expand_T * xp,char_u * arg,int doautocmd)1921 char_u *set_context_in_autocmd(expand_T *xp, char_u *arg, int doautocmd)
1922 {
1923 char_u *p;
1924 int group;
1925
1926 // check for a group name, skip it if present
1927 autocmd_include_groups = false;
1928 p = arg;
1929 group = au_get_grouparg(&arg);
1930
1931 // If there only is a group name that's what we expand.
1932 if (*arg == NUL && group != AUGROUP_ALL && !ascii_iswhite(arg[-1])) {
1933 arg = p;
1934 group = AUGROUP_ALL;
1935 }
1936
1937 // skip over event name
1938 for (p = arg; *p != NUL && !ascii_iswhite(*p); p++) {
1939 if (*p == ',') {
1940 arg = p + 1;
1941 }
1942 }
1943 if (*p == NUL) {
1944 if (group == AUGROUP_ALL) {
1945 autocmd_include_groups = true;
1946 }
1947 xp->xp_context = EXPAND_EVENTS; // expand event name
1948 xp->xp_pattern = arg;
1949 return NULL;
1950 }
1951
1952 // skip over pattern
1953 arg = skipwhite(p);
1954 while (*arg && (!ascii_iswhite(*arg) || arg[-1] == '\\')) {
1955 arg++;
1956 }
1957 if (*arg) {
1958 return arg; // expand (next) command
1959 }
1960
1961 if (doautocmd) {
1962 xp->xp_context = EXPAND_FILES; // expand file names
1963 } else {
1964 xp->xp_context = EXPAND_NOTHING; // pattern is not expanded
1965 }
1966 return NULL;
1967 }
1968
1969 // Function given to ExpandGeneric() to obtain the list of event names.
get_event_name(expand_T * xp,int idx)1970 char_u *get_event_name(expand_T *xp, int idx)
1971 {
1972 if (idx < augroups.ga_len) { // First list group names, if wanted
1973 if (!autocmd_include_groups || AUGROUP_NAME(idx) == NULL
1974 || AUGROUP_NAME(idx) == get_deleted_augroup()) {
1975 return (char_u *)""; // skip deleted entries
1976 }
1977 return (char_u *)AUGROUP_NAME(idx);
1978 }
1979 return (char_u *)event_names[idx - augroups.ga_len].name;
1980 }
1981
1982 /// Check whether given autocommand is supported
1983 ///
1984 /// @param[in] event Event to check.
1985 ///
1986 /// @return True if it is, false otherwise.
autocmd_supported(const char * const event)1987 bool autocmd_supported(const char *const event)
1988 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
1989 {
1990 char_u *p;
1991 return event_name2nr((const char_u *)event, &p) != NUM_EVENTS;
1992 }
1993
1994 /// Return true if an autocommand is defined for a group, event and
1995 /// pattern: The group can be omitted to accept any group.
1996 /// `event` and `pattern` can be omitted to accept any event and pattern.
1997 /// Buffer-local patterns <buffer> or <buffer=N> are accepted.
1998 /// Used for:
1999 /// exists("#Group") or
2000 /// exists("#Group#Event") or
2001 /// exists("#Group#Event#pat") or
2002 /// exists("#Event") or
2003 /// exists("#Event#pat")
2004 ///
2005 /// @param arg autocommand string
au_exists(const char * const arg)2006 bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT
2007 {
2008 event_T event;
2009 AutoPat *ap;
2010 buf_T *buflocal_buf = NULL;
2011 int group;
2012 bool retval = false;
2013
2014 // Make a copy so that we can change the '#' chars to a NUL.
2015 char *const arg_save = xstrdup(arg);
2016 char *p = strchr(arg_save, '#');
2017 if (p != NULL) {
2018 *p++ = NUL;
2019 }
2020
2021 // First, look for an autocmd group name.
2022 group = au_find_group((char_u *)arg_save);
2023 char *event_name;
2024 if (group == AUGROUP_ERROR) {
2025 // Didn't match a group name, assume the first argument is an event.
2026 group = AUGROUP_ALL;
2027 event_name = arg_save;
2028 } else {
2029 if (p == NULL) {
2030 // "Group": group name is present and it's recognized
2031 retval = true;
2032 goto theend;
2033 }
2034
2035 // Must be "Group#Event" or "Group#Event#pat".
2036 event_name = p;
2037 p = strchr(event_name, '#');
2038 if (p != NULL) {
2039 *p++ = NUL; // "Group#Event#pat"
2040 }
2041 }
2042
2043 char *pattern = p; // "pattern" is NULL when there is no pattern.
2044
2045 // Find the index (enum) for the event name.
2046 event = event_name2nr((char_u *)event_name, (char_u **)&p);
2047
2048 // return false if the event name is not recognized
2049 if (event == NUM_EVENTS) {
2050 goto theend;
2051 }
2052
2053 // Find the first autocommand for this event.
2054 // If there isn't any, return false;
2055 // If there is one and no pattern given, return true;
2056 ap = first_autopat[(int)event];
2057 if (ap == NULL) {
2058 goto theend;
2059 }
2060
2061 // if pattern is "<buffer>", special handling is needed which uses curbuf
2062 // for pattern "<buffer=N>, fnamecmp() will work fine
2063 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0) {
2064 buflocal_buf = curbuf;
2065 }
2066
2067 // Check if there is an autocommand with the given pattern.
2068 for (; ap != NULL; ap = ap->next) {
2069 // only use a pattern when it has not been removed and has commands.
2070 // For buffer-local autocommands, fnamecmp() works fine.
2071 if (ap->pat != NULL && ap->cmds != NULL
2072 && (group == AUGROUP_ALL || ap->group == group)
2073 && (pattern == NULL
2074 || (buflocal_buf == NULL
2075 ? fnamecmp(ap->pat, (char_u *)pattern) == 0
2076 : ap->buflocal_nr == buflocal_buf->b_fnum))) {
2077 retval = true;
2078 break;
2079 }
2080 }
2081
2082 theend:
2083 xfree(arg_save);
2084 return retval;
2085 }
2086