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