blob: d6945f30625b214c5a0325abd9896210a54efb59 [file] [log] [blame]
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * autocmd.c: Autocommand related functions
12 */
13
14#include "vim.h"
15
16/*
17 * The autocommands are stored in a list for each event.
18 * Autocommands for the same pattern, that are consecutive, are joined
19 * together, to avoid having to match the pattern too often.
20 * The result is an array of Autopat lists, which point to AutoCmd lists:
21 *
22 * last_autopat[0] -----------------------------+
23 * V
24 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
25 * Autopat.cmds Autopat.cmds
26 * | |
27 * V V
28 * AutoCmd.next AutoCmd.next
29 * | |
30 * V V
31 * AutoCmd.next NULL
32 * |
33 * V
34 * NULL
35 *
36 * last_autopat[1] --------+
37 * V
38 * first_autopat[1] --> Autopat.next --> NULL
39 * Autopat.cmds
40 * |
41 * V
42 * AutoCmd.next
43 * |
44 * V
45 * NULL
46 * etc.
47 *
48 * The order of AutoCmds is important, this is the order in which they were
49 * defined and will have to be executed.
50 */
51typedef struct AutoCmd
52{
53 char_u *cmd; // The command to be executed (NULL
54 // when command has been removed).
Bram Moolenaareb93f3f2019-04-04 15:04:56 +020055 char once; // "One shot": removed after execution
Bram Moolenaar3e460fd2019-01-26 16:21:07 +010056 char nested; // If autocommands nest here.
57 char last; // last command in list
58#ifdef FEAT_EVAL
59 sctx_T script_ctx; // script context where defined
60#endif
61 struct AutoCmd *next; // next AutoCmd in list
62} AutoCmd;
63
64typedef struct AutoPat
65{
66 struct AutoPat *next; // Next AutoPat in AutoPat list; MUST
67 // be the first entry.
68 char_u *pat; // pattern as typed (NULL when pattern
69 // has been removed)
70 regprog_T *reg_prog; // compiled regprog for pattern
71 AutoCmd *cmds; // list of commands to do
72 int group; // group ID
73 int patlen; // strlen() of pat
74 int buflocal_nr; // !=0 for buffer-local AutoPat
75 char allow_dirs; // Pattern may match whole path
76 char last; // last pattern for apply_autocmds()
77} AutoPat;
78
79static struct event_name
80{
81 char *name; // event name
82 event_T event; // event number
83} event_names[] =
84{
85 {"BufAdd", EVENT_BUFADD},
86 {"BufCreate", EVENT_BUFADD},
87 {"BufDelete", EVENT_BUFDELETE},
88 {"BufEnter", EVENT_BUFENTER},
89 {"BufFilePost", EVENT_BUFFILEPOST},
90 {"BufFilePre", EVENT_BUFFILEPRE},
91 {"BufHidden", EVENT_BUFHIDDEN},
92 {"BufLeave", EVENT_BUFLEAVE},
93 {"BufNew", EVENT_BUFNEW},
94 {"BufNewFile", EVENT_BUFNEWFILE},
95 {"BufRead", EVENT_BUFREADPOST},
96 {"BufReadCmd", EVENT_BUFREADCMD},
97 {"BufReadPost", EVENT_BUFREADPOST},
98 {"BufReadPre", EVENT_BUFREADPRE},
99 {"BufUnload", EVENT_BUFUNLOAD},
100 {"BufWinEnter", EVENT_BUFWINENTER},
101 {"BufWinLeave", EVENT_BUFWINLEAVE},
102 {"BufWipeout", EVENT_BUFWIPEOUT},
103 {"BufWrite", EVENT_BUFWRITEPRE},
104 {"BufWritePost", EVENT_BUFWRITEPOST},
105 {"BufWritePre", EVENT_BUFWRITEPRE},
106 {"BufWriteCmd", EVENT_BUFWRITECMD},
107 {"CmdlineChanged", EVENT_CMDLINECHANGED},
108 {"CmdlineEnter", EVENT_CMDLINEENTER},
109 {"CmdlineLeave", EVENT_CMDLINELEAVE},
110 {"CmdwinEnter", EVENT_CMDWINENTER},
111 {"CmdwinLeave", EVENT_CMDWINLEAVE},
112 {"CmdUndefined", EVENT_CMDUNDEFINED},
113 {"ColorScheme", EVENT_COLORSCHEME},
114 {"ColorSchemePre", EVENT_COLORSCHEMEPRE},
Bram Moolenaard7f246c2019-04-08 18:15:41 +0200115 {"CompleteChanged", EVENT_COMPLETECHANGED},
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100116 {"CompleteDone", EVENT_COMPLETEDONE},
Bram Moolenaar3f169ce2020-01-26 22:43:31 +0100117 {"CompleteDonePre", EVENT_COMPLETEDONEPRE},
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100118 {"CursorHold", EVENT_CURSORHOLD},
119 {"CursorHoldI", EVENT_CURSORHOLDI},
120 {"CursorMoved", EVENT_CURSORMOVED},
121 {"CursorMovedI", EVENT_CURSORMOVEDI},
122 {"DiffUpdated", EVENT_DIFFUPDATED},
123 {"DirChanged", EVENT_DIRCHANGED},
124 {"EncodingChanged", EVENT_ENCODINGCHANGED},
125 {"ExitPre", EVENT_EXITPRE},
126 {"FileEncoding", EVENT_ENCODINGCHANGED},
127 {"FileAppendPost", EVENT_FILEAPPENDPOST},
128 {"FileAppendPre", EVENT_FILEAPPENDPRE},
129 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
130 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
131 {"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
132 {"FileChangedRO", EVENT_FILECHANGEDRO},
133 {"FileReadPost", EVENT_FILEREADPOST},
134 {"FileReadPre", EVENT_FILEREADPRE},
135 {"FileReadCmd", EVENT_FILEREADCMD},
136 {"FileType", EVENT_FILETYPE},
137 {"FileWritePost", EVENT_FILEWRITEPOST},
138 {"FileWritePre", EVENT_FILEWRITEPRE},
139 {"FileWriteCmd", EVENT_FILEWRITECMD},
140 {"FilterReadPost", EVENT_FILTERREADPOST},
141 {"FilterReadPre", EVENT_FILTERREADPRE},
142 {"FilterWritePost", EVENT_FILTERWRITEPOST},
143 {"FilterWritePre", EVENT_FILTERWRITEPRE},
144 {"FocusGained", EVENT_FOCUSGAINED},
145 {"FocusLost", EVENT_FOCUSLOST},
146 {"FuncUndefined", EVENT_FUNCUNDEFINED},
147 {"GUIEnter", EVENT_GUIENTER},
148 {"GUIFailed", EVENT_GUIFAILED},
149 {"InsertChange", EVENT_INSERTCHANGE},
150 {"InsertEnter", EVENT_INSERTENTER},
151 {"InsertLeave", EVENT_INSERTLEAVE},
152 {"InsertCharPre", EVENT_INSERTCHARPRE},
153 {"MenuPopup", EVENT_MENUPOPUP},
154 {"OptionSet", EVENT_OPTIONSET},
155 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
156 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
157 {"QuitPre", EVENT_QUITPRE},
158 {"RemoteReply", EVENT_REMOTEREPLY},
Bram Moolenaar8aeec402019-09-15 23:02:04 +0200159 {"SafeState", EVENT_SAFESTATE},
Bram Moolenaar69198cb2019-09-16 21:58:13 +0200160 {"SafeStateAgain", EVENT_SAFESTATEAGAIN},
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100161 {"SessionLoadPost", EVENT_SESSIONLOADPOST},
162 {"ShellCmdPost", EVENT_SHELLCMDPOST},
163 {"ShellFilterPost", EVENT_SHELLFILTERPOST},
164 {"SourceCmd", EVENT_SOURCECMD},
165 {"SourcePre", EVENT_SOURCEPRE},
166 {"SourcePost", EVENT_SOURCEPOST},
167 {"SpellFileMissing",EVENT_SPELLFILEMISSING},
168 {"StdinReadPost", EVENT_STDINREADPOST},
169 {"StdinReadPre", EVENT_STDINREADPRE},
170 {"SwapExists", EVENT_SWAPEXISTS},
171 {"Syntax", EVENT_SYNTAX},
172 {"TabNew", EVENT_TABNEW},
173 {"TabClosed", EVENT_TABCLOSED},
174 {"TabEnter", EVENT_TABENTER},
175 {"TabLeave", EVENT_TABLEAVE},
176 {"TermChanged", EVENT_TERMCHANGED},
177 {"TerminalOpen", EVENT_TERMINALOPEN},
Bram Moolenaar28ed4df2019-10-26 16:21:40 +0200178 {"TerminalWinOpen", EVENT_TERMINALWINOPEN},
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100179 {"TermResponse", EVENT_TERMRESPONSE},
180 {"TextChanged", EVENT_TEXTCHANGED},
181 {"TextChangedI", EVENT_TEXTCHANGEDI},
182 {"TextChangedP", EVENT_TEXTCHANGEDP},
183 {"User", EVENT_USER},
184 {"VimEnter", EVENT_VIMENTER},
185 {"VimLeave", EVENT_VIMLEAVE},
186 {"VimLeavePre", EVENT_VIMLEAVEPRE},
187 {"WinNew", EVENT_WINNEW},
188 {"WinEnter", EVENT_WINENTER},
189 {"WinLeave", EVENT_WINLEAVE},
190 {"VimResized", EVENT_VIMRESIZED},
191 {"TextYankPost", EVENT_TEXTYANKPOST},
192 {NULL, (event_T)0}
193};
194
195static AutoPat *first_autopat[NUM_EVENTS] =
196{
197 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
198 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
199 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
200 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
201 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
202 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
203};
204
205static AutoPat *last_autopat[NUM_EVENTS] =
206{
207 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
208 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
209 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
210 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
211 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
212 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
213};
214
215#define AUGROUP_DEFAULT -1 // default autocmd group
216#define AUGROUP_ERROR -2 // erroneous autocmd group
217#define AUGROUP_ALL -3 // all autocmd groups
218
219/*
220 * struct used to keep status while executing autocommands for an event.
221 */
Bram Moolenaar1a47ae32019-12-29 23:04:25 +0100222struct AutoPatCmd_S
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100223{
224 AutoPat *curpat; // next AutoPat to examine
225 AutoCmd *nextcmd; // next AutoCmd to execute
226 int group; // group being used
227 char_u *fname; // fname to match with
228 char_u *sfname; // sfname to match with
229 char_u *tail; // tail of fname
230 event_T event; // current event
231 int arg_bufnr; // Initially equal to <abuf>, set to zero when
232 // buf is deleted.
Bram Moolenaar1a47ae32019-12-29 23:04:25 +0100233 AutoPatCmd *next; // chain of active apc-s for auto-invalidation
234};
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100235
Bram Moolenaarc667da52019-11-30 20:52:27 +0100236static AutoPatCmd *active_apc_list = NULL; // stack of active autocommands
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100237
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200238// Macro to loop over all the patterns for an autocmd event
239#define FOR_ALL_AUTOCMD_PATTERNS(event, ap) \
240 for ((ap) = first_autopat[(int)(event)]; (ap) != NULL; (ap) = (ap)->next)
241
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100242/*
243 * augroups stores a list of autocmd group names.
244 */
245static garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
246#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
Bram Moolenaarc667da52019-11-30 20:52:27 +0100247// use get_deleted_augroup() to get this
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100248static char_u *deleted_augroup = NULL;
249
250/*
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100251 * The ID of the current group. Group 0 is the default one.
252 */
253static int current_augroup = AUGROUP_DEFAULT;
254
Bram Moolenaarc667da52019-11-30 20:52:27 +0100255static int au_need_clean = FALSE; // need to delete marked patterns
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100256
257static char_u *event_nr2name(event_T event);
258static int au_get_grouparg(char_u **argp);
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200259static int do_autocmd_event(event_T event, char_u *pat, int once, int nested, char_u *cmd, int forceit, int group);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100260static int apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, int force, int group, buf_T *buf, exarg_T *eap);
261static void auto_next_pat(AutoPatCmd *apc, int stop_at_last);
262static int au_find_group(char_u *name);
263
264static event_T last_event;
265static int last_group;
Bram Moolenaarc667da52019-11-30 20:52:27 +0100266static int autocmd_blocked = 0; // block all autocmds
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100267
268 static char_u *
269get_deleted_augroup(void)
270{
271 if (deleted_augroup == NULL)
272 deleted_augroup = (char_u *)_("--Deleted--");
273 return deleted_augroup;
274}
275
276/*
277 * Show the autocommands for one AutoPat.
278 */
279 static void
280show_autocmd(AutoPat *ap, event_T event)
281{
282 AutoCmd *ac;
283
284 // Check for "got_int" (here and at various places below), which is set
285 // when "q" has been hit for the "--more--" prompt
286 if (got_int)
287 return;
288 if (ap->pat == NULL) // pattern has been removed
289 return;
290
291 msg_putchar('\n');
292 if (got_int)
293 return;
294 if (event != last_event || ap->group != last_group)
295 {
296 if (ap->group != AUGROUP_DEFAULT)
297 {
298 if (AUGROUP_NAME(ap->group) == NULL)
299 msg_puts_attr((char *)get_deleted_augroup(), HL_ATTR(HLF_E));
300 else
301 msg_puts_attr((char *)AUGROUP_NAME(ap->group), HL_ATTR(HLF_T));
302 msg_puts(" ");
303 }
304 msg_puts_attr((char *)event_nr2name(event), HL_ATTR(HLF_T));
305 last_event = event;
306 last_group = ap->group;
307 msg_putchar('\n');
308 if (got_int)
309 return;
310 }
311 msg_col = 4;
312 msg_outtrans(ap->pat);
313
314 for (ac = ap->cmds; ac != NULL; ac = ac->next)
315 {
316 if (ac->cmd != NULL) // skip removed commands
317 {
318 if (msg_col >= 14)
319 msg_putchar('\n');
320 msg_col = 14;
321 if (got_int)
322 return;
323 msg_outtrans(ac->cmd);
324#ifdef FEAT_EVAL
325 if (p_verbose > 0)
326 last_set_msg(ac->script_ctx);
327#endif
328 if (got_int)
329 return;
330 if (ac->next != NULL)
331 {
332 msg_putchar('\n');
333 if (got_int)
334 return;
335 }
336 }
337 }
338}
339
340/*
341 * Mark an autocommand pattern for deletion.
342 */
343 static void
344au_remove_pat(AutoPat *ap)
345{
346 VIM_CLEAR(ap->pat);
347 ap->buflocal_nr = -1;
348 au_need_clean = TRUE;
349}
350
351/*
352 * Mark all commands for a pattern for deletion.
353 */
354 static void
355au_remove_cmds(AutoPat *ap)
356{
357 AutoCmd *ac;
358
359 for (ac = ap->cmds; ac != NULL; ac = ac->next)
360 VIM_CLEAR(ac->cmd);
361 au_need_clean = TRUE;
362}
363
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200364// Delete one command from an autocmd pattern.
365static void au_del_cmd(AutoCmd *ac)
366{
367 VIM_CLEAR(ac->cmd);
368 au_need_clean = TRUE;
369}
370
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100371/*
372 * Cleanup autocommands and patterns that have been deleted.
373 * This is only done when not executing autocommands.
374 */
375 static void
376au_cleanup(void)
377{
378 AutoPat *ap, **prev_ap;
379 AutoCmd *ac, **prev_ac;
380 event_T event;
381
382 if (autocmd_busy || !au_need_clean)
383 return;
384
385 // loop over all events
386 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
387 event = (event_T)((int)event + 1))
388 {
389 // loop over all autocommand patterns
390 prev_ap = &(first_autopat[(int)event]);
391 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
392 {
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200393 int has_cmd = FALSE;
394
Bram Moolenaar8f4aeb52019-04-04 15:40:56 +0200395 // loop over all commands for this pattern
396 prev_ac = &(ap->cmds);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100397 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
398 {
399 // remove the command if the pattern is to be deleted or when
400 // the command has been marked for deletion
401 if (ap->pat == NULL || ac->cmd == NULL)
402 {
403 *prev_ac = ac->next;
404 vim_free(ac->cmd);
405 vim_free(ac);
406 }
Bram Moolenaar8f4aeb52019-04-04 15:40:56 +0200407 else
408 {
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200409 has_cmd = TRUE;
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100410 prev_ac = &(ac->next);
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200411 }
412 }
413
Bram Moolenaar8f4aeb52019-04-04 15:40:56 +0200414 if (ap->pat != NULL && !has_cmd)
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200415 // Pattern was not marked for deletion, but all of its
416 // commands were. So mark the pattern for deletion.
417 au_remove_pat(ap);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100418
419 // remove the pattern if it has been marked for deletion
420 if (ap->pat == NULL)
421 {
422 if (ap->next == NULL)
423 {
424 if (prev_ap == &(first_autopat[(int)event]))
425 last_autopat[(int)event] = NULL;
426 else
427 // this depends on the "next" field being the first in
428 // the struct
429 last_autopat[(int)event] = (AutoPat *)prev_ap;
430 }
431 *prev_ap = ap->next;
432 vim_regfree(ap->reg_prog);
433 vim_free(ap);
434 }
435 else
436 prev_ap = &(ap->next);
437 }
438 }
439
440 au_need_clean = FALSE;
441}
442
443/*
444 * Called when buffer is freed, to remove/invalidate related buffer-local
445 * autocmds.
446 */
447 void
448aubuflocal_remove(buf_T *buf)
449{
450 AutoPat *ap;
451 event_T event;
452 AutoPatCmd *apc;
453
454 // invalidate currently executing autocommands
455 for (apc = active_apc_list; apc; apc = apc->next)
456 if (buf->b_fnum == apc->arg_bufnr)
457 apc->arg_bufnr = 0;
458
459 // invalidate buflocals looping through events
460 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
461 event = (event_T)((int)event + 1))
462 // loop over all autocommand patterns
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200463 FOR_ALL_AUTOCMD_PATTERNS(event, ap)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100464 if (ap->buflocal_nr == buf->b_fnum)
465 {
466 au_remove_pat(ap);
467 if (p_verbose >= 6)
468 {
469 verbose_enter();
470 smsg(_("auto-removing autocommand: %s <buffer=%d>"),
471 event_nr2name(event), buf->b_fnum);
472 verbose_leave();
473 }
474 }
475 au_cleanup();
476}
477
478/*
479 * Add an autocmd group name.
480 * Return its ID. Returns AUGROUP_ERROR (< 0) for error.
481 */
482 static int
483au_new_group(char_u *name)
484{
485 int i;
486
487 i = au_find_group(name);
488 if (i == AUGROUP_ERROR) // the group doesn't exist yet, add it
489 {
490 // First try using a free entry.
491 for (i = 0; i < augroups.ga_len; ++i)
492 if (AUGROUP_NAME(i) == NULL)
493 break;
494 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
495 return AUGROUP_ERROR;
496
497 AUGROUP_NAME(i) = vim_strsave(name);
498 if (AUGROUP_NAME(i) == NULL)
499 return AUGROUP_ERROR;
500 if (i == augroups.ga_len)
501 ++augroups.ga_len;
502 }
503
504 return i;
505}
506
507 static void
508au_del_group(char_u *name)
509{
510 int i;
511
512 i = au_find_group(name);
513 if (i == AUGROUP_ERROR) // the group doesn't exist
514 semsg(_("E367: No such group: \"%s\""), name);
515 else if (i == current_augroup)
516 emsg(_("E936: Cannot delete the current group"));
517 else
518 {
519 event_T event;
520 AutoPat *ap;
521 int in_use = FALSE;
522
523 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
524 event = (event_T)((int)event + 1))
525 {
Bram Moolenaaraeea7212020-04-02 18:50:46 +0200526 FOR_ALL_AUTOCMD_PATTERNS(event, ap)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100527 if (ap->group == i && ap->pat != NULL)
528 {
529 give_warning((char_u *)_("W19: Deleting augroup that is still in use"), TRUE);
530 in_use = TRUE;
531 event = NUM_EVENTS;
532 break;
533 }
534 }
535 vim_free(AUGROUP_NAME(i));
536 if (in_use)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100537 AUGROUP_NAME(i) = get_deleted_augroup();
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100538 else
539 AUGROUP_NAME(i) = NULL;
540 }
541}
542
543/*
544 * Find the ID of an autocmd group name.
545 * Return its ID. Returns AUGROUP_ERROR (< 0) for error.
546 */
547 static int
548au_find_group(char_u *name)
549{
550 int i;
551
552 for (i = 0; i < augroups.ga_len; ++i)
553 if (AUGROUP_NAME(i) != NULL && AUGROUP_NAME(i) != get_deleted_augroup()
554 && STRCMP(AUGROUP_NAME(i), name) == 0)
555 return i;
556 return AUGROUP_ERROR;
557}
558
559/*
560 * Return TRUE if augroup "name" exists.
561 */
562 int
563au_has_group(char_u *name)
564{
565 return au_find_group(name) != AUGROUP_ERROR;
566}
567
568/*
569 * ":augroup {name}".
570 */
571 void
572do_augroup(char_u *arg, int del_group)
573{
574 int i;
575
576 if (del_group)
577 {
578 if (*arg == NUL)
579 emsg(_(e_argreq));
580 else
581 au_del_group(arg);
582 }
583 else if (STRICMP(arg, "end") == 0) // ":aug end": back to group 0
584 current_augroup = AUGROUP_DEFAULT;
585 else if (*arg) // ":aug xxx": switch to group xxx
586 {
587 i = au_new_group(arg);
588 if (i != AUGROUP_ERROR)
589 current_augroup = i;
590 }
591 else // ":aug": list the group names
592 {
593 msg_start();
594 for (i = 0; i < augroups.ga_len; ++i)
595 {
596 if (AUGROUP_NAME(i) != NULL)
597 {
598 msg_puts((char *)AUGROUP_NAME(i));
599 msg_puts(" ");
600 }
601 }
602 msg_clr_eos();
603 msg_end();
604 }
605}
606
607#if defined(EXITFREE) || defined(PROTO)
608 void
609free_all_autocmds(void)
610{
611 int i;
612 char_u *s;
613
614 for (current_augroup = -1; current_augroup < augroups.ga_len;
615 ++current_augroup)
616 do_autocmd((char_u *)"", TRUE);
617
618 for (i = 0; i < augroups.ga_len; ++i)
619 {
620 s = ((char_u **)(augroups.ga_data))[i];
621 if (s != get_deleted_augroup())
622 vim_free(s);
623 }
624 ga_clear(&augroups);
625}
626#endif
627
628/*
629 * Return the event number for event name "start".
630 * Return NUM_EVENTS if the event name was not found.
631 * Return a pointer to the next event name in "end".
632 */
633 static event_T
634event_name2nr(char_u *start, char_u **end)
635{
636 char_u *p;
637 int i;
638 int len;
639
640 // the event name ends with end of line, '|', a blank or a comma
641 for (p = start; *p && !VIM_ISWHITE(*p) && *p != ',' && *p != '|'; ++p)
642 ;
643 for (i = 0; event_names[i].name != NULL; ++i)
644 {
645 len = (int)STRLEN(event_names[i].name);
646 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
647 break;
648 }
649 if (*p == ',')
650 ++p;
651 *end = p;
652 if (event_names[i].name == NULL)
653 return NUM_EVENTS;
654 return event_names[i].event;
655}
656
657/*
658 * Return the name for event "event".
659 */
660 static char_u *
661event_nr2name(event_T event)
662{
663 int i;
664
665 for (i = 0; event_names[i].name != NULL; ++i)
666 if (event_names[i].event == event)
667 return (char_u *)event_names[i].name;
668 return (char_u *)"Unknown";
669}
670
671/*
672 * Scan over the events. "*" stands for all events.
673 */
674 static char_u *
675find_end_event(
676 char_u *arg,
677 int have_group) // TRUE when group name was found
678{
679 char_u *pat;
680 char_u *p;
681
682 if (*arg == '*')
683 {
684 if (arg[1] && !VIM_ISWHITE(arg[1]))
685 {
686 semsg(_("E215: Illegal character after *: %s"), arg);
687 return NULL;
688 }
689 pat = arg + 1;
690 }
691 else
692 {
693 for (pat = arg; *pat && *pat != '|' && !VIM_ISWHITE(*pat); pat = p)
694 {
695 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
696 {
697 if (have_group)
698 semsg(_("E216: No such event: %s"), pat);
699 else
700 semsg(_("E216: No such group or event: %s"), pat);
701 return NULL;
702 }
703 }
704 }
705 return pat;
706}
707
708/*
709 * Return TRUE if "event" is included in 'eventignore'.
710 */
711 static int
712event_ignored(event_T event)
713{
714 char_u *p = p_ei;
715
716 while (*p != NUL)
717 {
718 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
719 return TRUE;
720 if (event_name2nr(p, &p) == event)
721 return TRUE;
722 }
723
724 return FALSE;
725}
726
727/*
728 * Return OK when the contents of p_ei is valid, FAIL otherwise.
729 */
730 int
731check_ei(void)
732{
733 char_u *p = p_ei;
734
735 while (*p)
736 {
737 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ','))
738 {
739 p += 3;
740 if (*p == ',')
741 ++p;
742 }
743 else if (event_name2nr(p, &p) == NUM_EVENTS)
744 return FAIL;
745 }
746
747 return OK;
748}
749
750# if defined(FEAT_SYN_HL) || defined(PROTO)
751
752/*
753 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
754 * buffer loaded into the window. "what" must start with a comma.
755 * Returns the old value of 'eventignore' in allocated memory.
756 */
757 char_u *
758au_event_disable(char *what)
759{
760 char_u *new_ei;
761 char_u *save_ei;
762
763 save_ei = vim_strsave(p_ei);
764 if (save_ei != NULL)
765 {
766 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
767 if (new_ei != NULL)
768 {
769 if (*what == ',' && *p_ei == NUL)
770 STRCPY(new_ei, what + 1);
771 else
772 STRCAT(new_ei, what);
773 set_string_option_direct((char_u *)"ei", -1, new_ei,
774 OPT_FREE, SID_NONE);
775 vim_free(new_ei);
776 }
777 }
778 return save_ei;
779}
780
781 void
782au_event_restore(char_u *old_ei)
783{
784 if (old_ei != NULL)
785 {
786 set_string_option_direct((char_u *)"ei", -1, old_ei,
787 OPT_FREE, SID_NONE);
788 vim_free(old_ei);
789 }
790}
Bram Moolenaarc667da52019-11-30 20:52:27 +0100791# endif // FEAT_SYN_HL
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100792
793/*
794 * do_autocmd() -- implements the :autocmd command. Can be used in the
795 * following ways:
796 *
797 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
798 * will be automatically executed for <event>
799 * when editing a file matching <pat>, in
800 * the current group.
801 * :autocmd <event> <pat> Show the autocommands associated with
802 * <event> and <pat>.
803 * :autocmd <event> Show the autocommands associated with
804 * <event>.
805 * :autocmd Show all autocommands.
806 * :autocmd! <event> <pat> <cmd> Remove all autocommands associated with
807 * <event> and <pat>, and add the command
808 * <cmd>, for the current group.
809 * :autocmd! <event> <pat> Remove all autocommands associated with
810 * <event> and <pat> for the current group.
811 * :autocmd! <event> Remove all autocommands associated with
812 * <event> for the current group.
813 * :autocmd! Remove ALL autocommands for the current
814 * group.
815 *
816 * Multiple events and patterns may be given separated by commas. Here are
817 * some examples:
818 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
819 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
820 *
821 * :autocmd * *.c show all autocommands for *.c files.
822 *
823 * Mostly a {group} argument can optionally appear before <event>.
824 */
825 void
826do_autocmd(char_u *arg_in, int forceit)
827{
828 char_u *arg = arg_in;
829 char_u *pat;
830 char_u *envpat = NULL;
831 char_u *cmd;
832 event_T event;
833 int need_free = FALSE;
834 int nested = FALSE;
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200835 int once = FALSE;
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100836 int group;
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200837 int i;
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100838
839 if (*arg == '|')
840 {
841 arg = (char_u *)"";
842 group = AUGROUP_ALL; // no argument, use all groups
843 }
844 else
845 {
846 /*
847 * Check for a legal group name. If not, use AUGROUP_ALL.
848 */
849 group = au_get_grouparg(&arg);
850 if (arg == NULL) // out of memory
851 return;
852 }
853
854 /*
855 * Scan over the events.
856 * If we find an illegal name, return here, don't do anything.
857 */
858 pat = find_end_event(arg, group != AUGROUP_ALL);
859 if (pat == NULL)
860 return;
861
862 pat = skipwhite(pat);
863 if (*pat == '|')
864 {
865 pat = (char_u *)"";
866 cmd = (char_u *)"";
867 }
868 else
869 {
870 /*
871 * Scan over the pattern. Put a NUL at the end.
872 */
873 cmd = pat;
874 while (*cmd && (!VIM_ISWHITE(*cmd) || cmd[-1] == '\\'))
875 cmd++;
876 if (*cmd)
877 *cmd++ = NUL;
878
879 // Expand environment variables in the pattern. Set 'shellslash', we
880 // want forward slashes here.
881 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
882 {
883#ifdef BACKSLASH_IN_FILENAME
884 int p_ssl_save = p_ssl;
885
886 p_ssl = TRUE;
887#endif
888 envpat = expand_env_save(pat);
889#ifdef BACKSLASH_IN_FILENAME
890 p_ssl = p_ssl_save;
891#endif
892 if (envpat != NULL)
893 pat = envpat;
894 }
895
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100896 cmd = skipwhite(cmd);
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200897 for (i = 0; i < 2; i++)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100898 {
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200899 if (*cmd != NUL)
900 {
901 // Check for "++once" flag.
902 if (STRNCMP(cmd, "++once", 6) == 0 && VIM_ISWHITE(cmd[6]))
903 {
904 if (once)
905 semsg(_(e_duparg2), "++once");
906 once = TRUE;
907 cmd = skipwhite(cmd + 6);
908 }
909
910 // Check for "++nested" flag.
911 if ((STRNCMP(cmd, "++nested", 8) == 0 && VIM_ISWHITE(cmd[8])))
912 {
913 if (nested)
914 semsg(_(e_duparg2), "++nested");
915 nested = TRUE;
916 cmd = skipwhite(cmd + 8);
917 }
918
919 // Check for the old "nested" flag.
920 if (STRNCMP(cmd, "nested", 6) == 0 && VIM_ISWHITE(cmd[6]))
921 {
922 if (nested)
923 semsg(_(e_duparg2), "nested");
924 nested = TRUE;
925 cmd = skipwhite(cmd + 6);
926 }
927 }
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100928 }
929
930 /*
931 * Find the start of the commands.
932 * Expand <sfile> in it.
933 */
934 if (*cmd != NUL)
935 {
936 cmd = expand_sfile(cmd);
937 if (cmd == NULL) // some error
938 return;
939 need_free = TRUE;
940 }
941 }
942
943 /*
944 * Print header when showing autocommands.
945 */
946 if (!forceit && *cmd == NUL)
947 // Highlight title
948 msg_puts_title(_("\n--- Autocommands ---"));
949
950 /*
951 * Loop over the events.
952 */
953 last_event = (event_T)-1; // for listing the event name
954 last_group = AUGROUP_ERROR; // for listing the group name
955 if (*arg == '*' || *arg == NUL || *arg == '|')
956 {
957 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
958 event = (event_T)((int)event + 1))
959 if (do_autocmd_event(event, pat,
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200960 once, nested, cmd, forceit, group) == FAIL)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100961 break;
962 }
963 else
964 {
965 while (*arg && *arg != '|' && !VIM_ISWHITE(*arg))
966 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
Bram Moolenaareb93f3f2019-04-04 15:04:56 +0200967 once, nested, cmd, forceit, group) == FAIL)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +0100968 break;
969 }
970
971 if (need_free)
972 vim_free(cmd);
973 vim_free(envpat);
974}
975
976/*
977 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
978 * The "argp" argument is advanced to the following argument.
979 *
980 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
981 */
982 static int
983au_get_grouparg(char_u **argp)
984{
985 char_u *group_name;
986 char_u *p;
987 char_u *arg = *argp;
988 int group = AUGROUP_ALL;
989
990 for (p = arg; *p && !VIM_ISWHITE(*p) && *p != '|'; ++p)
991 ;
992 if (p > arg)
993 {
994 group_name = vim_strnsave(arg, (int)(p - arg));
995 if (group_name == NULL) // out of memory
996 return AUGROUP_ERROR;
997 group = au_find_group(group_name);
998 if (group == AUGROUP_ERROR)
999 group = AUGROUP_ALL; // no match, use all groups
1000 else
1001 *argp = skipwhite(p); // match, skip over group name
1002 vim_free(group_name);
1003 }
1004 return group;
1005}
1006
1007/*
1008 * do_autocmd() for one event.
1009 * If *pat == NUL do for all patterns.
1010 * If *cmd == NUL show entries.
1011 * If forceit == TRUE delete entries.
1012 * If group is not AUGROUP_ALL, only use this group.
1013 */
1014 static int
1015do_autocmd_event(
1016 event_T event,
1017 char_u *pat,
Bram Moolenaareb93f3f2019-04-04 15:04:56 +02001018 int once,
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001019 int nested,
1020 char_u *cmd,
1021 int forceit,
1022 int group)
1023{
1024 AutoPat *ap;
1025 AutoPat **prev_ap;
1026 AutoCmd *ac;
1027 AutoCmd **prev_ac;
1028 int brace_level;
1029 char_u *endpat;
1030 int findgroup;
1031 int allgroups;
1032 int patlen;
1033 int is_buflocal;
1034 int buflocal_nr;
Bram Moolenaarc667da52019-11-30 20:52:27 +01001035 char_u buflocal_pat[25]; // for "<buffer=X>"
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001036
1037 if (group == AUGROUP_ALL)
1038 findgroup = current_augroup;
1039 else
1040 findgroup = group;
1041 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
1042
1043 /*
1044 * Show or delete all patterns for an event.
1045 */
1046 if (*pat == NUL)
1047 {
Bram Moolenaaraeea7212020-04-02 18:50:46 +02001048 FOR_ALL_AUTOCMD_PATTERNS(event, ap)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001049 {
1050 if (forceit) // delete the AutoPat, if it's in the current group
1051 {
1052 if (ap->group == findgroup)
1053 au_remove_pat(ap);
1054 }
1055 else if (group == AUGROUP_ALL || ap->group == group)
1056 show_autocmd(ap, event);
1057 }
1058 }
1059
1060 /*
1061 * Loop through all the specified patterns.
1062 */
1063 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
1064 {
1065 /*
1066 * Find end of the pattern.
1067 * Watch out for a comma in braces, like "*.\{obj,o\}".
1068 */
1069 brace_level = 0;
1070 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
1071 || (endpat > pat && endpat[-1] == '\\')); ++endpat)
1072 {
1073 if (*endpat == '{')
1074 brace_level++;
1075 else if (*endpat == '}')
1076 brace_level--;
1077 }
1078 if (pat == endpat) // ignore single comma
1079 continue;
1080 patlen = (int)(endpat - pat);
1081
1082 /*
1083 * detect special <buflocal[=X]> buffer-local patterns
1084 */
1085 is_buflocal = FALSE;
1086 buflocal_nr = 0;
1087
1088 if (patlen >= 8 && STRNCMP(pat, "<buffer", 7) == 0
1089 && pat[patlen - 1] == '>')
1090 {
1091 // "<buffer...>": Error will be printed only for addition.
1092 // printing and removing will proceed silently.
1093 is_buflocal = TRUE;
1094 if (patlen == 8)
1095 // "<buffer>"
1096 buflocal_nr = curbuf->b_fnum;
1097 else if (patlen > 9 && pat[7] == '=')
1098 {
1099 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13) == 0)
1100 // "<buffer=abuf>"
1101 buflocal_nr = autocmd_bufnr;
1102 else if (skipdigits(pat + 8) == pat + patlen - 1)
1103 // "<buffer=123>"
1104 buflocal_nr = atoi((char *)pat + 8);
1105 }
1106 }
1107
1108 if (is_buflocal)
1109 {
1110 // normalize pat into standard "<buffer>#N" form
1111 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
1112 pat = buflocal_pat; // can modify pat and patlen
1113 patlen = (int)STRLEN(buflocal_pat); // but not endpat
1114 }
1115
1116 /*
1117 * Find AutoPat entries with this pattern. When adding a command it
1118 * always goes at or after the last one, so start at the end.
1119 */
1120 if (!forceit && *cmd != NUL && last_autopat[(int)event] != NULL)
1121 prev_ap = &last_autopat[(int)event];
1122 else
1123 prev_ap = &first_autopat[(int)event];
1124 while ((ap = *prev_ap) != NULL)
1125 {
1126 if (ap->pat != NULL)
1127 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001128 /*
1129 * Accept a pattern when:
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001130 * - a group was specified and it's that group, or a group was
1131 * not specified and it's the current group, or a group was
1132 * not specified and we are listing
1133 * - the length of the pattern matches
1134 * - the pattern matches.
1135 * For <buffer[=X]>, this condition works because we normalize
1136 * all buffer-local patterns.
1137 */
1138 if ((allgroups || ap->group == findgroup)
1139 && ap->patlen == patlen
1140 && STRNCMP(pat, ap->pat, patlen) == 0)
1141 {
1142 /*
1143 * Remove existing autocommands.
1144 * If adding any new autocmd's for this AutoPat, don't
1145 * delete the pattern from the autopat list, append to
1146 * this list.
1147 */
1148 if (forceit)
1149 {
1150 if (*cmd != NUL && ap->next == NULL)
1151 {
1152 au_remove_cmds(ap);
1153 break;
1154 }
1155 au_remove_pat(ap);
1156 }
1157
1158 /*
1159 * Show autocmd's for this autopat, or buflocals <buffer=X>
1160 */
1161 else if (*cmd == NUL)
1162 show_autocmd(ap, event);
1163
1164 /*
1165 * Add autocmd to this autopat, if it's the last one.
1166 */
1167 else if (ap->next == NULL)
1168 break;
1169 }
1170 }
1171 prev_ap = &ap->next;
1172 }
1173
1174 /*
1175 * Add a new command.
1176 */
1177 if (*cmd != NUL)
1178 {
1179 /*
1180 * If the pattern we want to add a command to does appear at the
1181 * end of the list (or not is not in the list at all), add the
1182 * pattern at the end of the list.
1183 */
1184 if (ap == NULL)
1185 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001186 // refuse to add buffer-local ap if buffer number is invalid
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001187 if (is_buflocal && (buflocal_nr == 0
1188 || buflist_findnr(buflocal_nr) == NULL))
1189 {
1190 semsg(_("E680: <buffer=%d>: invalid buffer number "),
1191 buflocal_nr);
1192 return FAIL;
1193 }
1194
Bram Moolenaarc799fe22019-05-28 23:08:19 +02001195 ap = ALLOC_ONE(AutoPat);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001196 if (ap == NULL)
1197 return FAIL;
1198 ap->pat = vim_strnsave(pat, patlen);
1199 ap->patlen = patlen;
1200 if (ap->pat == NULL)
1201 {
1202 vim_free(ap);
1203 return FAIL;
1204 }
1205
1206 if (is_buflocal)
1207 {
1208 ap->buflocal_nr = buflocal_nr;
1209 ap->reg_prog = NULL;
1210 }
1211 else
1212 {
1213 char_u *reg_pat;
1214
1215 ap->buflocal_nr = 0;
1216 reg_pat = file_pat_to_reg_pat(pat, endpat,
1217 &ap->allow_dirs, TRUE);
1218 if (reg_pat != NULL)
1219 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
1220 vim_free(reg_pat);
1221 if (reg_pat == NULL || ap->reg_prog == NULL)
1222 {
1223 vim_free(ap->pat);
1224 vim_free(ap);
1225 return FAIL;
1226 }
1227 }
1228 ap->cmds = NULL;
1229 *prev_ap = ap;
1230 last_autopat[(int)event] = ap;
1231 ap->next = NULL;
1232 if (group == AUGROUP_ALL)
1233 ap->group = current_augroup;
1234 else
1235 ap->group = group;
1236 }
1237
1238 /*
1239 * Add the autocmd at the end of the AutoCmd list.
1240 */
1241 prev_ac = &(ap->cmds);
1242 while ((ac = *prev_ac) != NULL)
1243 prev_ac = &ac->next;
Bram Moolenaarc799fe22019-05-28 23:08:19 +02001244 ac = ALLOC_ONE(AutoCmd);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001245 if (ac == NULL)
1246 return FAIL;
1247 ac->cmd = vim_strsave(cmd);
1248#ifdef FEAT_EVAL
1249 ac->script_ctx = current_sctx;
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01001250 ac->script_ctx.sc_lnum += SOURCING_LNUM;
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001251#endif
1252 if (ac->cmd == NULL)
1253 {
1254 vim_free(ac);
1255 return FAIL;
1256 }
1257 ac->next = NULL;
1258 *prev_ac = ac;
Bram Moolenaareb93f3f2019-04-04 15:04:56 +02001259 ac->once = once;
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001260 ac->nested = nested;
1261 }
1262 }
1263
1264 au_cleanup(); // may really delete removed patterns/commands now
1265 return OK;
1266}
1267
1268/*
1269 * Implementation of ":doautocmd [group] event [fname]".
1270 * Return OK for success, FAIL for failure;
1271 */
1272 int
1273do_doautocmd(
1274 char_u *arg,
1275 int do_msg, // give message for no matching autocmds?
1276 int *did_something)
1277{
1278 char_u *fname;
1279 int nothing_done = TRUE;
1280 int group;
1281
1282 if (did_something != NULL)
1283 *did_something = FALSE;
1284
1285 /*
1286 * Check for a legal group name. If not, use AUGROUP_ALL.
1287 */
1288 group = au_get_grouparg(&arg);
1289 if (arg == NULL) // out of memory
1290 return FAIL;
1291
1292 if (*arg == '*')
1293 {
1294 emsg(_("E217: Can't execute autocommands for ALL events"));
1295 return FAIL;
1296 }
1297
1298 /*
1299 * Scan over the events.
1300 * If we find an illegal name, return here, don't do anything.
1301 */
1302 fname = find_end_event(arg, group != AUGROUP_ALL);
1303 if (fname == NULL)
1304 return FAIL;
1305
1306 fname = skipwhite(fname);
1307
1308 /*
1309 * Loop over the events.
1310 */
1311 while (*arg && !ends_excmd(*arg) && !VIM_ISWHITE(*arg))
1312 if (apply_autocmds_group(event_name2nr(arg, &arg),
1313 fname, NULL, TRUE, group, curbuf, NULL))
1314 nothing_done = FALSE;
1315
1316 if (nothing_done && do_msg)
1317 msg(_("No matching autocommands"));
1318 if (did_something != NULL)
1319 *did_something = !nothing_done;
1320
1321#ifdef FEAT_EVAL
1322 return aborting() ? FAIL : OK;
1323#else
1324 return OK;
1325#endif
1326}
1327
1328/*
1329 * ":doautoall": execute autocommands for each loaded buffer.
1330 */
1331 void
1332ex_doautoall(exarg_T *eap)
1333{
1334 int retval;
1335 aco_save_T aco;
1336 buf_T *buf;
1337 bufref_T bufref;
1338 char_u *arg = eap->arg;
1339 int call_do_modelines = check_nomodeline(&arg);
1340 int did_aucmd;
1341
1342 /*
1343 * This is a bit tricky: For some commands curwin->w_buffer needs to be
1344 * equal to curbuf, but for some buffers there may not be a window.
1345 * So we change the buffer for the current window for a moment. This
1346 * gives problems when the autocommands make changes to the list of
1347 * buffers or windows...
1348 */
1349 FOR_ALL_BUFFERS(buf)
1350 {
Bram Moolenaar89adc3a2019-05-30 17:29:40 +02001351 if (buf->b_ml.ml_mfp != NULL)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001352 {
1353 // find a window for this buffer and save some values
1354 aucmd_prepbuf(&aco, buf);
1355 set_bufref(&bufref, buf);
1356
1357 // execute the autocommands for this buffer
1358 retval = do_doautocmd(arg, FALSE, &did_aucmd);
1359
1360 if (call_do_modelines && did_aucmd)
1361 {
1362 // Execute the modeline settings, but don't set window-local
1363 // options if we are using the current window for another
1364 // buffer.
1365 do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
1366 }
1367
1368 // restore the current window
1369 aucmd_restbuf(&aco);
1370
1371 // stop if there is some error or buffer was deleted
1372 if (retval == FAIL || !bufref_valid(&bufref))
1373 break;
1374 }
1375 }
1376
1377 check_cursor(); // just in case lines got deleted
1378}
1379
1380/*
1381 * Check *argp for <nomodeline>. When it is present return FALSE, otherwise
1382 * return TRUE and advance *argp to after it.
1383 * Thus return TRUE when do_modelines() should be called.
1384 */
1385 int
1386check_nomodeline(char_u **argp)
1387{
1388 if (STRNCMP(*argp, "<nomodeline>", 12) == 0)
1389 {
1390 *argp = skipwhite(*argp + 12);
1391 return FALSE;
1392 }
1393 return TRUE;
1394}
1395
1396/*
1397 * Prepare for executing autocommands for (hidden) buffer "buf".
1398 * Search for a visible window containing the current buffer. If there isn't
1399 * one then use "aucmd_win".
1400 * Set "curbuf" and "curwin" to match "buf".
1401 */
1402 void
1403aucmd_prepbuf(
1404 aco_save_T *aco, // structure to save values in
1405 buf_T *buf) // new curbuf
1406{
1407 win_T *win;
1408 int save_ea;
1409#ifdef FEAT_AUTOCHDIR
1410 int save_acd;
1411#endif
1412
1413 // Find a window that is for the new buffer
1414 if (buf == curbuf) // be quick when buf is curbuf
1415 win = curwin;
1416 else
1417 FOR_ALL_WINDOWS(win)
1418 if (win->w_buffer == buf)
1419 break;
1420
1421 // Allocate "aucmd_win" when needed. If this fails (out of memory) fall
1422 // back to using the current window.
1423 if (win == NULL && aucmd_win == NULL)
1424 {
Bram Moolenaar4d784b22019-05-25 19:51:39 +02001425 aucmd_win = win_alloc_popup_win();
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001426 if (aucmd_win == NULL)
1427 win = curwin;
1428 }
1429 if (win == NULL && aucmd_win_used)
1430 // Strange recursive autocommand, fall back to using the current
1431 // window. Expect a few side effects...
1432 win = curwin;
1433
1434 aco->save_curwin = curwin;
1435 aco->save_curbuf = curbuf;
1436 aco->save_prevwin = prevwin;
1437 if (win != NULL)
1438 {
1439 // There is a window for "buf" in the current tab page, make it the
1440 // curwin. This is preferred, it has the least side effects (esp. if
1441 // "buf" is curbuf).
1442 aco->use_aucmd_win = FALSE;
1443 curwin = win;
1444 }
1445 else
1446 {
1447 // There is no window for "buf", use "aucmd_win". To minimize the side
1448 // effects, insert it in the current tab page.
1449 // Anything related to a window (e.g., setting folds) may have
1450 // unexpected results.
1451 aco->use_aucmd_win = TRUE;
1452 aucmd_win_used = TRUE;
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001453
Bram Moolenaar4d784b22019-05-25 19:51:39 +02001454 win_init_popup_win(aucmd_win, buf);
1455
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001456 aco->globaldir = globaldir;
1457 globaldir = NULL;
1458
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001459 // Split the current window, put the aucmd_win in the upper half.
1460 // We don't want the BufEnter or WinEnter autocommands.
1461 block_autocmds();
1462 make_snapshot(SNAP_AUCMD_IDX);
1463 save_ea = p_ea;
1464 p_ea = FALSE;
1465
1466#ifdef FEAT_AUTOCHDIR
1467 // Prevent chdir() call in win_enter_ext(), through do_autochdir().
1468 save_acd = p_acd;
1469 p_acd = FALSE;
1470#endif
1471
1472 (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
1473 (void)win_comp_pos(); // recompute window positions
1474 p_ea = save_ea;
1475#ifdef FEAT_AUTOCHDIR
1476 p_acd = save_acd;
1477#endif
1478 unblock_autocmds();
1479 curwin = aucmd_win;
1480 }
1481 curbuf = buf;
1482 aco->new_curwin = curwin;
1483 set_bufref(&aco->new_curbuf, curbuf);
1484}
1485
1486/*
1487 * Cleanup after executing autocommands for a (hidden) buffer.
1488 * Restore the window as it was (if possible).
1489 */
1490 void
1491aucmd_restbuf(
1492 aco_save_T *aco) // structure holding saved values
1493{
1494 int dummy;
1495
1496 if (aco->use_aucmd_win)
1497 {
1498 --curbuf->b_nwindows;
1499 // Find "aucmd_win", it can't be closed, but it may be in another tab
1500 // page. Do not trigger autocommands here.
1501 block_autocmds();
1502 if (curwin != aucmd_win)
1503 {
1504 tabpage_T *tp;
1505 win_T *wp;
1506
1507 FOR_ALL_TAB_WINDOWS(tp, wp)
1508 {
1509 if (wp == aucmd_win)
1510 {
1511 if (tp != curtab)
1512 goto_tabpage_tp(tp, TRUE, TRUE);
1513 win_goto(aucmd_win);
1514 goto win_found;
1515 }
1516 }
1517 }
1518win_found:
1519
1520 // Remove the window and frame from the tree of frames.
1521 (void)winframe_remove(curwin, &dummy, NULL);
1522 win_remove(curwin, NULL);
1523 aucmd_win_used = FALSE;
1524 last_status(FALSE); // may need to remove last status line
1525
1526 if (!valid_tabpage_win(curtab))
1527 // no valid window in current tabpage
1528 close_tabpage(curtab);
1529
1530 restore_snapshot(SNAP_AUCMD_IDX, FALSE);
1531 (void)win_comp_pos(); // recompute window positions
1532 unblock_autocmds();
1533
1534 if (win_valid(aco->save_curwin))
1535 curwin = aco->save_curwin;
1536 else
1537 // Hmm, original window disappeared. Just use the first one.
1538 curwin = firstwin;
1539 if (win_valid(aco->save_prevwin))
1540 prevwin = aco->save_prevwin;
1541#ifdef FEAT_EVAL
1542 vars_clear(&aucmd_win->w_vars->dv_hashtab); // free all w: variables
1543 hash_init(&aucmd_win->w_vars->dv_hashtab); // re-use the hashtab
1544#endif
1545 curbuf = curwin->w_buffer;
1546
1547 vim_free(globaldir);
1548 globaldir = aco->globaldir;
1549
1550 // the buffer contents may have changed
1551 check_cursor();
1552 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
1553 {
1554 curwin->w_topline = curbuf->b_ml.ml_line_count;
1555#ifdef FEAT_DIFF
1556 curwin->w_topfill = 0;
1557#endif
1558 }
1559#if defined(FEAT_GUI)
1560 // Hide the scrollbars from the aucmd_win and update.
1561 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_LEFT], FALSE);
1562 gui_mch_enable_scrollbar(&aucmd_win->w_scrollbars[SBAR_RIGHT], FALSE);
1563 gui_may_update_scrollbars();
1564#endif
1565 }
1566 else
1567 {
1568 // restore curwin
1569 if (win_valid(aco->save_curwin))
1570 {
1571 // Restore the buffer which was previously edited by curwin, if
1572 // it was changed, we are still the same window and the buffer is
1573 // valid.
1574 if (curwin == aco->new_curwin
1575 && curbuf != aco->new_curbuf.br_buf
1576 && bufref_valid(&aco->new_curbuf)
1577 && aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL)
1578 {
1579# if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
1580 if (curwin->w_s == &curbuf->b_s)
1581 curwin->w_s = &aco->new_curbuf.br_buf->b_s;
1582# endif
1583 --curbuf->b_nwindows;
1584 curbuf = aco->new_curbuf.br_buf;
1585 curwin->w_buffer = curbuf;
1586 ++curbuf->b_nwindows;
1587 }
1588
1589 curwin = aco->save_curwin;
1590 curbuf = curwin->w_buffer;
1591 if (win_valid(aco->save_prevwin))
1592 prevwin = aco->save_prevwin;
Bram Moolenaar32aa1022019-11-02 22:54:41 +01001593 // In case the autocommand moves the cursor to a position that
1594 // does not exist in curbuf.
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001595 check_cursor();
1596 }
1597 }
1598}
1599
1600static int autocmd_nested = FALSE;
1601
1602/*
1603 * Execute autocommands for "event" and file name "fname".
1604 * Return TRUE if some commands were executed.
1605 */
1606 int
1607apply_autocmds(
1608 event_T event,
1609 char_u *fname, // NULL or empty means use actual file name
1610 char_u *fname_io, // fname to use for <afile> on cmdline
1611 int force, // when TRUE, ignore autocmd_busy
1612 buf_T *buf) // buffer for <abuf>
1613{
1614 return apply_autocmds_group(event, fname, fname_io, force,
1615 AUGROUP_ALL, buf, NULL);
1616}
1617
1618/*
1619 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
1620 * setting v:filearg.
1621 */
1622 int
1623apply_autocmds_exarg(
1624 event_T event,
1625 char_u *fname,
1626 char_u *fname_io,
1627 int force,
1628 buf_T *buf,
1629 exarg_T *eap)
1630{
1631 return apply_autocmds_group(event, fname, fname_io, force,
1632 AUGROUP_ALL, buf, eap);
1633}
1634
1635/*
1636 * Like apply_autocmds(), but handles the caller's retval. If the script
1637 * processing is being aborted or if retval is FAIL when inside a try
1638 * conditional, no autocommands are executed. If otherwise the autocommands
1639 * cause the script to be aborted, retval is set to FAIL.
1640 */
1641 int
1642apply_autocmds_retval(
1643 event_T event,
1644 char_u *fname, // NULL or empty means use actual file name
1645 char_u *fname_io, // fname to use for <afile> on cmdline
1646 int force, // when TRUE, ignore autocmd_busy
1647 buf_T *buf, // buffer for <abuf>
1648 int *retval) // pointer to caller's retval
1649{
1650 int did_cmd;
1651
1652#ifdef FEAT_EVAL
1653 if (should_abort(*retval))
1654 return FALSE;
1655#endif
1656
1657 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
1658 AUGROUP_ALL, buf, NULL);
1659 if (did_cmd
1660#ifdef FEAT_EVAL
1661 && aborting()
1662#endif
1663 )
1664 *retval = FAIL;
1665 return did_cmd;
1666}
1667
1668/*
1669 * Return TRUE when there is a CursorHold autocommand defined.
1670 */
Bram Moolenaar5843f5f2019-08-20 20:13:45 +02001671 static int
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001672has_cursorhold(void)
1673{
1674 return (first_autopat[(int)(get_real_state() == NORMAL_BUSY
1675 ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL);
1676}
1677
1678/*
1679 * Return TRUE if the CursorHold event can be triggered.
1680 */
1681 int
1682trigger_cursorhold(void)
1683{
1684 int state;
1685
1686 if (!did_cursorhold
1687 && has_cursorhold()
1688 && reg_recording == 0
1689 && typebuf.tb_len == 0
Bram Moolenaare2c453d2019-08-21 14:37:09 +02001690 && !ins_compl_active())
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001691 {
1692 state = get_real_state();
1693 if (state == NORMAL_BUSY || (state & INSERT) != 0)
1694 return TRUE;
1695 }
1696 return FALSE;
1697}
1698
1699/*
1700 * Return TRUE when there is a CursorMoved autocommand defined.
1701 */
1702 int
1703has_cursormoved(void)
1704{
1705 return (first_autopat[(int)EVENT_CURSORMOVED] != NULL);
1706}
1707
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001708/*
1709 * Return TRUE when there is a CursorMovedI autocommand defined.
1710 */
1711 int
1712has_cursormovedI(void)
1713{
1714 return (first_autopat[(int)EVENT_CURSORMOVEDI] != NULL);
1715}
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001716
1717/*
1718 * Return TRUE when there is a TextChanged autocommand defined.
1719 */
1720 int
1721has_textchanged(void)
1722{
1723 return (first_autopat[(int)EVENT_TEXTCHANGED] != NULL);
1724}
1725
1726/*
1727 * Return TRUE when there is a TextChangedI autocommand defined.
1728 */
1729 int
1730has_textchangedI(void)
1731{
1732 return (first_autopat[(int)EVENT_TEXTCHANGEDI] != NULL);
1733}
1734
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001735/*
1736 * Return TRUE when there is a TextChangedP autocommand defined.
1737 */
1738 int
1739has_textchangedP(void)
1740{
1741 return (first_autopat[(int)EVENT_TEXTCHANGEDP] != NULL);
1742}
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001743
1744/*
1745 * Return TRUE when there is an InsertCharPre autocommand defined.
1746 */
1747 int
1748has_insertcharpre(void)
1749{
1750 return (first_autopat[(int)EVENT_INSERTCHARPRE] != NULL);
1751}
1752
1753/*
1754 * Return TRUE when there is an CmdUndefined autocommand defined.
1755 */
1756 int
1757has_cmdundefined(void)
1758{
1759 return (first_autopat[(int)EVENT_CMDUNDEFINED] != NULL);
1760}
1761
1762/*
1763 * Return TRUE when there is an FuncUndefined autocommand defined.
1764 */
1765 int
1766has_funcundefined(void)
1767{
1768 return (first_autopat[(int)EVENT_FUNCUNDEFINED] != NULL);
1769}
1770
1771#if defined(FEAT_EVAL) || defined(PROTO)
1772/*
1773 * Return TRUE when there is a TextYankPost autocommand defined.
1774 */
1775 int
1776has_textyankpost(void)
1777{
1778 return (first_autopat[(int)EVENT_TEXTYANKPOST] != NULL);
1779}
1780#endif
1781
Bram Moolenaard7f246c2019-04-08 18:15:41 +02001782#if defined(FEAT_EVAL) || defined(PROTO)
1783/*
1784 * Return TRUE when there is a CompleteChanged autocommand defined.
1785 */
1786 int
1787has_completechanged(void)
1788{
1789 return (first_autopat[(int)EVENT_COMPLETECHANGED] != NULL);
1790}
1791#endif
1792
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001793/*
1794 * Execute autocommands for "event" and file name "fname".
1795 * Return TRUE if some commands were executed.
1796 */
1797 static int
1798apply_autocmds_group(
1799 event_T event,
1800 char_u *fname, // NULL or empty means use actual file name
1801 char_u *fname_io, // fname to use for <afile> on cmdline, NULL means
1802 // use fname
1803 int force, // when TRUE, ignore autocmd_busy
1804 int group, // group ID, or AUGROUP_ALL
1805 buf_T *buf, // buffer for <abuf>
1806 exarg_T *eap UNUSED) // command arguments
1807{
1808 char_u *sfname = NULL; // short file name
1809 char_u *tail;
1810 int save_changed;
1811 buf_T *old_curbuf;
1812 int retval = FALSE;
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001813 char_u *save_autocmd_fname;
1814 int save_autocmd_fname_full;
1815 int save_autocmd_bufnr;
1816 char_u *save_autocmd_match;
1817 int save_autocmd_busy;
1818 int save_autocmd_nested;
1819 static int nesting = 0;
1820 AutoPatCmd patcmd;
1821 AutoPat *ap;
1822#ifdef FEAT_EVAL
1823 sctx_T save_current_sctx;
1824 funccal_entry_T funccal_entry;
1825 char_u *save_cmdarg;
1826 long save_cmdbang;
1827#endif
1828 static int filechangeshell_busy = FALSE;
1829#ifdef FEAT_PROFILE
1830 proftime_T wait_time;
1831#endif
1832 int did_save_redobuff = FALSE;
1833 save_redo_T save_redo;
1834 int save_KeyTyped = KeyTyped;
Bram Moolenaare31ee862020-01-07 20:59:34 +01001835 ESTACK_CHECK_DECLARATION
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01001836
1837 /*
1838 * Quickly return if there are no autocommands for this event or
1839 * autocommands are blocked.
1840 */
1841 if (event == NUM_EVENTS || first_autopat[(int)event] == NULL
1842 || autocmd_blocked > 0)
1843 goto BYPASS_AU;
1844
1845 /*
1846 * When autocommands are busy, new autocommands are only executed when
1847 * explicitly enabled with the "nested" flag.
1848 */
1849 if (autocmd_busy && !(force || autocmd_nested))
1850 goto BYPASS_AU;
1851
1852#ifdef FEAT_EVAL
1853 /*
1854 * Quickly return when immediately aborting on error, or when an interrupt
1855 * occurred or an exception was thrown but not caught.
1856 */
1857 if (aborting())
1858 goto BYPASS_AU;
1859#endif
1860
1861 /*
1862 * FileChangedShell never nests, because it can create an endless loop.
1863 */
1864 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
1865 || event == EVENT_FILECHANGEDSHELLPOST))
1866 goto BYPASS_AU;
1867
1868 /*
1869 * Ignore events in 'eventignore'.
1870 */
1871 if (event_ignored(event))
1872 goto BYPASS_AU;
1873
1874 /*
1875 * Allow nesting of autocommands, but restrict the depth, because it's
1876 * possible to create an endless loop.
1877 */
1878 if (nesting == 10)
1879 {
1880 emsg(_("E218: autocommand nesting too deep"));
1881 goto BYPASS_AU;
1882 }
1883
1884 /*
1885 * Check if these autocommands are disabled. Used when doing ":all" or
1886 * ":ball".
1887 */
1888 if ( (autocmd_no_enter
1889 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
1890 || (autocmd_no_leave
1891 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
1892 goto BYPASS_AU;
1893
1894 /*
1895 * Save the autocmd_* variables and info about the current buffer.
1896 */
1897 save_autocmd_fname = autocmd_fname;
1898 save_autocmd_fname_full = autocmd_fname_full;
1899 save_autocmd_bufnr = autocmd_bufnr;
1900 save_autocmd_match = autocmd_match;
1901 save_autocmd_busy = autocmd_busy;
1902 save_autocmd_nested = autocmd_nested;
1903 save_changed = curbuf->b_changed;
1904 old_curbuf = curbuf;
1905
1906 /*
1907 * Set the file name to be used for <afile>.
1908 * Make a copy to avoid that changing a buffer name or directory makes it
1909 * invalid.
1910 */
1911 if (fname_io == NULL)
1912 {
1913 if (event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE
1914 || event == EVENT_OPTIONSET)
1915 autocmd_fname = NULL;
1916 else if (fname != NULL && !ends_excmd(*fname))
1917 autocmd_fname = fname;
1918 else if (buf != NULL)
1919 autocmd_fname = buf->b_ffname;
1920 else
1921 autocmd_fname = NULL;
1922 }
1923 else
1924 autocmd_fname = fname_io;
1925 if (autocmd_fname != NULL)
1926 autocmd_fname = vim_strsave(autocmd_fname);
1927 autocmd_fname_full = FALSE; // call FullName_save() later
1928
1929 /*
1930 * Set the buffer number to be used for <abuf>.
1931 */
1932 if (buf == NULL)
1933 autocmd_bufnr = 0;
1934 else
1935 autocmd_bufnr = buf->b_fnum;
1936
1937 /*
1938 * When the file name is NULL or empty, use the file name of buffer "buf".
1939 * Always use the full path of the file name to match with, in case
1940 * "allow_dirs" is set.
1941 */
1942 if (fname == NULL || *fname == NUL)
1943 {
1944 if (buf == NULL)
1945 fname = NULL;
1946 else
1947 {
1948#ifdef FEAT_SYN_HL
1949 if (event == EVENT_SYNTAX)
1950 fname = buf->b_p_syn;
1951 else
1952#endif
1953 if (event == EVENT_FILETYPE)
1954 fname = buf->b_p_ft;
1955 else
1956 {
1957 if (buf->b_sfname != NULL)
1958 sfname = vim_strsave(buf->b_sfname);
1959 fname = buf->b_ffname;
1960 }
1961 }
1962 if (fname == NULL)
1963 fname = (char_u *)"";
1964 fname = vim_strsave(fname); // make a copy, so we can change it
1965 }
1966 else
1967 {
1968 sfname = vim_strsave(fname);
1969 // Don't try expanding FileType, Syntax, FuncUndefined, WindowID,
1970 // ColorScheme, QuickFixCmd* or DirChanged
1971 if (event == EVENT_FILETYPE
1972 || event == EVENT_SYNTAX
1973 || event == EVENT_CMDLINECHANGED
1974 || event == EVENT_CMDLINEENTER
1975 || event == EVENT_CMDLINELEAVE
1976 || event == EVENT_CMDWINENTER
1977 || event == EVENT_CMDWINLEAVE
1978 || event == EVENT_CMDUNDEFINED
1979 || event == EVENT_FUNCUNDEFINED
1980 || event == EVENT_REMOTEREPLY
1981 || event == EVENT_SPELLFILEMISSING
1982 || event == EVENT_QUICKFIXCMDPRE
1983 || event == EVENT_COLORSCHEME
1984 || event == EVENT_COLORSCHEMEPRE
1985 || event == EVENT_OPTIONSET
1986 || event == EVENT_QUICKFIXCMDPOST
1987 || event == EVENT_DIRCHANGED)
1988 {
1989 fname = vim_strsave(fname);
1990 autocmd_fname_full = TRUE; // don't expand it later
1991 }
1992 else
1993 fname = FullName_save(fname, FALSE);
1994 }
1995 if (fname == NULL) // out of memory
1996 {
1997 vim_free(sfname);
1998 retval = FALSE;
1999 goto BYPASS_AU;
2000 }
2001
2002#ifdef BACKSLASH_IN_FILENAME
2003 /*
2004 * Replace all backslashes with forward slashes. This makes the
2005 * autocommand patterns portable between Unix and MS-DOS.
2006 */
2007 if (sfname != NULL)
2008 forward_slash(sfname);
2009 forward_slash(fname);
2010#endif
2011
2012#ifdef VMS
2013 // remove version for correct match
2014 if (sfname != NULL)
2015 vms_remove_version(sfname);
2016 vms_remove_version(fname);
2017#endif
2018
2019 /*
2020 * Set the name to be used for <amatch>.
2021 */
2022 autocmd_match = fname;
2023
2024
2025 // Don't redraw while doing autocommands.
2026 ++RedrawingDisabled;
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002027
2028 // name and lnum are filled in later
2029 estack_push(ETYPE_AUCMD, NULL, 0);
Bram Moolenaare31ee862020-01-07 20:59:34 +01002030 ESTACK_CHECK_SETUP
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002031
2032#ifdef FEAT_EVAL
2033 save_current_sctx = current_sctx;
2034
2035# ifdef FEAT_PROFILE
2036 if (do_profiling == PROF_YES)
2037 prof_child_enter(&wait_time); // doesn't count for the caller itself
2038# endif
2039
2040 // Don't use local function variables, if called from a function.
2041 save_funccal(&funccal_entry);
2042#endif
2043
2044 /*
2045 * When starting to execute autocommands, save the search patterns.
2046 */
2047 if (!autocmd_busy)
2048 {
2049 save_search_patterns();
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002050 if (!ins_compl_active())
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002051 {
2052 saveRedobuff(&save_redo);
2053 did_save_redobuff = TRUE;
2054 }
2055 did_filetype = keep_filetype;
2056 }
2057
2058 /*
2059 * Note that we are applying autocmds. Some commands need to know.
2060 */
2061 autocmd_busy = TRUE;
2062 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
2063 ++nesting; // see matching decrement below
2064
2065 // Remember that FileType was triggered. Used for did_filetype().
2066 if (event == EVENT_FILETYPE)
2067 did_filetype = TRUE;
2068
2069 tail = gettail(fname);
2070
2071 // Find first autocommand that matches
2072 patcmd.curpat = first_autopat[(int)event];
2073 patcmd.nextcmd = NULL;
2074 patcmd.group = group;
2075 patcmd.fname = fname;
2076 patcmd.sfname = sfname;
2077 patcmd.tail = tail;
2078 patcmd.event = event;
2079 patcmd.arg_bufnr = autocmd_bufnr;
2080 patcmd.next = NULL;
2081 auto_next_pat(&patcmd, FALSE);
2082
2083 // found one, start executing the autocommands
2084 if (patcmd.curpat != NULL)
2085 {
2086 // add to active_apc_list
2087 patcmd.next = active_apc_list;
2088 active_apc_list = &patcmd;
2089
2090#ifdef FEAT_EVAL
2091 // set v:cmdarg (only when there is a matching pattern)
2092 save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG);
2093 if (eap != NULL)
2094 {
2095 save_cmdarg = set_cmdarg(eap, NULL);
2096 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
2097 }
2098 else
2099 save_cmdarg = NULL; // avoid gcc warning
2100#endif
2101 retval = TRUE;
2102 // mark the last pattern, to avoid an endless loop when more patterns
2103 // are added when executing autocommands
2104 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
2105 ap->last = FALSE;
2106 ap->last = TRUE;
Bram Moolenaara68e5952019-04-25 22:22:01 +02002107
2108 // make sure cursor and topline are valid
2109 check_lnums(TRUE);
2110
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002111 do_cmdline(NULL, getnextac, (void *)&patcmd,
2112 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
Bram Moolenaara68e5952019-04-25 22:22:01 +02002113
2114 // restore cursor and topline, unless they were changed
2115 reset_lnums();
2116
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002117#ifdef FEAT_EVAL
2118 if (eap != NULL)
2119 {
2120 (void)set_cmdarg(NULL, save_cmdarg);
2121 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
2122 }
2123#endif
2124 // delete from active_apc_list
2125 if (active_apc_list == &patcmd) // just in case
2126 active_apc_list = patcmd.next;
2127 }
2128
2129 --RedrawingDisabled;
2130 autocmd_busy = save_autocmd_busy;
2131 filechangeshell_busy = FALSE;
2132 autocmd_nested = save_autocmd_nested;
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002133 vim_free(SOURCING_NAME);
Bram Moolenaare31ee862020-01-07 20:59:34 +01002134 ESTACK_CHECK_NOW
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002135 estack_pop();
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002136 vim_free(autocmd_fname);
2137 autocmd_fname = save_autocmd_fname;
2138 autocmd_fname_full = save_autocmd_fname_full;
2139 autocmd_bufnr = save_autocmd_bufnr;
2140 autocmd_match = save_autocmd_match;
2141#ifdef FEAT_EVAL
2142 current_sctx = save_current_sctx;
2143 restore_funccal();
2144# ifdef FEAT_PROFILE
2145 if (do_profiling == PROF_YES)
2146 prof_child_exit(&wait_time);
2147# endif
2148#endif
2149 KeyTyped = save_KeyTyped;
2150 vim_free(fname);
2151 vim_free(sfname);
2152 --nesting; // see matching increment above
2153
2154 /*
2155 * When stopping to execute autocommands, restore the search patterns and
2156 * the redo buffer. Free any buffers in the au_pending_free_buf list and
2157 * free any windows in the au_pending_free_win list.
2158 */
2159 if (!autocmd_busy)
2160 {
2161 restore_search_patterns();
2162 if (did_save_redobuff)
2163 restoreRedobuff(&save_redo);
2164 did_filetype = FALSE;
2165 while (au_pending_free_buf != NULL)
2166 {
2167 buf_T *b = au_pending_free_buf->b_next;
2168 vim_free(au_pending_free_buf);
2169 au_pending_free_buf = b;
2170 }
2171 while (au_pending_free_win != NULL)
2172 {
2173 win_T *w = au_pending_free_win->w_next;
2174 vim_free(au_pending_free_win);
2175 au_pending_free_win = w;
2176 }
2177 }
2178
2179 /*
2180 * Some events don't set or reset the Changed flag.
2181 * Check if still in the same buffer!
2182 */
2183 if (curbuf == old_curbuf
2184 && (event == EVENT_BUFREADPOST
2185 || event == EVENT_BUFWRITEPOST
2186 || event == EVENT_FILEAPPENDPOST
2187 || event == EVENT_VIMLEAVE
2188 || event == EVENT_VIMLEAVEPRE))
2189 {
2190#ifdef FEAT_TITLE
2191 if (curbuf->b_changed != save_changed)
2192 need_maketitle = TRUE;
2193#endif
2194 curbuf->b_changed = save_changed;
2195 }
2196
2197 au_cleanup(); // may really delete removed patterns/commands now
2198
2199BYPASS_AU:
2200 // When wiping out a buffer make sure all its buffer-local autocommands
2201 // are deleted.
2202 if (event == EVENT_BUFWIPEOUT && buf != NULL)
2203 aubuflocal_remove(buf);
2204
2205 if (retval == OK && event == EVENT_FILETYPE)
2206 au_did_filetype = TRUE;
2207
2208 return retval;
2209}
2210
2211# ifdef FEAT_EVAL
2212static char_u *old_termresponse = NULL;
2213# endif
2214
2215/*
2216 * Block triggering autocommands until unblock_autocmd() is called.
2217 * Can be used recursively, so long as it's symmetric.
2218 */
2219 void
2220block_autocmds(void)
2221{
2222# ifdef FEAT_EVAL
2223 // Remember the value of v:termresponse.
2224 if (autocmd_blocked == 0)
2225 old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
2226# endif
2227 ++autocmd_blocked;
2228}
2229
2230 void
2231unblock_autocmds(void)
2232{
2233 --autocmd_blocked;
2234
2235# ifdef FEAT_EVAL
2236 // When v:termresponse was set while autocommands were blocked, trigger
2237 // the autocommands now. Esp. useful when executing a shell command
2238 // during startup (vimdiff).
2239 if (autocmd_blocked == 0
2240 && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
2241 apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
2242# endif
2243}
2244
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002245 int
2246is_autocmd_blocked(void)
2247{
2248 return autocmd_blocked != 0;
2249}
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002250
2251/*
2252 * Find next autocommand pattern that matches.
2253 */
2254 static void
2255auto_next_pat(
2256 AutoPatCmd *apc,
2257 int stop_at_last) // stop when 'last' flag is set
2258{
2259 AutoPat *ap;
2260 AutoCmd *cp;
2261 char_u *name;
2262 char *s;
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002263 char_u **sourcing_namep = &SOURCING_NAME;
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002264
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002265 VIM_CLEAR(*sourcing_namep);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002266
2267 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
2268 {
2269 apc->curpat = NULL;
2270
2271 // Only use a pattern when it has not been removed, has commands and
2272 // the group matches. For buffer-local autocommands only check the
2273 // buffer number.
2274 if (ap->pat != NULL && ap->cmds != NULL
2275 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
2276 {
2277 // execution-condition
2278 if (ap->buflocal_nr == 0
2279 ? (match_file_pat(NULL, &ap->reg_prog, apc->fname,
2280 apc->sfname, apc->tail, ap->allow_dirs))
2281 : ap->buflocal_nr == apc->arg_bufnr)
2282 {
2283 name = event_nr2name(apc->event);
2284 s = _("%s Autocommands for \"%s\"");
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002285 *sourcing_namep = alloc(STRLEN(s)
Bram Moolenaar964b3742019-05-24 18:54:09 +02002286 + STRLEN(name) + ap->patlen + 1);
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002287 if (*sourcing_namep != NULL)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002288 {
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002289 sprintf((char *)*sourcing_namep, s,
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002290 (char *)name, (char *)ap->pat);
2291 if (p_verbose >= 8)
2292 {
2293 verbose_enter();
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002294 smsg(_("Executing %s"), *sourcing_namep);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002295 verbose_leave();
2296 }
2297 }
2298
2299 apc->curpat = ap;
2300 apc->nextcmd = ap->cmds;
2301 // mark last command
2302 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
2303 cp->last = FALSE;
2304 cp->last = TRUE;
2305 }
2306 line_breakcheck();
2307 if (apc->curpat != NULL) // found a match
2308 break;
2309 }
2310 if (stop_at_last && ap->last)
2311 break;
2312 }
2313}
2314
2315/*
2316 * Get next autocommand command.
2317 * Called by do_cmdline() to get the next line for ":if".
2318 * Returns allocated string, or NULL for end of autocommands.
2319 */
2320 char_u *
Bram Moolenaare96a2492019-06-25 04:12:16 +02002321getnextac(int c UNUSED, void *cookie, int indent UNUSED, int do_concat UNUSED)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002322{
2323 AutoPatCmd *acp = (AutoPatCmd *)cookie;
2324 char_u *retval;
2325 AutoCmd *ac;
2326
2327 // Can be called again after returning the last line.
2328 if (acp->curpat == NULL)
2329 return NULL;
2330
2331 // repeat until we find an autocommand to execute
2332 for (;;)
2333 {
2334 // skip removed commands
2335 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
2336 if (acp->nextcmd->last)
2337 acp->nextcmd = NULL;
2338 else
2339 acp->nextcmd = acp->nextcmd->next;
2340
2341 if (acp->nextcmd != NULL)
2342 break;
2343
2344 // at end of commands, find next pattern that matches
2345 if (acp->curpat->last)
2346 acp->curpat = NULL;
2347 else
2348 acp->curpat = acp->curpat->next;
2349 if (acp->curpat != NULL)
2350 auto_next_pat(acp, TRUE);
2351 if (acp->curpat == NULL)
2352 return NULL;
2353 }
2354
2355 ac = acp->nextcmd;
2356
2357 if (p_verbose >= 9)
2358 {
2359 verbose_enter_scroll();
2360 smsg(_("autocommand %s"), ac->cmd);
2361 msg_puts("\n"); // don't overwrite this either
2362 verbose_leave_scroll();
2363 }
2364 retval = vim_strsave(ac->cmd);
Bram Moolenaareb93f3f2019-04-04 15:04:56 +02002365 // Remove one-shot ("once") autocmd in anticipation of its execution.
2366 if (ac->once)
2367 au_del_cmd(ac);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002368 autocmd_nested = ac->nested;
2369#ifdef FEAT_EVAL
2370 current_sctx = ac->script_ctx;
2371#endif
2372 if (ac->last)
2373 acp->nextcmd = NULL;
2374 else
2375 acp->nextcmd = ac->next;
2376 return retval;
2377}
2378
2379/*
2380 * Return TRUE if there is a matching autocommand for "fname".
2381 * To account for buffer-local autocommands, function needs to know
2382 * in which buffer the file will be opened.
2383 */
2384 int
2385has_autocmd(event_T event, char_u *sfname, buf_T *buf)
2386{
2387 AutoPat *ap;
2388 char_u *fname;
2389 char_u *tail = gettail(sfname);
2390 int retval = FALSE;
2391
2392 fname = FullName_save(sfname, FALSE);
2393 if (fname == NULL)
2394 return FALSE;
2395
2396#ifdef BACKSLASH_IN_FILENAME
2397 /*
2398 * Replace all backslashes with forward slashes. This makes the
2399 * autocommand patterns portable between Unix and MS-DOS.
2400 */
2401 sfname = vim_strsave(sfname);
2402 if (sfname != NULL)
2403 forward_slash(sfname);
2404 forward_slash(fname);
2405#endif
2406
Bram Moolenaaraeea7212020-04-02 18:50:46 +02002407 FOR_ALL_AUTOCMD_PATTERNS(event, ap)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002408 if (ap->pat != NULL && ap->cmds != NULL
2409 && (ap->buflocal_nr == 0
2410 ? match_file_pat(NULL, &ap->reg_prog,
2411 fname, sfname, tail, ap->allow_dirs)
2412 : buf != NULL && ap->buflocal_nr == buf->b_fnum
2413 ))
2414 {
2415 retval = TRUE;
2416 break;
2417 }
2418
2419 vim_free(fname);
2420#ifdef BACKSLASH_IN_FILENAME
2421 vim_free(sfname);
2422#endif
2423
2424 return retval;
2425}
2426
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002427/*
2428 * Function given to ExpandGeneric() to obtain the list of autocommand group
2429 * names.
2430 */
2431 char_u *
2432get_augroup_name(expand_T *xp UNUSED, int idx)
2433{
2434 if (idx == augroups.ga_len) // add "END" add the end
2435 return (char_u *)"END";
2436 if (idx >= augroups.ga_len) // end of list
2437 return NULL;
2438 if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup())
2439 // skip deleted entries
2440 return (char_u *)"";
2441 return AUGROUP_NAME(idx); // return a name
2442}
2443
2444static int include_groups = FALSE;
2445
2446 char_u *
2447set_context_in_autocmd(
2448 expand_T *xp,
2449 char_u *arg,
2450 int doautocmd) // TRUE for :doauto*, FALSE for :autocmd
2451{
2452 char_u *p;
2453 int group;
2454
2455 // check for a group name, skip it if present
2456 include_groups = FALSE;
2457 p = arg;
2458 group = au_get_grouparg(&arg);
2459 if (group == AUGROUP_ERROR)
2460 return NULL;
2461 // If there only is a group name that's what we expand.
2462 if (*arg == NUL && group != AUGROUP_ALL && !VIM_ISWHITE(arg[-1]))
2463 {
2464 arg = p;
2465 group = AUGROUP_ALL;
2466 }
2467
2468 // skip over event name
2469 for (p = arg; *p != NUL && !VIM_ISWHITE(*p); ++p)
2470 if (*p == ',')
2471 arg = p + 1;
2472 if (*p == NUL)
2473 {
2474 if (group == AUGROUP_ALL)
2475 include_groups = TRUE;
2476 xp->xp_context = EXPAND_EVENTS; // expand event name
2477 xp->xp_pattern = arg;
2478 return NULL;
2479 }
2480
2481 // skip over pattern
2482 arg = skipwhite(p);
2483 while (*arg && (!VIM_ISWHITE(*arg) || arg[-1] == '\\'))
2484 arg++;
2485 if (*arg)
2486 return arg; // expand (next) command
2487
2488 if (doautocmd)
2489 xp->xp_context = EXPAND_FILES; // expand file names
2490 else
2491 xp->xp_context = EXPAND_NOTHING; // pattern is not expanded
2492 return NULL;
2493}
2494
2495/*
2496 * Function given to ExpandGeneric() to obtain the list of event names.
2497 */
2498 char_u *
2499get_event_name(expand_T *xp UNUSED, int idx)
2500{
2501 if (idx < augroups.ga_len) // First list group names, if wanted
2502 {
2503 if (!include_groups || AUGROUP_NAME(idx) == NULL
2504 || AUGROUP_NAME(idx) == get_deleted_augroup())
2505 return (char_u *)""; // skip deleted entries
2506 return AUGROUP_NAME(idx); // return a name
2507 }
2508 return (char_u *)event_names[idx - augroups.ga_len].name;
2509}
2510
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002511
2512#if defined(FEAT_EVAL) || defined(PROTO)
2513/*
2514 * Return TRUE if autocmd is supported.
2515 */
2516 int
2517autocmd_supported(char_u *name)
2518{
2519 char_u *p;
2520
2521 return (event_name2nr(name, &p) != NUM_EVENTS);
2522}
2523
2524/*
2525 * Return TRUE if an autocommand is defined for a group, event and
2526 * pattern: The group can be omitted to accept any group. "event" and "pattern"
2527 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
2528 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
2529 * Used for:
2530 * exists("#Group") or
2531 * exists("#Group#Event") or
2532 * exists("#Group#Event#pat") or
2533 * exists("#Event") or
2534 * exists("#Event#pat")
2535 */
2536 int
2537au_exists(char_u *arg)
2538{
2539 char_u *arg_save;
2540 char_u *pattern = NULL;
2541 char_u *event_name;
2542 char_u *p;
2543 event_T event;
2544 AutoPat *ap;
2545 buf_T *buflocal_buf = NULL;
2546 int group;
2547 int retval = FALSE;
2548
2549 // Make a copy so that we can change the '#' chars to a NUL.
2550 arg_save = vim_strsave(arg);
2551 if (arg_save == NULL)
2552 return FALSE;
2553 p = vim_strchr(arg_save, '#');
2554 if (p != NULL)
2555 *p++ = NUL;
2556
2557 // First, look for an autocmd group name
2558 group = au_find_group(arg_save);
2559 if (group == AUGROUP_ERROR)
2560 {
2561 // Didn't match a group name, assume the first argument is an event.
2562 group = AUGROUP_ALL;
2563 event_name = arg_save;
2564 }
2565 else
2566 {
2567 if (p == NULL)
2568 {
2569 // "Group": group name is present and it's recognized
2570 retval = TRUE;
2571 goto theend;
2572 }
2573
2574 // Must be "Group#Event" or "Group#Event#pat".
2575 event_name = p;
2576 p = vim_strchr(event_name, '#');
2577 if (p != NULL)
2578 *p++ = NUL; // "Group#Event#pat"
2579 }
2580
2581 pattern = p; // "pattern" is NULL when there is no pattern
2582
2583 // find the index (enum) for the event name
2584 event = event_name2nr(event_name, &p);
2585
2586 // return FALSE if the event name is not recognized
2587 if (event == NUM_EVENTS)
2588 goto theend;
2589
2590 // Find the first autocommand for this event.
2591 // If there isn't any, return FALSE;
2592 // If there is one and no pattern given, return TRUE;
2593 ap = first_autopat[(int)event];
2594 if (ap == NULL)
2595 goto theend;
2596
2597 // if pattern is "<buffer>", special handling is needed which uses curbuf
2598 // for pattern "<buffer=N>, fnamecmp() will work fine
2599 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0)
2600 buflocal_buf = curbuf;
2601
2602 // Check if there is an autocommand with the given pattern.
2603 for ( ; ap != NULL; ap = ap->next)
2604 // only use a pattern when it has not been removed and has commands.
2605 // For buffer-local autocommands, fnamecmp() works fine.
2606 if (ap->pat != NULL && ap->cmds != NULL
2607 && (group == AUGROUP_ALL || ap->group == group)
2608 && (pattern == NULL
2609 || (buflocal_buf == NULL
2610 ? fnamecmp(ap->pat, pattern) == 0
2611 : ap->buflocal_nr == buflocal_buf->b_fnum)))
2612 {
2613 retval = TRUE;
2614 break;
2615 }
2616
2617theend:
2618 vim_free(arg_save);
2619 return retval;
2620}
2621#endif