blob: 983a155c60fd9111ebbfd0443534d4af428758ee [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;
1830
1831 /*
1832 * Quickly return if there are no autocommands for this event or
1833 * autocommands are blocked.
1834 */
1835 if (event == NUM_EVENTS || first_autopat[(int)event] == NULL
1836 || autocmd_blocked > 0)
1837 goto BYPASS_AU;
1838
1839 /*
1840 * When autocommands are busy, new autocommands are only executed when
1841 * explicitly enabled with the "nested" flag.
1842 */
1843 if (autocmd_busy && !(force || autocmd_nested))
1844 goto BYPASS_AU;
1845
1846#ifdef FEAT_EVAL
1847 /*
1848 * Quickly return when immediately aborting on error, or when an interrupt
1849 * occurred or an exception was thrown but not caught.
1850 */
1851 if (aborting())
1852 goto BYPASS_AU;
1853#endif
1854
1855 /*
1856 * FileChangedShell never nests, because it can create an endless loop.
1857 */
1858 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
1859 || event == EVENT_FILECHANGEDSHELLPOST))
1860 goto BYPASS_AU;
1861
1862 /*
1863 * Ignore events in 'eventignore'.
1864 */
1865 if (event_ignored(event))
1866 goto BYPASS_AU;
1867
1868 /*
1869 * Allow nesting of autocommands, but restrict the depth, because it's
1870 * possible to create an endless loop.
1871 */
1872 if (nesting == 10)
1873 {
1874 emsg(_("E218: autocommand nesting too deep"));
1875 goto BYPASS_AU;
1876 }
1877
1878 /*
1879 * Check if these autocommands are disabled. Used when doing ":all" or
1880 * ":ball".
1881 */
1882 if ( (autocmd_no_enter
1883 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
1884 || (autocmd_no_leave
1885 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
1886 goto BYPASS_AU;
1887
1888 /*
1889 * Save the autocmd_* variables and info about the current buffer.
1890 */
1891 save_autocmd_fname = autocmd_fname;
1892 save_autocmd_fname_full = autocmd_fname_full;
1893 save_autocmd_bufnr = autocmd_bufnr;
1894 save_autocmd_match = autocmd_match;
1895 save_autocmd_busy = autocmd_busy;
1896 save_autocmd_nested = autocmd_nested;
1897 save_changed = curbuf->b_changed;
1898 old_curbuf = curbuf;
1899
1900 /*
1901 * Set the file name to be used for <afile>.
1902 * Make a copy to avoid that changing a buffer name or directory makes it
1903 * invalid.
1904 */
1905 if (fname_io == NULL)
1906 {
1907 if (event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE
1908 || event == EVENT_OPTIONSET)
1909 autocmd_fname = NULL;
1910 else if (fname != NULL && !ends_excmd(*fname))
1911 autocmd_fname = fname;
1912 else if (buf != NULL)
1913 autocmd_fname = buf->b_ffname;
1914 else
1915 autocmd_fname = NULL;
1916 }
1917 else
1918 autocmd_fname = fname_io;
1919 if (autocmd_fname != NULL)
1920 autocmd_fname = vim_strsave(autocmd_fname);
1921 autocmd_fname_full = FALSE; // call FullName_save() later
1922
1923 /*
1924 * Set the buffer number to be used for <abuf>.
1925 */
1926 if (buf == NULL)
1927 autocmd_bufnr = 0;
1928 else
1929 autocmd_bufnr = buf->b_fnum;
1930
1931 /*
1932 * When the file name is NULL or empty, use the file name of buffer "buf".
1933 * Always use the full path of the file name to match with, in case
1934 * "allow_dirs" is set.
1935 */
1936 if (fname == NULL || *fname == NUL)
1937 {
1938 if (buf == NULL)
1939 fname = NULL;
1940 else
1941 {
1942#ifdef FEAT_SYN_HL
1943 if (event == EVENT_SYNTAX)
1944 fname = buf->b_p_syn;
1945 else
1946#endif
1947 if (event == EVENT_FILETYPE)
1948 fname = buf->b_p_ft;
1949 else
1950 {
1951 if (buf->b_sfname != NULL)
1952 sfname = vim_strsave(buf->b_sfname);
1953 fname = buf->b_ffname;
1954 }
1955 }
1956 if (fname == NULL)
1957 fname = (char_u *)"";
1958 fname = vim_strsave(fname); // make a copy, so we can change it
1959 }
1960 else
1961 {
1962 sfname = vim_strsave(fname);
1963 // Don't try expanding FileType, Syntax, FuncUndefined, WindowID,
1964 // ColorScheme, QuickFixCmd* or DirChanged
1965 if (event == EVENT_FILETYPE
1966 || event == EVENT_SYNTAX
1967 || event == EVENT_CMDLINECHANGED
1968 || event == EVENT_CMDLINEENTER
1969 || event == EVENT_CMDLINELEAVE
1970 || event == EVENT_CMDWINENTER
1971 || event == EVENT_CMDWINLEAVE
1972 || event == EVENT_CMDUNDEFINED
1973 || event == EVENT_FUNCUNDEFINED
1974 || event == EVENT_REMOTEREPLY
1975 || event == EVENT_SPELLFILEMISSING
1976 || event == EVENT_QUICKFIXCMDPRE
1977 || event == EVENT_COLORSCHEME
1978 || event == EVENT_COLORSCHEMEPRE
1979 || event == EVENT_OPTIONSET
1980 || event == EVENT_QUICKFIXCMDPOST
1981 || event == EVENT_DIRCHANGED)
1982 {
1983 fname = vim_strsave(fname);
1984 autocmd_fname_full = TRUE; // don't expand it later
1985 }
1986 else
1987 fname = FullName_save(fname, FALSE);
1988 }
1989 if (fname == NULL) // out of memory
1990 {
1991 vim_free(sfname);
1992 retval = FALSE;
1993 goto BYPASS_AU;
1994 }
1995
1996#ifdef BACKSLASH_IN_FILENAME
1997 /*
1998 * Replace all backslashes with forward slashes. This makes the
1999 * autocommand patterns portable between Unix and MS-DOS.
2000 */
2001 if (sfname != NULL)
2002 forward_slash(sfname);
2003 forward_slash(fname);
2004#endif
2005
2006#ifdef VMS
2007 // remove version for correct match
2008 if (sfname != NULL)
2009 vms_remove_version(sfname);
2010 vms_remove_version(fname);
2011#endif
2012
2013 /*
2014 * Set the name to be used for <amatch>.
2015 */
2016 autocmd_match = fname;
2017
2018
2019 // Don't redraw while doing autocommands.
2020 ++RedrawingDisabled;
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002021
2022 // name and lnum are filled in later
2023 estack_push(ETYPE_AUCMD, NULL, 0);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002024
2025#ifdef FEAT_EVAL
2026 save_current_sctx = current_sctx;
2027
2028# ifdef FEAT_PROFILE
2029 if (do_profiling == PROF_YES)
2030 prof_child_enter(&wait_time); // doesn't count for the caller itself
2031# endif
2032
2033 // Don't use local function variables, if called from a function.
2034 save_funccal(&funccal_entry);
2035#endif
2036
2037 /*
2038 * When starting to execute autocommands, save the search patterns.
2039 */
2040 if (!autocmd_busy)
2041 {
2042 save_search_patterns();
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002043 if (!ins_compl_active())
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002044 {
2045 saveRedobuff(&save_redo);
2046 did_save_redobuff = TRUE;
2047 }
2048 did_filetype = keep_filetype;
2049 }
2050
2051 /*
2052 * Note that we are applying autocmds. Some commands need to know.
2053 */
2054 autocmd_busy = TRUE;
2055 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
2056 ++nesting; // see matching decrement below
2057
2058 // Remember that FileType was triggered. Used for did_filetype().
2059 if (event == EVENT_FILETYPE)
2060 did_filetype = TRUE;
2061
2062 tail = gettail(fname);
2063
2064 // Find first autocommand that matches
2065 patcmd.curpat = first_autopat[(int)event];
2066 patcmd.nextcmd = NULL;
2067 patcmd.group = group;
2068 patcmd.fname = fname;
2069 patcmd.sfname = sfname;
2070 patcmd.tail = tail;
2071 patcmd.event = event;
2072 patcmd.arg_bufnr = autocmd_bufnr;
2073 patcmd.next = NULL;
2074 auto_next_pat(&patcmd, FALSE);
2075
2076 // found one, start executing the autocommands
2077 if (patcmd.curpat != NULL)
2078 {
2079 // add to active_apc_list
2080 patcmd.next = active_apc_list;
2081 active_apc_list = &patcmd;
2082
2083#ifdef FEAT_EVAL
2084 // set v:cmdarg (only when there is a matching pattern)
2085 save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG);
2086 if (eap != NULL)
2087 {
2088 save_cmdarg = set_cmdarg(eap, NULL);
2089 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
2090 }
2091 else
2092 save_cmdarg = NULL; // avoid gcc warning
2093#endif
2094 retval = TRUE;
2095 // mark the last pattern, to avoid an endless loop when more patterns
2096 // are added when executing autocommands
2097 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
2098 ap->last = FALSE;
2099 ap->last = TRUE;
Bram Moolenaara68e5952019-04-25 22:22:01 +02002100
2101 // make sure cursor and topline are valid
2102 check_lnums(TRUE);
2103
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002104 do_cmdline(NULL, getnextac, (void *)&patcmd,
2105 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
Bram Moolenaara68e5952019-04-25 22:22:01 +02002106
2107 // restore cursor and topline, unless they were changed
2108 reset_lnums();
2109
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002110#ifdef FEAT_EVAL
2111 if (eap != NULL)
2112 {
2113 (void)set_cmdarg(NULL, save_cmdarg);
2114 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
2115 }
2116#endif
2117 // delete from active_apc_list
2118 if (active_apc_list == &patcmd) // just in case
2119 active_apc_list = patcmd.next;
2120 }
2121
2122 --RedrawingDisabled;
2123 autocmd_busy = save_autocmd_busy;
2124 filechangeshell_busy = FALSE;
2125 autocmd_nested = save_autocmd_nested;
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002126 vim_free(SOURCING_NAME);
2127 estack_pop();
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002128 vim_free(autocmd_fname);
2129 autocmd_fname = save_autocmd_fname;
2130 autocmd_fname_full = save_autocmd_fname_full;
2131 autocmd_bufnr = save_autocmd_bufnr;
2132 autocmd_match = save_autocmd_match;
2133#ifdef FEAT_EVAL
2134 current_sctx = save_current_sctx;
2135 restore_funccal();
2136# ifdef FEAT_PROFILE
2137 if (do_profiling == PROF_YES)
2138 prof_child_exit(&wait_time);
2139# endif
2140#endif
2141 KeyTyped = save_KeyTyped;
2142 vim_free(fname);
2143 vim_free(sfname);
2144 --nesting; // see matching increment above
2145
2146 /*
2147 * When stopping to execute autocommands, restore the search patterns and
2148 * the redo buffer. Free any buffers in the au_pending_free_buf list and
2149 * free any windows in the au_pending_free_win list.
2150 */
2151 if (!autocmd_busy)
2152 {
2153 restore_search_patterns();
2154 if (did_save_redobuff)
2155 restoreRedobuff(&save_redo);
2156 did_filetype = FALSE;
2157 while (au_pending_free_buf != NULL)
2158 {
2159 buf_T *b = au_pending_free_buf->b_next;
2160 vim_free(au_pending_free_buf);
2161 au_pending_free_buf = b;
2162 }
2163 while (au_pending_free_win != NULL)
2164 {
2165 win_T *w = au_pending_free_win->w_next;
2166 vim_free(au_pending_free_win);
2167 au_pending_free_win = w;
2168 }
2169 }
2170
2171 /*
2172 * Some events don't set or reset the Changed flag.
2173 * Check if still in the same buffer!
2174 */
2175 if (curbuf == old_curbuf
2176 && (event == EVENT_BUFREADPOST
2177 || event == EVENT_BUFWRITEPOST
2178 || event == EVENT_FILEAPPENDPOST
2179 || event == EVENT_VIMLEAVE
2180 || event == EVENT_VIMLEAVEPRE))
2181 {
2182#ifdef FEAT_TITLE
2183 if (curbuf->b_changed != save_changed)
2184 need_maketitle = TRUE;
2185#endif
2186 curbuf->b_changed = save_changed;
2187 }
2188
2189 au_cleanup(); // may really delete removed patterns/commands now
2190
2191BYPASS_AU:
2192 // When wiping out a buffer make sure all its buffer-local autocommands
2193 // are deleted.
2194 if (event == EVENT_BUFWIPEOUT && buf != NULL)
2195 aubuflocal_remove(buf);
2196
2197 if (retval == OK && event == EVENT_FILETYPE)
2198 au_did_filetype = TRUE;
2199
2200 return retval;
2201}
2202
2203# ifdef FEAT_EVAL
2204static char_u *old_termresponse = NULL;
2205# endif
2206
2207/*
2208 * Block triggering autocommands until unblock_autocmd() is called.
2209 * Can be used recursively, so long as it's symmetric.
2210 */
2211 void
2212block_autocmds(void)
2213{
2214# ifdef FEAT_EVAL
2215 // Remember the value of v:termresponse.
2216 if (autocmd_blocked == 0)
2217 old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
2218# endif
2219 ++autocmd_blocked;
2220}
2221
2222 void
2223unblock_autocmds(void)
2224{
2225 --autocmd_blocked;
2226
2227# ifdef FEAT_EVAL
2228 // When v:termresponse was set while autocommands were blocked, trigger
2229 // the autocommands now. Esp. useful when executing a shell command
2230 // during startup (vimdiff).
2231 if (autocmd_blocked == 0
2232 && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
2233 apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
2234# endif
2235}
2236
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002237 int
2238is_autocmd_blocked(void)
2239{
2240 return autocmd_blocked != 0;
2241}
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002242
2243/*
2244 * Find next autocommand pattern that matches.
2245 */
2246 static void
2247auto_next_pat(
2248 AutoPatCmd *apc,
2249 int stop_at_last) // stop when 'last' flag is set
2250{
2251 AutoPat *ap;
2252 AutoCmd *cp;
2253 char_u *name;
2254 char *s;
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002255 char_u **sourcing_namep = &SOURCING_NAME;
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002256
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002257 VIM_CLEAR(*sourcing_namep);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002258
2259 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
2260 {
2261 apc->curpat = NULL;
2262
2263 // Only use a pattern when it has not been removed, has commands and
2264 // the group matches. For buffer-local autocommands only check the
2265 // buffer number.
2266 if (ap->pat != NULL && ap->cmds != NULL
2267 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
2268 {
2269 // execution-condition
2270 if (ap->buflocal_nr == 0
2271 ? (match_file_pat(NULL, &ap->reg_prog, apc->fname,
2272 apc->sfname, apc->tail, ap->allow_dirs))
2273 : ap->buflocal_nr == apc->arg_bufnr)
2274 {
2275 name = event_nr2name(apc->event);
2276 s = _("%s Autocommands for \"%s\"");
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002277 *sourcing_namep = alloc(STRLEN(s)
Bram Moolenaar964b3742019-05-24 18:54:09 +02002278 + STRLEN(name) + ap->patlen + 1);
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002279 if (*sourcing_namep != NULL)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002280 {
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002281 sprintf((char *)*sourcing_namep, s,
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002282 (char *)name, (char *)ap->pat);
2283 if (p_verbose >= 8)
2284 {
2285 verbose_enter();
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01002286 smsg(_("Executing %s"), *sourcing_namep);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002287 verbose_leave();
2288 }
2289 }
2290
2291 apc->curpat = ap;
2292 apc->nextcmd = ap->cmds;
2293 // mark last command
2294 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
2295 cp->last = FALSE;
2296 cp->last = TRUE;
2297 }
2298 line_breakcheck();
2299 if (apc->curpat != NULL) // found a match
2300 break;
2301 }
2302 if (stop_at_last && ap->last)
2303 break;
2304 }
2305}
2306
2307/*
2308 * Get next autocommand command.
2309 * Called by do_cmdline() to get the next line for ":if".
2310 * Returns allocated string, or NULL for end of autocommands.
2311 */
2312 char_u *
Bram Moolenaare96a2492019-06-25 04:12:16 +02002313getnextac(int c UNUSED, void *cookie, int indent UNUSED, int do_concat UNUSED)
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002314{
2315 AutoPatCmd *acp = (AutoPatCmd *)cookie;
2316 char_u *retval;
2317 AutoCmd *ac;
2318
2319 // Can be called again after returning the last line.
2320 if (acp->curpat == NULL)
2321 return NULL;
2322
2323 // repeat until we find an autocommand to execute
2324 for (;;)
2325 {
2326 // skip removed commands
2327 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
2328 if (acp->nextcmd->last)
2329 acp->nextcmd = NULL;
2330 else
2331 acp->nextcmd = acp->nextcmd->next;
2332
2333 if (acp->nextcmd != NULL)
2334 break;
2335
2336 // at end of commands, find next pattern that matches
2337 if (acp->curpat->last)
2338 acp->curpat = NULL;
2339 else
2340 acp->curpat = acp->curpat->next;
2341 if (acp->curpat != NULL)
2342 auto_next_pat(acp, TRUE);
2343 if (acp->curpat == NULL)
2344 return NULL;
2345 }
2346
2347 ac = acp->nextcmd;
2348
2349 if (p_verbose >= 9)
2350 {
2351 verbose_enter_scroll();
2352 smsg(_("autocommand %s"), ac->cmd);
2353 msg_puts("\n"); // don't overwrite this either
2354 verbose_leave_scroll();
2355 }
2356 retval = vim_strsave(ac->cmd);
Bram Moolenaareb93f3f2019-04-04 15:04:56 +02002357 // Remove one-shot ("once") autocmd in anticipation of its execution.
2358 if (ac->once)
2359 au_del_cmd(ac);
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002360 autocmd_nested = ac->nested;
2361#ifdef FEAT_EVAL
2362 current_sctx = ac->script_ctx;
2363#endif
2364 if (ac->last)
2365 acp->nextcmd = NULL;
2366 else
2367 acp->nextcmd = ac->next;
2368 return retval;
2369}
2370
2371/*
2372 * Return TRUE if there is a matching autocommand for "fname".
2373 * To account for buffer-local autocommands, function needs to know
2374 * in which buffer the file will be opened.
2375 */
2376 int
2377has_autocmd(event_T event, char_u *sfname, buf_T *buf)
2378{
2379 AutoPat *ap;
2380 char_u *fname;
2381 char_u *tail = gettail(sfname);
2382 int retval = FALSE;
2383
2384 fname = FullName_save(sfname, FALSE);
2385 if (fname == NULL)
2386 return FALSE;
2387
2388#ifdef BACKSLASH_IN_FILENAME
2389 /*
2390 * Replace all backslashes with forward slashes. This makes the
2391 * autocommand patterns portable between Unix and MS-DOS.
2392 */
2393 sfname = vim_strsave(sfname);
2394 if (sfname != NULL)
2395 forward_slash(sfname);
2396 forward_slash(fname);
2397#endif
2398
2399 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
2400 if (ap->pat != NULL && ap->cmds != NULL
2401 && (ap->buflocal_nr == 0
2402 ? match_file_pat(NULL, &ap->reg_prog,
2403 fname, sfname, tail, ap->allow_dirs)
2404 : buf != NULL && ap->buflocal_nr == buf->b_fnum
2405 ))
2406 {
2407 retval = TRUE;
2408 break;
2409 }
2410
2411 vim_free(fname);
2412#ifdef BACKSLASH_IN_FILENAME
2413 vim_free(sfname);
2414#endif
2415
2416 return retval;
2417}
2418
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002419/*
2420 * Function given to ExpandGeneric() to obtain the list of autocommand group
2421 * names.
2422 */
2423 char_u *
2424get_augroup_name(expand_T *xp UNUSED, int idx)
2425{
2426 if (idx == augroups.ga_len) // add "END" add the end
2427 return (char_u *)"END";
2428 if (idx >= augroups.ga_len) // end of list
2429 return NULL;
2430 if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup())
2431 // skip deleted entries
2432 return (char_u *)"";
2433 return AUGROUP_NAME(idx); // return a name
2434}
2435
2436static int include_groups = FALSE;
2437
2438 char_u *
2439set_context_in_autocmd(
2440 expand_T *xp,
2441 char_u *arg,
2442 int doautocmd) // TRUE for :doauto*, FALSE for :autocmd
2443{
2444 char_u *p;
2445 int group;
2446
2447 // check for a group name, skip it if present
2448 include_groups = FALSE;
2449 p = arg;
2450 group = au_get_grouparg(&arg);
2451 if (group == AUGROUP_ERROR)
2452 return NULL;
2453 // If there only is a group name that's what we expand.
2454 if (*arg == NUL && group != AUGROUP_ALL && !VIM_ISWHITE(arg[-1]))
2455 {
2456 arg = p;
2457 group = AUGROUP_ALL;
2458 }
2459
2460 // skip over event name
2461 for (p = arg; *p != NUL && !VIM_ISWHITE(*p); ++p)
2462 if (*p == ',')
2463 arg = p + 1;
2464 if (*p == NUL)
2465 {
2466 if (group == AUGROUP_ALL)
2467 include_groups = TRUE;
2468 xp->xp_context = EXPAND_EVENTS; // expand event name
2469 xp->xp_pattern = arg;
2470 return NULL;
2471 }
2472
2473 // skip over pattern
2474 arg = skipwhite(p);
2475 while (*arg && (!VIM_ISWHITE(*arg) || arg[-1] == '\\'))
2476 arg++;
2477 if (*arg)
2478 return arg; // expand (next) command
2479
2480 if (doautocmd)
2481 xp->xp_context = EXPAND_FILES; // expand file names
2482 else
2483 xp->xp_context = EXPAND_NOTHING; // pattern is not expanded
2484 return NULL;
2485}
2486
2487/*
2488 * Function given to ExpandGeneric() to obtain the list of event names.
2489 */
2490 char_u *
2491get_event_name(expand_T *xp UNUSED, int idx)
2492{
2493 if (idx < augroups.ga_len) // First list group names, if wanted
2494 {
2495 if (!include_groups || AUGROUP_NAME(idx) == NULL
2496 || AUGROUP_NAME(idx) == get_deleted_augroup())
2497 return (char_u *)""; // skip deleted entries
2498 return AUGROUP_NAME(idx); // return a name
2499 }
2500 return (char_u *)event_names[idx - augroups.ga_len].name;
2501}
2502
Bram Moolenaar3e460fd2019-01-26 16:21:07 +01002503
2504#if defined(FEAT_EVAL) || defined(PROTO)
2505/*
2506 * Return TRUE if autocmd is supported.
2507 */
2508 int
2509autocmd_supported(char_u *name)
2510{
2511 char_u *p;
2512
2513 return (event_name2nr(name, &p) != NUM_EVENTS);
2514}
2515
2516/*
2517 * Return TRUE if an autocommand is defined for a group, event and
2518 * pattern: The group can be omitted to accept any group. "event" and "pattern"
2519 * can be NULL to accept any event and pattern. "pattern" can be NULL to accept
2520 * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted.
2521 * Used for:
2522 * exists("#Group") or
2523 * exists("#Group#Event") or
2524 * exists("#Group#Event#pat") or
2525 * exists("#Event") or
2526 * exists("#Event#pat")
2527 */
2528 int
2529au_exists(char_u *arg)
2530{
2531 char_u *arg_save;
2532 char_u *pattern = NULL;
2533 char_u *event_name;
2534 char_u *p;
2535 event_T event;
2536 AutoPat *ap;
2537 buf_T *buflocal_buf = NULL;
2538 int group;
2539 int retval = FALSE;
2540
2541 // Make a copy so that we can change the '#' chars to a NUL.
2542 arg_save = vim_strsave(arg);
2543 if (arg_save == NULL)
2544 return FALSE;
2545 p = vim_strchr(arg_save, '#');
2546 if (p != NULL)
2547 *p++ = NUL;
2548
2549 // First, look for an autocmd group name
2550 group = au_find_group(arg_save);
2551 if (group == AUGROUP_ERROR)
2552 {
2553 // Didn't match a group name, assume the first argument is an event.
2554 group = AUGROUP_ALL;
2555 event_name = arg_save;
2556 }
2557 else
2558 {
2559 if (p == NULL)
2560 {
2561 // "Group": group name is present and it's recognized
2562 retval = TRUE;
2563 goto theend;
2564 }
2565
2566 // Must be "Group#Event" or "Group#Event#pat".
2567 event_name = p;
2568 p = vim_strchr(event_name, '#');
2569 if (p != NULL)
2570 *p++ = NUL; // "Group#Event#pat"
2571 }
2572
2573 pattern = p; // "pattern" is NULL when there is no pattern
2574
2575 // find the index (enum) for the event name
2576 event = event_name2nr(event_name, &p);
2577
2578 // return FALSE if the event name is not recognized
2579 if (event == NUM_EVENTS)
2580 goto theend;
2581
2582 // Find the first autocommand for this event.
2583 // If there isn't any, return FALSE;
2584 // If there is one and no pattern given, return TRUE;
2585 ap = first_autopat[(int)event];
2586 if (ap == NULL)
2587 goto theend;
2588
2589 // if pattern is "<buffer>", special handling is needed which uses curbuf
2590 // for pattern "<buffer=N>, fnamecmp() will work fine
2591 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0)
2592 buflocal_buf = curbuf;
2593
2594 // Check if there is an autocommand with the given pattern.
2595 for ( ; ap != NULL; ap = ap->next)
2596 // only use a pattern when it has not been removed and has commands.
2597 // For buffer-local autocommands, fnamecmp() works fine.
2598 if (ap->pat != NULL && ap->cmds != NULL
2599 && (group == AUGROUP_ALL || ap->group == group)
2600 && (pattern == NULL
2601 || (buflocal_buf == NULL
2602 ? fnamecmp(ap->pat, pattern) == 0
2603 : ap->buflocal_nr == buflocal_buf->b_fnum)))
2604 {
2605 retval = TRUE;
2606 break;
2607 }
2608
2609theend:
2610 vim_free(arg_save);
2611 return retval;
2612}
2613#endif