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