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