autocmd.c (80875B)
1 // autocmd.c: Autocommand related functions 2 3 #include <assert.h> 4 #include <stddef.h> 5 #include <stdint.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 10 #include "nvim/api/private/converter.h" 11 #include "nvim/autocmd.h" 12 #include "nvim/autocmd_defs.h" 13 #include "nvim/buffer.h" 14 #include "nvim/charset.h" 15 #include "nvim/cmdexpand_defs.h" 16 #include "nvim/cursor.h" 17 #include "nvim/errors.h" 18 #include "nvim/eval.h" 19 #include "nvim/eval/typval.h" 20 #include "nvim/eval/userfunc.h" 21 #include "nvim/eval/vars.h" 22 #include "nvim/event/loop.h" 23 #include "nvim/event/multiqueue.h" 24 #include "nvim/ex_docmd.h" 25 #include "nvim/ex_eval.h" 26 #include "nvim/fileio.h" 27 #include "nvim/getchar.h" 28 #include "nvim/getchar_defs.h" 29 #include "nvim/gettext_defs.h" 30 #include "nvim/globals.h" 31 #include "nvim/grid.h" 32 #include "nvim/grid_defs.h" 33 #include "nvim/hashtab.h" 34 #include "nvim/highlight_defs.h" 35 #include "nvim/insexpand.h" 36 #include "nvim/lua/executor.h" 37 #include "nvim/main.h" 38 #include "nvim/map_defs.h" 39 #include "nvim/memory.h" 40 #include "nvim/message.h" 41 #include "nvim/option.h" 42 #include "nvim/option_defs.h" 43 #include "nvim/option_vars.h" 44 #include "nvim/os/input.h" 45 #include "nvim/os/os.h" 46 #include "nvim/os/os_defs.h" 47 #include "nvim/os/time.h" 48 #include "nvim/os/time_defs.h" 49 #include "nvim/path.h" 50 #include "nvim/profile.h" 51 #include "nvim/regexp.h" 52 #include "nvim/runtime.h" 53 #include "nvim/runtime_defs.h" 54 #include "nvim/search.h" 55 #include "nvim/state.h" 56 #include "nvim/state_defs.h" 57 #include "nvim/strings.h" 58 #include "nvim/types_defs.h" 59 #include "nvim/ui.h" 60 #include "nvim/ui_compositor.h" 61 #include "nvim/vim_defs.h" 62 #include "nvim/window.h" 63 #include "nvim/winfloat.h" 64 65 #include "auevents_name_map.generated.h" 66 #include "autocmd.c.generated.h" 67 68 static const char e_autocommand_nesting_too_deep[] 69 = N_("E218: Autocommand nesting too deep"); 70 71 // Naming Conventions: 72 // - general autocmd behavior start with au_ 73 // - AutoCmd start with aucmd_ 74 // - AutoPat start with aupat_ 75 // - Groups start with augroup_ 76 // - Events start with event_ 77 78 // The autocommands are stored in a contiguous vector for each event. 79 // 80 // The order of AutoCmds is important, this is the order in which they 81 // were defined and will have to be executed. 82 // 83 // To avoid having to match the pattern too often, patterns are reference 84 // counted and reused for consecutive autocommands. 85 86 // Code for automatic commands. 87 static AutoPatCmd *active_apc_list = NULL; // stack of active autocommands 88 89 // ID for associating autocmds created via nvim_create_autocmd 90 // Used to delete autocmds from nvim_del_autocmd 91 static int next_augroup_id = 1; 92 93 // use get_deleted_augroup() to get this 94 static const char *deleted_augroup = NULL; 95 96 // The ID of the current group. 97 static int current_augroup = AUGROUP_DEFAULT; 98 99 // Whether we need to delete marked patterns. 100 // While deleting autocmds, they aren't actually remover, just marked. 101 static bool au_need_clean = false; 102 103 static int autocmd_blocked = 0; // block all autocmds 104 105 static bool autocmd_nested = false; 106 static bool autocmd_include_groups = false; 107 108 static bool termresponse_changed = false; 109 110 // Map of autocmd group names and ids. 111 // name -> ID 112 // ID -> name 113 static Map(String, int) map_augroup_name_to_id = MAP_INIT; 114 static Map(int, String) map_augroup_id_to_name = MAP_INIT; 115 116 void autocmd_init(void) 117 { 118 deferred_events = multiqueue_new_child(main_loop.events); 119 } 120 121 #ifdef EXITFREE 122 void autocmd_free_all_mem(void) 123 { 124 multiqueue_free(deferred_events); 125 } 126 #endif 127 128 static void augroup_map_del(int id, const char *name) 129 { 130 if (name != NULL) { 131 String key; 132 map_del(String, int)(&map_augroup_name_to_id, cstr_as_string(name), &key); 133 api_free_string(key); 134 } 135 if (id > 0) { 136 String mapped = map_del(int, String)(&map_augroup_id_to_name, id, NULL); 137 api_free_string(mapped); 138 } 139 } 140 141 static inline const char *get_deleted_augroup(void) FUNC_ATTR_ALWAYS_INLINE 142 { 143 if (deleted_augroup == NULL) { 144 deleted_augroup = _("--Deleted--"); 145 } 146 return deleted_augroup; 147 } 148 149 static void au_show_for_all_events(int group, const char *pat) 150 { 151 FOR_ALL_AUEVENTS(event) { 152 au_show_for_event(group, event, pat); 153 } 154 } 155 156 static void au_show_for_event(int group, event_T event, const char *pat) 157 FUNC_ATTR_NONNULL_ALL 158 { 159 AutoCmdVec *const acs = &autocmds[(int)event]; 160 // Return early if there are no autocmds for this event 161 if (kv_size(*acs) == 0) { 162 return; 163 } 164 165 // Empty pattern shows all autocommands for this event 166 int patlen = 0; 167 if (*pat != NUL) { 168 patlen = (int)aucmd_span_pattern(pat, &pat); 169 if (patlen == 0) { // Don't show if it contains only commas 170 return; 171 } 172 } 173 174 char buflocal_pat[BUFLOCAL_PAT_LEN]; // for "<buffer=X>" 175 int last_group = AUGROUP_ERROR; 176 const char *last_group_name = NULL; 177 178 // Loop through all the specified patterns. 179 do { 180 AutoPat *last_ap = NULL; 181 const char *endpat = pat + patlen; 182 183 // detect special <buffer[=X]> buffer-local patterns 184 if (aupat_is_buflocal(pat, patlen)) { 185 // normalize pat into standard "<buffer>#N" form 186 aupat_normalize_buflocal_pat(buflocal_pat, pat, patlen, aupat_get_buflocal_nr(pat, patlen)); 187 pat = buflocal_pat; 188 patlen = (int)strlen(buflocal_pat); 189 } 190 191 for (size_t i = 0; i < kv_size(*acs); i++) { 192 AutoCmd *const ac = &kv_A(*acs, i); 193 194 // Skip deleted autocommands. 195 if (ac->pat == NULL) { 196 continue; 197 } 198 199 // Accept a pattern when: 200 // - a group was specified and it's that group 201 // - the length of the pattern matches 202 // - the pattern matches. 203 // For <buffer[=X]>, this condition works because we normalize 204 // all buffer-local patterns. 205 if ((group != AUGROUP_ALL && ac->pat->group != group) 206 || (patlen 207 && (ac->pat->patlen != patlen || strncmp(pat, ac->pat->pat, (size_t)patlen) != 0))) { 208 continue; 209 } 210 211 // Show event name and group only if one of them changed. 212 if (ac->pat->group != last_group) { 213 last_group = ac->pat->group; 214 last_group_name = augroup_name(ac->pat->group); 215 216 if (got_int) { 217 return; 218 } 219 220 msg_putchar('\n'); 221 if (got_int) { 222 return; 223 } 224 225 // When switching groups, we need to show the new group information. 226 // show the group name, if it's not the default group 227 if (ac->pat->group != AUGROUP_DEFAULT) { 228 if (last_group_name == NULL) { 229 msg_puts_hl(get_deleted_augroup(), HLF_E, false); 230 } else { 231 msg_puts_hl(last_group_name, HLF_T, false); 232 } 233 msg_puts(" "); 234 } 235 // show the event name 236 msg_puts_hl(event_nr2name(event), HLF_T, false); 237 } 238 239 // Show pattern only if it changed. 240 if (last_ap != ac->pat) { 241 last_ap = ac->pat; 242 243 msg_putchar('\n'); 244 if (got_int) { 245 return; 246 } 247 248 msg_advance(4); 249 msg_outtrans(ac->pat->pat, 0, false); 250 } 251 252 if (got_int) { 253 return; 254 } 255 256 if (msg_col >= 14) { 257 msg_putchar('\n'); 258 } 259 msg_advance(14); 260 if (got_int) { 261 return; 262 } 263 264 char *handler_str = aucmd_handler_to_string(ac); 265 if (ac->desc != NULL) { 266 size_t msglen = 100; 267 char *msg = xmallocz(msglen); 268 if (ac->handler_cmd) { 269 snprintf(msg, msglen, "%s [%s]", handler_str, ac->desc); 270 } else { 271 msg_puts_hl(handler_str, HLF_8, false); 272 snprintf(msg, msglen, " [%s]", ac->desc); 273 } 274 msg_outtrans(msg, 0, false); 275 XFREE_CLEAR(msg); 276 } else if (ac->handler_cmd) { 277 msg_outtrans(handler_str, 0, false); 278 } else { 279 msg_puts_hl(handler_str, HLF_8, false); 280 } 281 XFREE_CLEAR(handler_str); 282 if (p_verbose > 0) { 283 last_set_msg(ac->script_ctx); 284 } 285 286 if (got_int) { 287 return; 288 } 289 } 290 291 patlen = (int)aucmd_span_pattern(endpat, &pat); 292 } while (patlen); 293 } 294 295 // Delete autocommand. 296 static void aucmd_del(AutoCmd *ac) 297 { 298 if (ac->pat != NULL && --ac->pat->refcount == 0) { 299 XFREE_CLEAR(ac->pat->pat); 300 vim_regfree(ac->pat->reg_prog); 301 xfree(ac->pat); 302 } 303 ac->pat = NULL; 304 if (ac->handler_cmd) { 305 XFREE_CLEAR(ac->handler_cmd); 306 } else { 307 callback_free(&ac->handler_fn); 308 } 309 XFREE_CLEAR(ac->desc); 310 311 au_need_clean = true; 312 } 313 314 void aucmd_del_for_event_and_group(event_T event, int group) 315 { 316 AutoCmdVec *const acs = &autocmds[(int)event]; 317 for (size_t i = 0; i < kv_size(*acs); i++) { 318 AutoCmd *const ac = &kv_A(*acs, i); 319 if (ac->pat != NULL && ac->pat->group == group) { 320 aucmd_del(ac); 321 } 322 } 323 324 au_cleanup(); 325 } 326 327 /// Cleanup autocommands that have been deleted. 328 /// This is only done when not executing autocommands. 329 static void au_cleanup(void) 330 { 331 if (autocmd_busy || !au_need_clean) { 332 return; 333 } 334 335 // Loop over all events. 336 FOR_ALL_AUEVENTS(event) { 337 // Loop over all autocommands. 338 AutoCmdVec *const acs = &autocmds[(int)event]; 339 size_t nsize = 0; 340 for (size_t i = 0; i < kv_size(*acs); i++) { 341 AutoCmd *const ac = &kv_A(*acs, i); 342 if (nsize != i) { 343 kv_A(*acs, nsize) = *ac; 344 } 345 if (ac->pat != NULL) { 346 nsize++; 347 } 348 } 349 if (nsize == 0) { 350 kv_destroy(*acs); 351 } else { 352 acs->size = nsize; 353 } 354 } 355 356 au_need_clean = false; 357 } 358 359 AutoCmdVec *au_get_autocmds_for_event(event_T event) 360 FUNC_ATTR_PURE 361 { 362 return &autocmds[(int)event]; 363 } 364 365 // Called when buffer is freed, to remove/invalidate related buffer-local autocmds. 366 void aubuflocal_remove(buf_T *buf) 367 { 368 // invalidate currently executing autocommands 369 for (AutoPatCmd *apc = active_apc_list; apc != NULL; apc = apc->next) { 370 if (buf->b_fnum == apc->arg_bufnr) { 371 apc->arg_bufnr = 0; 372 } 373 } 374 375 // invalidate buflocals looping through events 376 FOR_ALL_AUEVENTS(event) { 377 AutoCmdVec *const acs = &autocmds[(int)event]; 378 for (size_t i = 0; i < kv_size(*acs); i++) { 379 AutoCmd *const ac = &kv_A(*acs, i); 380 if (ac->pat == NULL || ac->pat->buflocal_nr != buf->b_fnum) { 381 continue; 382 } 383 384 aucmd_del(ac); 385 386 if (p_verbose >= 6) { 387 verbose_enter(); 388 smsg(0, _("auto-removing autocommand: %s <buffer=%d>"), event_nr2name(event), buf->b_fnum); 389 verbose_leave(); 390 } 391 } 392 } 393 au_cleanup(); 394 } 395 396 // Add an autocmd group name or return existing group matching name. 397 // Return its ID. 398 int augroup_add(const char *name) 399 { 400 assert(STRICMP(name, "end") != 0); 401 402 int existing_id = augroup_find(name); 403 if (existing_id > 0) { 404 assert(existing_id != AUGROUP_DELETED); 405 return existing_id; 406 } 407 408 if (existing_id == AUGROUP_DELETED) { 409 augroup_map_del(existing_id, name); 410 } 411 412 int next_id = next_augroup_id++; 413 String name_key = cstr_to_string(name); 414 String name_val = cstr_to_string(name); 415 map_put(String, int)(&map_augroup_name_to_id, name_key, next_id); 416 map_put(int, String)(&map_augroup_id_to_name, next_id, name_val); 417 418 return next_id; 419 } 420 421 /// Delete the augroup that matches name. 422 /// @param stupid_legacy_mode bool: This parameter determines whether to run the augroup 423 /// deletion in the same fashion as `:augroup! {name}` where if there are any remaining 424 /// autocmds left in the augroup, it will change the name of the augroup to `--- DELETED ---` 425 /// but leave the autocmds existing. These are _separate_ augroups, so if you do this for 426 /// multiple augroups, you will have a bunch of `--- DELETED ---` augroups at the same time. 427 /// There is no way, as far as I could tell, how to actually delete them at this point as a user 428 /// 429 /// I did not consider this good behavior, so now when NOT in stupid_legacy_mode, we actually 430 /// delete these groups and their commands, like you would expect (and don't leave hanging 431 /// `--- DELETED ---` groups around) 432 void augroup_del(char *name, bool stupid_legacy_mode) 433 { 434 int group = augroup_find(name); 435 if (group == AUGROUP_ERROR) { // the group doesn't exist 436 semsg(_("E367: No such group: \"%s\""), name); 437 return; 438 } else if (group == current_augroup) { 439 emsg(_("E936: Cannot delete the current group")); 440 return; 441 } 442 443 if (stupid_legacy_mode) { 444 FOR_ALL_AUEVENTS(event) { 445 AutoCmdVec *const acs = &autocmds[(int)event]; 446 for (size_t i = 0; i < kv_size(*acs); i++) { 447 AutoPat *const ap = kv_A(*acs, i).pat; 448 if (ap != NULL && ap->group == group) { 449 give_warning(_("W19: Deleting augroup that is still in use"), true, true); 450 map_put(String, int)(&map_augroup_name_to_id, cstr_as_string(name), AUGROUP_DELETED); 451 augroup_map_del(ap->group, NULL); 452 return; 453 } 454 } 455 } 456 } else { 457 FOR_ALL_AUEVENTS(event) { 458 AutoCmdVec *const acs = &autocmds[(int)event]; 459 for (size_t i = 0; i < kv_size(*acs); i++) { 460 AutoCmd *const ac = &kv_A(*acs, i); 461 if (ac->pat != NULL && ac->pat->group == group) { 462 aucmd_del(ac); 463 } 464 } 465 } 466 } 467 468 // Remove the group because it's not currently in use. 469 augroup_map_del(group, name); 470 au_cleanup(); 471 } 472 473 /// Find the ID of an autocmd group name. 474 /// 475 /// @param name augroup name 476 /// 477 /// @return the ID or AUGROUP_ERROR (< 0) for error. 478 int augroup_find(const char *name) 479 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT 480 { 481 int existing_id = map_get(String, int)(&map_augroup_name_to_id, cstr_as_string(name)); 482 if (existing_id == AUGROUP_DELETED) { 483 return existing_id; 484 } 485 486 if (existing_id > 0) { 487 return existing_id; 488 } 489 490 return AUGROUP_ERROR; 491 } 492 493 /// Gets the name for a particular group. 494 char *augroup_name(int group) 495 { 496 assert(group != 0); 497 498 if (group == AUGROUP_DELETED) { 499 return (char *)get_deleted_augroup(); 500 } 501 502 if (group == AUGROUP_ALL) { 503 group = current_augroup; 504 } 505 506 // next_augroup_id is the "source of truth" about what autocmds have existed 507 // 508 // The map_size is not the source of truth because groups can be removed from 509 // the map. When this happens, the map size is reduced. That's why this function 510 // relies on next_augroup_id instead. 511 512 // "END" is always considered the last augroup ID. 513 // Used for expand_get_event_name and expand_get_augroup_name 514 if (group == next_augroup_id) { 515 return "END"; 516 } 517 518 // If it's larger than the largest group, then it doesn't have a name 519 if (group > next_augroup_id) { 520 return NULL; 521 } 522 523 String key = map_get(int, String)(&map_augroup_id_to_name, group); 524 if (key.data != NULL) { 525 return key.data; 526 } 527 528 // If it's not in the map anymore, then it must have been deleted. 529 return (char *)get_deleted_augroup(); 530 } 531 532 /// Return true if augroup "name" exists. 533 /// 534 /// @param name augroup name 535 bool augroup_exists(const char *name) 536 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT 537 { 538 return augroup_find(name) > 0; 539 } 540 541 /// ":augroup {name}". 542 void do_augroup(char *arg, bool del_group) 543 { 544 if (del_group) { 545 if (*arg == NUL) { 546 emsg(_(e_argreq)); 547 } else { 548 augroup_del(arg, true); 549 } 550 } else if (STRICMP(arg, "end") == 0) { // ":aug end": back to group 0 551 current_augroup = AUGROUP_DEFAULT; 552 } else if (*arg) { // ":aug xxx": switch to group xxx 553 current_augroup = augroup_add(arg); 554 } else { // ":aug": list the group names 555 msg_start(); 556 msg_ext_set_kind("list_cmd"); 557 558 String name; 559 int value; 560 map_foreach(&map_augroup_name_to_id, name, value, { 561 if (value > 0) { 562 msg_puts(name.data); 563 } else { 564 msg_puts(augroup_name(value)); 565 } 566 567 msg_puts(" "); 568 }); 569 570 msg_clr_eos(); 571 msg_end(); 572 } 573 } 574 575 #if defined(EXITFREE) 576 void free_all_autocmds(void) 577 { 578 FOR_ALL_AUEVENTS(event) { 579 AutoCmdVec *const acs = &autocmds[(int)event]; 580 for (size_t i = 0; i < kv_size(*acs); i++) { 581 aucmd_del(&kv_A(*acs, i)); 582 } 583 kv_destroy(*acs); 584 au_need_clean = false; 585 } 586 587 // Delete the augroup_map, including free the data 588 String name; 589 map_foreach_key(&map_augroup_name_to_id, name, { 590 api_free_string(name); 591 }) 592 map_destroy(String, &map_augroup_name_to_id); 593 594 map_foreach_value(&map_augroup_id_to_name, name, { 595 api_free_string(name); 596 }) 597 map_destroy(int, &map_augroup_id_to_name); 598 599 // aucmd_win[] is freed in win_free_all() 600 } 601 #endif 602 603 /// Return true if "win" is an active entry in aucmd_win[]. 604 bool is_aucmd_win(win_T *win) 605 { 606 for (int i = 0; i < AUCMD_WIN_COUNT; i++) { 607 if (aucmd_win[i].auc_win_used && aucmd_win[i].auc_win == win) { 608 return true; 609 } 610 } 611 return false; 612 } 613 614 /// Return the event number for event name "start". 615 /// Return NUM_EVENTS if the event name was not found. 616 /// Return a pointer to the next event name in "end". 617 event_T event_name2nr(const char *start, char **end) 618 { 619 const char *p; 620 621 // the event name ends with end of line, '|', a blank or a comma 622 for (p = start; *p && !ascii_iswhite(*p) && *p != ',' && *p != '|'; p++) {} 623 624 int hash_idx = event_name2nr_hash(start, (size_t)(p - start)); 625 if (*p == ',') { 626 p++; 627 } 628 *end = (char *)p; 629 if (hash_idx < 0) { 630 return NUM_EVENTS; 631 } 632 return (event_T)abs(event_names[event_hash[hash_idx]].event); 633 } 634 635 /// Return the event number for event name "str". 636 /// Return NUM_EVENTS if the event name was not found. 637 event_T event_name2nr_str(String str) 638 { 639 int hash_idx = event_name2nr_hash(str.data, str.size); 640 if (hash_idx < 0) { 641 return NUM_EVENTS; 642 } 643 return (event_T)abs(event_names[event_hash[hash_idx]].event); 644 } 645 646 /// Return the name for event 647 /// 648 /// @param[in] event Event to return name for. 649 /// 650 /// @return Event name, static string. Returns "Unknown" for unknown events. 651 const char *event_nr2name(event_T event) 652 FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST 653 { 654 return event >= 0 && event < NUM_EVENTS ? event_names[event].name : "Unknown"; 655 } 656 657 /// Return true if "event" is included in 'eventignore(win)'. 658 /// 659 /// @param event event to check 660 bool event_ignored(event_T event, char *ei) 661 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT 662 { 663 bool ignored = false; 664 while (*ei != NUL) { 665 bool unignore = *ei == '-'; 666 ei += unignore; 667 if (STRNICMP(ei, "all", 3) == 0 && (ei[3] == NUL || ei[3] == ',')) { 668 ignored = ei == p_ei || event_names[event].event <= 0; 669 ei += 3 + (ei[3] == ','); 670 } else if (event_name2nr(ei, &ei) == event) { 671 if (unignore) { 672 return false; 673 } 674 ignored = true; 675 } 676 } 677 678 return ignored; 679 } 680 681 /// Return OK when the contents of 'eventignore' or 'eventignorewin' is valid, 682 /// FAIL otherwise. 683 int check_ei(char *ei) 684 { 685 bool win = ei != p_ei; 686 687 while (*ei) { 688 if (STRNICMP(ei, "all", 3) == 0 && (ei[3] == NUL || ei[3] == ',')) { 689 ei += 3 + (ei[3] == ','); 690 } else { 691 ei += (*ei == '-'); 692 event_T event = event_name2nr(ei, &ei); 693 if (event == NUM_EVENTS || (win && event_names[event].event > 0)) { 694 return FAIL; 695 } 696 } 697 } 698 699 return OK; 700 } 701 702 // Add "what" to 'eventignore' to skip loading syntax highlighting for every 703 // buffer loaded into the window. "what" must start with a comma. 704 // Returns the old value of 'eventignore' in allocated memory. 705 char *au_event_disable(char *what) 706 { 707 size_t p_ei_len = strlen(p_ei); 708 char *save_ei = xmemdupz(p_ei, p_ei_len); 709 char *new_ei = xstrnsave(p_ei, p_ei_len + strlen(what)); 710 if (*what == ',' && *p_ei == NUL) { 711 STRCPY(new_ei, what + 1); 712 } else { 713 STRCPY(new_ei + p_ei_len, what); 714 } 715 set_option_direct(kOptEventignore, CSTR_AS_OPTVAL(new_ei), 0, SID_NONE); 716 xfree(new_ei); 717 return save_ei; 718 } 719 720 void au_event_restore(char *old_ei) 721 { 722 if (old_ei != NULL) { 723 set_option_direct(kOptEventignore, CSTR_AS_OPTVAL(old_ei), 0, SID_NONE); 724 xfree(old_ei); 725 } 726 } 727 728 // Implements :autocmd. 729 // Defines an autocmd (does not execute; cf. apply_autocmds_group). 730 // 731 // Can be used in the following ways: 732 // 733 // :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that 734 // will be automatically executed for <event> 735 // when editing a file matching <pat>, in 736 // the current group. 737 // :autocmd <event> <pat> Show the autocommands associated with 738 // <event> and <pat>. 739 // :autocmd <event> Show the autocommands associated with 740 // <event>. 741 // :autocmd Show all autocommands. 742 // :autocmd! <event> <pat> <cmd> Remove all autocommands associated with 743 // <event> and <pat>, and add the command 744 // <cmd>, for the current group. 745 // :autocmd! <event> <pat> Remove all autocommands associated with 746 // <event> and <pat> for the current group. 747 // :autocmd! <event> Remove all autocommands associated with 748 // <event> for the current group. 749 // :autocmd! Remove ALL autocommands for the current 750 // group. 751 // 752 // Multiple events and patterns may be given separated by commas. Here are 753 // some examples: 754 // :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic 755 // :autocmd bufleave * set tw=79 nosmartindent ic infercase 756 // 757 // :autocmd * *.c show all autocommands for *.c files. 758 // 759 // Mostly a {group} argument can optionally appear before <event>. 760 void do_autocmd(exarg_T *eap, char *arg_in, int forceit) 761 { 762 char *arg = arg_in; 763 char *envpat = NULL; 764 char *cmd; 765 bool need_free = false; 766 bool nested = false; 767 bool once = false; 768 int group; 769 770 if (*arg == '|') { 771 eap->nextcmd = arg + 1; 772 arg = ""; 773 group = AUGROUP_ALL; // no argument, use all groups 774 } else { 775 // Check for a legal group name. If not, use AUGROUP_ALL. 776 group = arg_augroup_get(&arg); 777 } 778 779 // Scan over the events. 780 // If we find an illegal name, return here, don't do anything. 781 char *pat = arg_event_skip(arg, group != AUGROUP_ALL); 782 if (pat == NULL) { 783 return; 784 } 785 786 pat = skipwhite(pat); 787 if (*pat == '|') { 788 eap->nextcmd = pat + 1; 789 pat = ""; 790 cmd = ""; 791 } else { 792 // Scan over the pattern. Put a NUL at the end. 793 cmd = pat; 794 while (*cmd && (!ascii_iswhite(*cmd) || cmd[-1] == '\\')) { 795 cmd++; 796 } 797 if (*cmd) { 798 *cmd++ = NUL; 799 } 800 801 // Expand environment variables in the pattern. Set 'shellslash', we want 802 // forward slashes here. 803 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL) { 804 #ifdef BACKSLASH_IN_FILENAME 805 int p_ssl_save = p_ssl; 806 807 p_ssl = true; 808 #endif 809 envpat = expand_env_save(pat); 810 #ifdef BACKSLASH_IN_FILENAME 811 p_ssl = p_ssl_save; 812 #endif 813 if (envpat != NULL) { 814 pat = envpat; 815 } 816 } 817 818 cmd = skipwhite(cmd); 819 820 bool invalid_flags = false; 821 for (size_t i = 0; i < 2; i++) { 822 if (*cmd == NUL) { 823 continue; 824 } 825 826 invalid_flags |= arg_autocmd_flag_get(&once, &cmd, "++once", 6); 827 invalid_flags |= arg_autocmd_flag_get(&nested, &cmd, "++nested", 8); 828 829 // Check the deprecated "nested" flag. 830 invalid_flags |= arg_autocmd_flag_get(&nested, &cmd, "nested", 6); 831 } 832 833 if (invalid_flags) { 834 return; 835 } 836 837 // Find the start of the commands. 838 // Expand <sfile> in it. 839 if (*cmd != NUL) { 840 cmd = expand_sfile(cmd); 841 if (cmd == NULL) { // some error 842 return; 843 } 844 need_free = true; 845 } 846 } 847 848 const bool is_showing = !forceit && *cmd == NUL; 849 850 // Print header when showing autocommands. 851 if (is_showing) { 852 // Highlight title 853 msg_ext_set_kind("list_cmd"); 854 msg_puts_title(_("\n--- Autocommands ---")); 855 856 if (*arg == '*' || *arg == '|' || *arg == NUL) { 857 au_show_for_all_events(group, pat); 858 } else { 859 event_T event = event_name2nr(arg, &arg); 860 assert(event < NUM_EVENTS); 861 au_show_for_event(group, event, pat); 862 } 863 } else { 864 if (*arg == '*' || *arg == NUL || *arg == '|') { 865 if (*cmd != NUL) { 866 emsg(_(e_cannot_define_autocommands_for_all_events)); 867 } else { 868 do_all_autocmd_events(pat, once, nested, cmd, forceit, group); 869 } 870 } else { 871 while (*arg && *arg != '|' && !ascii_iswhite(*arg)) { 872 event_T event = event_name2nr(arg, &arg); 873 assert(event < NUM_EVENTS); 874 if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group) == FAIL) { 875 break; 876 } 877 } 878 } 879 } 880 881 if (need_free) { 882 xfree(cmd); 883 } 884 xfree(envpat); 885 } 886 887 void do_all_autocmd_events(const char *pat, bool once, int nested, char *cmd, bool del, int group) 888 { 889 FOR_ALL_AUEVENTS(event) { 890 if (do_autocmd_event(event, pat, once, nested, cmd, del, group) == FAIL) { 891 return; 892 } 893 } 894 } 895 896 // do_autocmd() for one event. 897 // Defines an autocmd (does not execute; cf. apply_autocmds_group). 898 // 899 // If *pat == NUL: do for all patterns. 900 // If *cmd == NUL: show entries. 901 // If forceit == true: delete entries. 902 // If group is not AUGROUP_ALL: only use this group. 903 int do_autocmd_event(event_T event, const char *pat, bool once, int nested, const char *cmd, 904 bool del, int group) 905 FUNC_ATTR_NONNULL_ALL 906 { 907 // Cannot be used to show all patterns. See au_show_for_event or au_show_for_all_events 908 assert(*pat != NUL || del); 909 910 char buflocal_pat[BUFLOCAL_PAT_LEN]; // for "<buffer=X>" 911 912 bool is_adding_cmd = *cmd != NUL; 913 const int findgroup = group == AUGROUP_ALL ? current_augroup : group; 914 915 // Delete all aupat for an event. 916 if (*pat == NUL && del) { 917 aucmd_del_for_event_and_group(event, findgroup); 918 return OK; 919 } 920 921 // Loop through all the specified patterns. 922 int patlen = (int)aucmd_span_pattern(pat, &pat); 923 while (patlen) { 924 const char *endpat = pat + patlen; 925 926 // detect special <buffer[=X]> buffer-local patterns 927 bool is_buflocal = aupat_is_buflocal(pat, patlen); 928 if (is_buflocal) { 929 const int buflocal_nr = aupat_get_buflocal_nr(pat, patlen); 930 931 // normalize pat into standard "<buffer>#N" form 932 aupat_normalize_buflocal_pat(buflocal_pat, pat, patlen, buflocal_nr); 933 934 pat = buflocal_pat; 935 patlen = (int)strlen(buflocal_pat); 936 } 937 938 if (del) { 939 assert(*pat != NUL); 940 941 // Find existing autocommands with this pattern. 942 AutoCmdVec *const acs = &autocmds[(int)event]; 943 for (size_t i = 0; i < kv_size(*acs); i++) { 944 AutoCmd *const ac = &kv_A(*acs, i); 945 AutoPat *const ap = ac->pat; 946 // Accept a pattern when: 947 // - a group was specified and it's that group 948 // - the length of the pattern matches 949 // - the pattern matches. 950 // For <buffer[=X]>, this condition works because we normalize 951 // all buffer-local patterns. 952 if (ap != NULL && ap->group == findgroup && ap->patlen == patlen 953 && strncmp(pat, ap->pat, (size_t)patlen) == 0) { 954 // Remove existing autocommands. 955 // If adding any new autocmd's for this AutoPat, don't 956 // delete the pattern from the autopat list, append to 957 // this list. 958 aucmd_del(ac); 959 } 960 } 961 } 962 963 if (is_adding_cmd) { 964 Callback handler_fn = CALLBACK_INIT; 965 autocmd_register(0, event, pat, patlen, group, once, nested, NULL, cmd, &handler_fn); 966 } 967 968 patlen = (int)aucmd_span_pattern(endpat, &pat); 969 } 970 971 au_cleanup(); // may really delete removed patterns/commands now 972 return OK; 973 } 974 975 /// Registers an autocmd. The handler may be a Ex command or callback function, decided by 976 /// the `handler_cmd` or `handler_fn` args. 977 /// 978 /// @param handler_cmd Handler Ex command, or NULL if handler is a function (`handler_fn`). 979 /// @param handler_fn Handler function, ignored if `handler_cmd` is not NULL. 980 int autocmd_register(int64_t id, event_T event, const char *pat, int patlen, int group, bool once, 981 bool nested, char *desc, const char *handler_cmd, Callback *handler_fn) 982 { 983 // 0 is not a valid group. 984 assert(group != 0); 985 986 if (patlen > (int)strlen(pat)) { 987 return FAIL; 988 } 989 990 const int findgroup = group == AUGROUP_ALL ? current_augroup : group; 991 992 // detect special <buffer[=X]> buffer-local patterns 993 const bool is_buflocal = aupat_is_buflocal(pat, patlen); 994 int buflocal_nr = 0; 995 996 char buflocal_pat[BUFLOCAL_PAT_LEN]; // for "<buffer=X>" 997 if (is_buflocal) { 998 buflocal_nr = aupat_get_buflocal_nr(pat, patlen); 999 1000 // normalize pat into standard "<buffer>#N" form 1001 aupat_normalize_buflocal_pat(buflocal_pat, pat, patlen, buflocal_nr); 1002 1003 pat = buflocal_pat; 1004 patlen = (int)strlen(buflocal_pat); 1005 } 1006 1007 // Try to reuse pattern from the last existing autocommand. 1008 AutoPat *ap = NULL; 1009 AutoCmdVec *const acs = &autocmds[(int)event]; 1010 for (ptrdiff_t i = (ptrdiff_t)kv_size(*acs) - 1; i >= 0; i--) { 1011 ap = kv_A(*acs, i).pat; 1012 if (ap == NULL) { 1013 continue; // Skip deleted autocommands. 1014 } 1015 // Set result back to NULL if the last pattern doesn't match. 1016 if (ap->group != findgroup || ap->patlen != patlen 1017 || strncmp(pat, ap->pat, (size_t)patlen) != 0) { 1018 ap = NULL; 1019 } 1020 break; 1021 } 1022 1023 // No matching pattern found, allocate a new one. 1024 if (ap == NULL) { 1025 // refuse to add buffer-local ap if buffer number is invalid 1026 if (is_buflocal && (buflocal_nr == 0 || buflist_findnr(buflocal_nr) == NULL)) { 1027 semsg(_("E680: <buffer=%d>: invalid buffer number "), buflocal_nr); 1028 return FAIL; 1029 } 1030 1031 ap = xmalloc(sizeof(AutoPat)); 1032 1033 if (is_buflocal) { 1034 ap->buflocal_nr = buflocal_nr; 1035 ap->reg_prog = NULL; 1036 } else { 1037 ap->buflocal_nr = 0; 1038 char *reg_pat = file_pat_to_reg_pat(pat, pat + patlen, &ap->allow_dirs, true); 1039 if (reg_pat != NULL) { 1040 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC); 1041 } 1042 xfree(reg_pat); 1043 if (reg_pat == NULL || ap->reg_prog == NULL) { 1044 xfree(ap); 1045 return FAIL; 1046 } 1047 } 1048 1049 ap->refcount = 0; 1050 ap->pat = xmemdupz(pat, (size_t)patlen); 1051 ap->patlen = patlen; 1052 1053 // need to initialize last_mode for the first ModeChanged autocmd 1054 if (event == EVENT_MODECHANGED && !has_event(EVENT_MODECHANGED)) { 1055 get_mode(last_mode); 1056 } 1057 1058 // If the event is CursorMoved or CursorMovedI, update the last cursor position 1059 // position to avoid immediately triggering the autocommand 1060 if ((event == EVENT_CURSORMOVED && !has_event(EVENT_CURSORMOVED)) 1061 || (event == EVENT_CURSORMOVEDI && !has_event(EVENT_CURSORMOVEDI))) { 1062 last_cursormoved_win = curwin; 1063 last_cursormoved = curwin->w_cursor; 1064 } 1065 1066 // Initialize the fields checked by the WinScrolled and 1067 // WinResized trigger to prevent them from firing right after 1068 // the first autocmd is defined. 1069 if ((event == EVENT_WINSCROLLED || event == EVENT_WINRESIZED) 1070 && !(has_event(EVENT_WINSCROLLED) || has_event(EVENT_WINRESIZED))) { 1071 tabpage_T *save_curtab = curtab; 1072 FOR_ALL_TABS(tp) { 1073 unuse_tabpage(curtab); 1074 use_tabpage(tp); 1075 snapshot_windows_scroll_size(); 1076 } 1077 unuse_tabpage(curtab); 1078 use_tabpage(save_curtab); 1079 } 1080 1081 ap->group = group == AUGROUP_ALL ? current_augroup : group; 1082 } 1083 1084 ap->refcount++; 1085 1086 // Add the autocmd at the end of the AutoCmd vector. 1087 AutoCmd *ac = kv_pushp(autocmds[(int)event]); 1088 ac->pat = ap; 1089 ac->id = id; 1090 if (handler_cmd) { 1091 ac->handler_cmd = xstrdup(handler_cmd); 1092 } else { 1093 ac->handler_cmd = NULL; 1094 callback_copy(&ac->handler_fn, handler_fn); 1095 } 1096 ac->script_ctx = current_sctx; 1097 ac->script_ctx.sc_lnum += SOURCING_LNUM; 1098 nlua_set_sctx(&ac->script_ctx); 1099 ac->once = once; 1100 ac->nested = nested; 1101 ac->desc = desc == NULL ? NULL : xstrdup(desc); 1102 1103 return OK; 1104 } 1105 1106 size_t aucmd_span_pattern(const char *pat, const char **start) 1107 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT 1108 { 1109 // Skip leading commas. 1110 while (*pat == ',') { 1111 pat++; 1112 } 1113 1114 // Find end of the pattern. 1115 // Watch out for a comma in braces, like "*.\{obj,o\}". 1116 const char *p = pat; 1117 int brace_level = 0; 1118 for (; *p && (*p != ',' || brace_level || (p > pat && p[-1] == '\\')); p++) { 1119 if (*p == '{') { 1120 brace_level++; 1121 } else if (*p == '}') { 1122 brace_level--; 1123 } 1124 } 1125 1126 *start = pat; 1127 return (size_t)(p - pat); 1128 } 1129 1130 /// Implementation of ":doautocmd [group] event [fname]". 1131 /// Return OK for success, FAIL for failure; 1132 /// 1133 /// @param do_msg give message for no matching autocmds? 1134 int do_doautocmd(char *arg_start, bool do_msg, bool *did_something) 1135 { 1136 char *arg = arg_start; 1137 int nothing_done = true; 1138 1139 if (did_something != NULL) { 1140 *did_something = false; 1141 } 1142 1143 // Check for a legal group name. If not, use AUGROUP_ALL. 1144 int group = arg_augroup_get(&arg); 1145 1146 if (*arg == '*') { 1147 emsg(_("E217: Can't execute autocommands for ALL events")); 1148 return FAIL; 1149 } 1150 1151 // Scan over the events. 1152 // If we find an illegal name, return here, don't do anything. 1153 char *fname = arg_event_skip(arg, group != AUGROUP_ALL); 1154 if (fname == NULL) { 1155 return FAIL; 1156 } 1157 1158 fname = skipwhite(fname); 1159 1160 // Loop over the events. 1161 while (*arg && !ends_excmd(*arg) && !ascii_iswhite(*arg)) { 1162 if (apply_autocmds_group(event_name2nr(arg, &arg), fname, NULL, true, group, 1163 curbuf, NULL, NULL)) { 1164 nothing_done = false; 1165 } 1166 } 1167 1168 if (nothing_done && do_msg && !aborting()) { 1169 smsg(0, _("No matching autocommands: %s"), arg_start); 1170 } 1171 if (did_something != NULL) { 1172 *did_something = !nothing_done; 1173 } 1174 1175 return aborting() ? FAIL : OK; 1176 } 1177 1178 // ":doautoall": execute autocommands for each loaded buffer. 1179 void ex_doautoall(exarg_T *eap) 1180 { 1181 int retval = OK; 1182 aco_save_T aco; 1183 char *arg = eap->arg; 1184 int call_do_modelines = check_nomodeline(&arg); 1185 bufref_T bufref; 1186 bool did_aucmd; 1187 1188 // This is a bit tricky: For some commands curwin->w_buffer needs to be 1189 // equal to curbuf, but for some buffers there may not be a window. 1190 // So we change the buffer for the current window for a moment. This 1191 // gives problems when the autocommands make changes to the list of 1192 // buffers or windows... 1193 FOR_ALL_BUFFERS(buf) { 1194 // Only do loaded buffers and skip the current buffer, it's done last. 1195 if (buf->b_ml.ml_mfp == NULL || buf == curbuf) { 1196 continue; 1197 } 1198 1199 // Find a window for this buffer and save some values. 1200 aucmd_prepbuf(&aco, buf); 1201 set_bufref(&bufref, buf); 1202 1203 // execute the autocommands for this buffer 1204 retval = do_doautocmd(arg, false, &did_aucmd); 1205 1206 if (call_do_modelines && did_aucmd) { 1207 // Execute the modeline settings, but don't set window-local 1208 // options if we are using the current window for another 1209 // buffer. 1210 do_modelines(is_aucmd_win(curwin) ? OPT_NOWIN : 0); 1211 } 1212 1213 // restore the current window 1214 aucmd_restbuf(&aco); 1215 1216 // Stop if there is some error or buffer was deleted. 1217 if (retval == FAIL || !bufref_valid(&bufref)) { 1218 retval = FAIL; 1219 break; 1220 } 1221 } 1222 1223 // Execute autocommands for the current buffer last. 1224 if (retval == OK) { 1225 do_doautocmd(arg, false, &did_aucmd); 1226 if (call_do_modelines && did_aucmd) { 1227 do_modelines(0); 1228 } 1229 } 1230 } 1231 1232 /// Check *argp for <nomodeline>. When it is present return false, otherwise 1233 /// return true and advance *argp to after it. Thus do_modelines() should be 1234 /// called when true is returned. 1235 /// 1236 /// @param[in,out] argp argument string 1237 bool check_nomodeline(char **argp) 1238 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT 1239 { 1240 if (strncmp(*argp, "<nomodeline>", 12) == 0) { 1241 *argp = skipwhite(*argp + 12); 1242 return false; 1243 } 1244 return true; 1245 } 1246 1247 /// Prepare for executing autocommands for (hidden) buffer `buf`. 1248 /// If the current buffer is not in any visible window, put it in a temporary 1249 /// floating window using an entry in `aucmd_win[]`. 1250 /// Set `curbuf` and `curwin` to match `buf`. 1251 /// 1252 /// @param aco structure to save values in 1253 /// @param buf new curbuf 1254 void aucmd_prepbuf(aco_save_T *aco, buf_T *buf) 1255 { 1256 win_T *win; 1257 bool need_append = true; // Append `aucmd_win` to the window list. 1258 const bool same_buffer = buf == curbuf; 1259 1260 // Find a window that is for the new buffer 1261 if (same_buffer) { // be quick when buf is curbuf 1262 win = curwin; 1263 } else { 1264 win = NULL; 1265 FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { 1266 if (wp->w_buffer == buf) { 1267 win = wp; 1268 break; 1269 } 1270 } 1271 } 1272 1273 // Allocate a window when needed. 1274 win_T *auc_win = NULL; 1275 int auc_idx = AUCMD_WIN_COUNT; 1276 if (win == NULL) { 1277 for (auc_idx = 0; auc_idx < AUCMD_WIN_COUNT; auc_idx++) { 1278 if (!aucmd_win[auc_idx].auc_win_used) { 1279 break; 1280 } 1281 } 1282 1283 if (auc_idx == AUCMD_WIN_COUNT) { 1284 kv_push(aucmd_win_vec, ((aucmdwin_T){ 1285 .auc_win = NULL, 1286 .auc_win_used = false, 1287 })); 1288 } 1289 1290 if (aucmd_win[auc_idx].auc_win == NULL) { 1291 win_alloc_aucmd_win(auc_idx); 1292 need_append = false; 1293 } 1294 auc_win = aucmd_win[auc_idx].auc_win; 1295 aucmd_win[auc_idx].auc_win_used = true; 1296 } 1297 1298 aco->save_curwin_handle = curwin->handle; 1299 aco->save_prevwin_handle = prevwin == NULL ? 0 : prevwin->handle; 1300 if (bt_prompt(curbuf)) { 1301 aco->save_prompt_insert = curbuf->b_prompt_insert; 1302 } 1303 1304 if (win != NULL) { 1305 // There is a window for "buf" in the current tab page, make it the 1306 // curwin. This is preferred, it has the least side effects (esp. if 1307 // "buf" is curbuf). 1308 aco->use_aucmd_win_idx = -1; 1309 curwin = win; 1310 } else { 1311 // There is no window for "buf", use "auc_win". To minimize the side 1312 // effects, insert it in the current tab page. 1313 // Anything related to a window (e.g., setting folds) may have 1314 // unexpected results. 1315 aco->use_aucmd_win_idx = auc_idx; 1316 auc_win->w_buffer = buf; 1317 auc_win->w_s = &buf->b_s; 1318 buf->b_nwindows++; 1319 win_init_empty(auc_win); // set cursor and topline to safe values 1320 1321 // Make sure w_localdir, tp_localdir and globaldir are NULL to avoid a 1322 // chdir() in win_enter_ext(). 1323 XFREE_CLEAR(auc_win->w_localdir); 1324 aco->tp_localdir = curtab->tp_localdir; 1325 curtab->tp_localdir = NULL; 1326 aco->globaldir = globaldir; 1327 globaldir = NULL; 1328 1329 block_autocmds(); // We don't want BufEnter/WinEnter autocommands. 1330 if (need_append) { 1331 win_append(lastwin, auc_win, NULL); 1332 pmap_put(int)(&window_handles, auc_win->handle, auc_win); 1333 win_config_float(auc_win, auc_win->w_config); 1334 } 1335 // Prevent chdir() call in win_enter_ext(), through do_autochdir() 1336 const int save_acd = p_acd; 1337 p_acd = false; 1338 // no redrawing and don't set the window title 1339 RedrawingDisabled++; 1340 win_enter(auc_win, false); 1341 RedrawingDisabled--; 1342 p_acd = save_acd; 1343 unblock_autocmds(); 1344 curwin = auc_win; 1345 } 1346 curbuf = buf; 1347 aco->new_curwin_handle = curwin->handle; 1348 set_bufref(&aco->new_curbuf, curbuf); 1349 1350 aco->save_VIsual_active = VIsual_active; 1351 if (!same_buffer) { 1352 // disable the Visual area, position may be invalid in another buffer 1353 VIsual_active = false; 1354 } 1355 } 1356 1357 /// Cleanup after executing autocommands for a (hidden) buffer. 1358 /// Restore the window as it was (if possible). 1359 /// 1360 /// @param aco structure holding saved values 1361 void aucmd_restbuf(aco_save_T *aco) 1362 { 1363 if (aco->use_aucmd_win_idx >= 0) { 1364 win_T *awp = aucmd_win[aco->use_aucmd_win_idx].auc_win; 1365 1366 // Find "awp", it can't be closed, but it may be in another tab page. 1367 // Do not trigger autocommands here. 1368 block_autocmds(); 1369 if (curwin != awp) { 1370 FOR_ALL_TAB_WINDOWS(tp, wp) { 1371 if (wp == awp) { 1372 if (tp != curtab) { 1373 goto_tabpage_tp(tp, true, true); 1374 } 1375 win_goto(awp); 1376 goto win_found; 1377 } 1378 } 1379 } 1380 win_found: 1381 curbuf->b_nwindows--; 1382 // Remove the window. 1383 win_remove(curwin, NULL); 1384 pmap_del(int)(&window_handles, curwin->handle, NULL); 1385 if (curwin->w_grid_alloc.chars != NULL) { 1386 ui_comp_remove_grid(&curwin->w_grid_alloc); 1387 ui_call_win_hide(curwin->w_grid_alloc.handle); 1388 grid_free(&curwin->w_grid_alloc); 1389 } 1390 1391 // The window is marked as not used, but it is not freed, it can be 1392 // used again. 1393 aucmd_win[aco->use_aucmd_win_idx].auc_win_used = false; 1394 1395 if (!valid_tabpage_win(curtab)) { 1396 // no valid window in current tabpage 1397 close_tabpage(curtab); 1398 } 1399 1400 unblock_autocmds(); 1401 1402 win_T *const save_curwin = win_find_by_handle(aco->save_curwin_handle); 1403 if (save_curwin != NULL) { 1404 curwin = save_curwin; 1405 } else { 1406 // Hmm, original window disappeared. Just use the first one. 1407 curwin = firstwin; 1408 } 1409 curbuf = curwin->w_buffer; 1410 // May need to restore insert mode for a prompt buffer. 1411 entering_window(curwin); 1412 if (bt_prompt(curbuf)) { 1413 curbuf->b_prompt_insert = aco->save_prompt_insert; 1414 } 1415 1416 prevwin = win_find_by_handle(aco->save_prevwin_handle); 1417 vars_clear(&awp->w_vars->dv_hashtab); // free all w: variables 1418 hash_init(&awp->w_vars->dv_hashtab); // re-use the hashtab 1419 1420 // If :lcd has been used in the autocommand window, correct current 1421 // directory before restoring tp_localdir and globaldir. 1422 if (awp->w_localdir != NULL) { 1423 win_fix_current_dir(); 1424 } 1425 xfree(curtab->tp_localdir); 1426 curtab->tp_localdir = aco->tp_localdir; 1427 xfree(globaldir); 1428 globaldir = aco->globaldir; 1429 1430 // the buffer contents may have changed 1431 VIsual_active = aco->save_VIsual_active; 1432 check_cursor(curwin); 1433 if (curwin->w_topline > curbuf->b_ml.ml_line_count) { 1434 curwin->w_topline = curbuf->b_ml.ml_line_count; 1435 curwin->w_topfill = 0; 1436 } 1437 } else { 1438 // Restore curwin. Use the window ID, a window may have been closed 1439 // and the memory re-used for another one. 1440 win_T *const save_curwin = win_find_by_handle(aco->save_curwin_handle); 1441 if (save_curwin != NULL) { 1442 // Restore the buffer which was previously edited by curwin, if it was 1443 // changed, we are still the same window and the buffer is valid. 1444 if (curwin->handle == aco->new_curwin_handle 1445 && curbuf != aco->new_curbuf.br_buf 1446 && bufref_valid(&aco->new_curbuf) 1447 && aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL) { 1448 if (curwin->w_s == &curbuf->b_s) { 1449 curwin->w_s = &aco->new_curbuf.br_buf->b_s; 1450 } 1451 curbuf->b_nwindows--; 1452 curbuf = aco->new_curbuf.br_buf; 1453 curwin->w_buffer = curbuf; 1454 curbuf->b_nwindows++; 1455 } 1456 1457 curwin = save_curwin; 1458 curbuf = curwin->w_buffer; 1459 prevwin = win_find_by_handle(aco->save_prevwin_handle); 1460 1461 // In case the autocommand moves the cursor to a position that does not 1462 // exist in curbuf 1463 VIsual_active = aco->save_VIsual_active; 1464 check_cursor(curwin); 1465 } 1466 } 1467 1468 VIsual_active = aco->save_VIsual_active; 1469 check_cursor(curwin); // just in case lines got deleted 1470 if (VIsual_active) { 1471 check_pos(curbuf, &VIsual); 1472 } 1473 } 1474 1475 /// Schedules an autocommand event, to be executed at the next event-loop tick. 1476 /// 1477 /// @param event Event to schedule 1478 /// @param fname Name to use as `<amatch>` (the "pattern"). NULL/empty means use actual filename. 1479 /// @param fname_io Filename to use for <afile> on cmdline, NULL means use `fname`. 1480 /// @param group Group ID or AUGROUP_ALL 1481 /// @param buf Buffer for <abuf> 1482 /// @param eap Ex command arguments 1483 /// @param data Event-specific data. Will be copied, caller must free `data`. 1484 /// The `data` items will also be copied to `v:event`. 1485 void aucmd_defer(event_T event, char *fname, char *fname_io, int group, buf_T *buf, exarg_T *eap, 1486 Object *data) 1487 { 1488 AutoCmdEvent *evdata = xmalloc(sizeof(AutoCmdEvent)); 1489 evdata->event = event; 1490 evdata->fname = fname != NULL ? xstrdup(fname) : NULL; 1491 evdata->fname_io = fname_io != NULL ? xstrdup(fname_io) : NULL; 1492 evdata->group = group; 1493 evdata->buf = buf->handle; 1494 evdata->eap = eap; 1495 if (data) { 1496 evdata->data = xmalloc(sizeof(Object)); 1497 *evdata->data = copy_object(*data, NULL); 1498 } else { 1499 evdata->data = NULL; 1500 } 1501 1502 multiqueue_put(deferred_events, deferred_event, evdata); 1503 } 1504 1505 /// Executes a deferred autocommand event. 1506 static void deferred_event(void **argv) 1507 { 1508 AutoCmdEvent *e = argv[0]; 1509 event_T event = e->event; 1510 char *fname = e->fname; 1511 char *fname_io = e->fname_io; 1512 int group = e->group; 1513 exarg_T *eap = e->eap; 1514 Object *data = e->data; 1515 1516 Error err = ERROR_INIT; 1517 buf_T *buf = find_buffer_by_handle(e->buf, &err); 1518 if (buf) { 1519 // Copy `data` to `v:event`. 1520 save_v_event_T save_v_event; 1521 dict_T *v_event = get_v_event(&save_v_event); 1522 if (data && data->type == kObjectTypeDict) { 1523 for (size_t i = 0; i < data->data.dict.size; i++) { 1524 KeyValuePair item = data->data.dict.items[i]; 1525 typval_T tv; 1526 object_to_vim(item.value, &tv, &err); 1527 if (ERROR_SET(&err)) { 1528 api_clear_error(&err); 1529 continue; 1530 } 1531 tv_dict_add_tv(v_event, item.key.data, item.key.size, &tv); 1532 tv_clear(&tv); 1533 } 1534 } 1535 tv_dict_set_keys_readonly(v_event); 1536 1537 aco_save_T aco; 1538 aucmd_prepbuf(&aco, buf); 1539 apply_autocmds_group(event, fname, fname_io, false, group, buf, eap, data); 1540 aucmd_restbuf(&aco); 1541 1542 restore_v_event(v_event, &save_v_event); 1543 } 1544 1545 xfree(fname); 1546 xfree(fname_io); 1547 if (data) { 1548 api_free_object(*data); 1549 xfree(data); 1550 } 1551 xfree(e); 1552 } 1553 1554 /// Execute autocommands for "event" and file name "fname". 1555 /// 1556 /// @param event event that occurred 1557 /// @param fname filename, NULL or empty means use actual file name 1558 /// @param fname_io filename to use for <afile> on cmdline 1559 /// @param force When true, ignore autocmd_busy 1560 /// @param buf Buffer for <abuf> 1561 /// 1562 /// @return true if some commands were executed. 1563 bool apply_autocmds(event_T event, char *fname, char *fname_io, bool force, buf_T *buf) 1564 { 1565 return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, NULL, NULL); 1566 } 1567 1568 /// Like apply_autocmds(), but with extra "eap" argument. This takes care of 1569 /// setting v:filearg. 1570 /// 1571 /// @param event event that occurred 1572 /// @param fname NULL or empty means use actual file name 1573 /// @param fname_io fname to use for <afile> on cmdline 1574 /// @param force When true, ignore autocmd_busy 1575 /// @param buf Buffer for <abuf> 1576 /// @param exarg Ex command arguments 1577 /// 1578 /// @return true if some commands were executed. 1579 bool apply_autocmds_exarg(event_T event, char *fname, char *fname_io, bool force, buf_T *buf, 1580 exarg_T *eap) 1581 { 1582 return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, eap, NULL); 1583 } 1584 1585 /// Like apply_autocmds(), but handles the caller's retval. If the script 1586 /// processing is being aborted or if retval is FAIL when inside a try 1587 /// conditional, no autocommands are executed. If otherwise the autocommands 1588 /// cause the script to be aborted, retval is set to FAIL. 1589 /// 1590 /// @param event event that occurred 1591 /// @param fname NULL or empty means use actual file name 1592 /// @param fname_io fname to use for <afile> on cmdline 1593 /// @param force When true, ignore autocmd_busy 1594 /// @param buf Buffer for <abuf> 1595 /// @param[in,out] retval caller's retval 1596 /// 1597 /// @return true if some autocommands were executed 1598 bool apply_autocmds_retval(event_T event, char *fname, char *fname_io, bool force, buf_T *buf, 1599 int *retval) 1600 { 1601 if (should_abort(*retval)) { 1602 return false; 1603 } 1604 1605 bool did_cmd = apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, NULL, NULL); 1606 if (did_cmd && aborting()) { 1607 *retval = FAIL; 1608 } 1609 return did_cmd; 1610 } 1611 1612 /// Return true if "event" autocommand is defined. 1613 /// 1614 /// @param event the autocommand to check 1615 bool has_event(event_T event) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT 1616 { 1617 return kv_size(autocmds[(int)event]) != 0; 1618 } 1619 1620 /// Return true when there is a CursorHold/CursorHoldI autocommand defined for 1621 /// the current mode. 1622 static bool has_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT 1623 { 1624 return has_event((get_real_state() == MODE_NORMAL_BUSY ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)); 1625 } 1626 1627 /// Return true if the CursorHold/CursorHoldI event can be triggered. 1628 bool trigger_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT 1629 { 1630 if (!did_cursorhold && has_cursorhold() && reg_recording == 0 1631 && typebuf.tb_len == 0 && !ins_compl_active()) { 1632 int state = get_real_state(); 1633 if (state == MODE_NORMAL_BUSY || (state & MODE_INSERT) != 0) { 1634 return true; 1635 } 1636 } 1637 return false; 1638 } 1639 1640 /// Execute autocommands for "event" and file name "fname". 1641 /// 1642 /// @param event event that occurred 1643 /// @param fname filename, NULL or empty means use actual file name 1644 /// @param fname_io filename to use for <afile> on cmdline, 1645 /// NULL means use `fname`. 1646 /// @param force When true, ignore autocmd_busy 1647 /// @param group autocmd group ID or AUGROUP_ALL 1648 /// @param buf Buffer for <abuf> 1649 /// @param eap Ex command arguments 1650 /// 1651 /// @return true if some commands were executed. 1652 bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force, int group, 1653 buf_T *buf, exarg_T *eap, Object *data) 1654 { 1655 char *sfname = NULL; // short file name 1656 bool retval = false; 1657 static int nesting = 0; 1658 char *save_cmdarg; 1659 static bool filechangeshell_busy = false; 1660 proftime_T wait_time; 1661 bool did_save_redobuff = false; 1662 save_redo_T save_redo; 1663 const bool save_KeyTyped = KeyTyped; 1664 ESTACK_CHECK_DECLARATION; 1665 1666 // Quickly return if there are no autocommands for this event or 1667 // autocommands are blocked. 1668 if (event == NUM_EVENTS || kv_size(autocmds[(int)event]) == 0 || is_autocmd_blocked()) { 1669 goto BYPASS_AU; 1670 } 1671 1672 // When autocommands are busy, new autocommands are only executed when 1673 // explicitly enabled with the "nested" flag. 1674 if (autocmd_busy && !(force || autocmd_nested)) { 1675 goto BYPASS_AU; 1676 } 1677 1678 // Quickly return when immediately aborting on error, or when an interrupt 1679 // occurred or an exception was thrown but not caught. 1680 if (aborting()) { 1681 goto BYPASS_AU; 1682 } 1683 1684 // FileChangedShell never nests, because it can create an endless loop. 1685 if (filechangeshell_busy 1686 && (event == EVENT_FILECHANGEDSHELL || event == EVENT_FILECHANGEDSHELLPOST)) { 1687 goto BYPASS_AU; 1688 } 1689 1690 // Ignore events in 'eventignore'. 1691 if (event_ignored(event, p_ei)) { 1692 goto BYPASS_AU; 1693 } 1694 1695 bool win_ignore = false; 1696 // If event is allowed in 'eventignorewin', check if curwin or all windows 1697 // into "buf" are ignoring the event. 1698 if (buf == curbuf && event_names[event].event <= 0) { 1699 win_ignore = event_ignored(event, curwin->w_p_eiw); 1700 } else if (buf != NULL && event_names[event].event <= 0 && buf->b_nwindows > 0) { 1701 win_ignore = true; 1702 FOR_ALL_TAB_WINDOWS(tp, wp) { 1703 if (wp->w_buffer == buf && !event_ignored(event, wp->w_p_eiw)) { 1704 win_ignore = false; 1705 break; 1706 } 1707 } 1708 } 1709 if (win_ignore) { 1710 goto BYPASS_AU; 1711 } 1712 1713 // Allow nesting of autocommands, but restrict the depth, because it's 1714 // possible to create an endless loop. 1715 if (nesting == 10) { 1716 emsg(_(e_autocommand_nesting_too_deep)); 1717 goto BYPASS_AU; 1718 } 1719 1720 // Check if these autocommands are disabled. Used when doing ":all" or 1721 // ":ball". 1722 if ((autocmd_no_enter && (event == EVENT_WINENTER || event == EVENT_BUFENTER)) 1723 || (autocmd_no_leave && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE))) { 1724 goto BYPASS_AU; 1725 } 1726 1727 // Save the autocmd_* variables and info about the current buffer. 1728 char *save_autocmd_fname = autocmd_fname; 1729 bool save_autocmd_fname_full = autocmd_fname_full; 1730 int save_autocmd_bufnr = autocmd_bufnr; 1731 char *save_autocmd_match = autocmd_match; 1732 int save_autocmd_busy = autocmd_busy; 1733 int save_autocmd_nested = autocmd_nested; 1734 bool save_changed = curbuf->b_changed; 1735 buf_T *old_curbuf = curbuf; 1736 1737 // Set the file name to be used for <afile>. 1738 // Make a copy to avoid that changing a buffer name or directory makes it 1739 // invalid. 1740 if (fname_io == NULL) { 1741 if (event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE 1742 || event == EVENT_OPTIONSET || event == EVENT_MODECHANGED 1743 || event == EVENT_MARKSET) { 1744 autocmd_fname = NULL; 1745 } else if (fname != NULL && !ends_excmd(*fname)) { 1746 autocmd_fname = fname; 1747 } else if (buf != NULL) { 1748 autocmd_fname = buf->b_ffname; 1749 } else { 1750 autocmd_fname = NULL; 1751 } 1752 } else { 1753 autocmd_fname = fname_io; 1754 } 1755 char *afile_orig = NULL; ///< Unexpanded <afile> 1756 if (autocmd_fname != NULL) { 1757 afile_orig = xstrdup(autocmd_fname); 1758 // Allocate MAXPATHL for when eval_vars() resolves the fullpath. 1759 autocmd_fname = xstrnsave(autocmd_fname, MAXPATHL); 1760 } 1761 autocmd_fname_full = false; // call FullName_save() later 1762 1763 // Set the buffer number to be used for <abuf>. 1764 autocmd_bufnr = buf == NULL ? 0 : buf->b_fnum; 1765 1766 // When the file name is NULL or empty, use the file name of buffer "buf". 1767 // Always use the full path of the file name to match with, in case 1768 // "allow_dirs" is set. 1769 if (fname == NULL || *fname == NUL) { 1770 if (buf == NULL) { 1771 fname = NULL; 1772 } else { 1773 if (event == EVENT_SYNTAX) { 1774 fname = buf->b_p_syn; 1775 } else if (event == EVENT_FILETYPE) { 1776 fname = buf->b_p_ft; 1777 } else { 1778 if (buf->b_sfname != NULL) { 1779 sfname = xstrdup(buf->b_sfname); 1780 } 1781 fname = buf->b_ffname; 1782 } 1783 } 1784 if (fname == NULL) { 1785 fname = ""; 1786 } 1787 fname = xstrdup(fname); // make a copy, so we can change it 1788 } else { 1789 sfname = xstrdup(fname); 1790 // Don't try expanding the following events. 1791 if (event == EVENT_CMDLINECHANGED 1792 || event == EVENT_CMDLINEENTER 1793 || event == EVENT_CMDLINELEAVEPRE 1794 || event == EVENT_CMDLINELEAVE 1795 || event == EVENT_CMDUNDEFINED 1796 || event == EVENT_CURSORMOVEDC 1797 || event == EVENT_CMDWINENTER 1798 || event == EVENT_CMDWINLEAVE 1799 || event == EVENT_COLORSCHEME 1800 || event == EVENT_COLORSCHEMEPRE 1801 || event == EVENT_DIRCHANGED 1802 || event == EVENT_DIRCHANGEDPRE 1803 || event == EVENT_FILETYPE 1804 || event == EVENT_FUNCUNDEFINED 1805 || event == EVENT_MARKSET 1806 || event == EVENT_MENUPOPUP 1807 || event == EVENT_MODECHANGED 1808 || event == EVENT_OPTIONSET 1809 || event == EVENT_QUICKFIXCMDPOST 1810 || event == EVENT_QUICKFIXCMDPRE 1811 || event == EVENT_REMOTEREPLY 1812 || event == EVENT_SIGNAL 1813 || event == EVENT_SPELLFILEMISSING 1814 || event == EVENT_SYNTAX 1815 || event == EVENT_TABCLOSED 1816 || event == EVENT_USER 1817 || event == EVENT_WINCLOSED 1818 || event == EVENT_WINRESIZED 1819 || event == EVENT_WINSCROLLED) { 1820 fname = xstrdup(fname); 1821 autocmd_fname_full = true; // don't expand it later 1822 } else { 1823 fname = FullName_save(fname, false); 1824 } 1825 } 1826 if (fname == NULL) { // out of memory 1827 xfree(sfname); 1828 retval = false; 1829 goto BYPASS_AU; 1830 } 1831 1832 #ifdef BACKSLASH_IN_FILENAME 1833 // Replace all backslashes with forward slashes. This makes the 1834 // autocommand patterns portable between Unix and Windows. 1835 if (sfname != NULL) { 1836 forward_slash(sfname); 1837 } 1838 forward_slash(fname); 1839 #endif 1840 1841 // Set the name to be used for <amatch>. 1842 autocmd_match = fname; 1843 1844 // Don't redraw while doing autocommands. 1845 RedrawingDisabled++; 1846 1847 // name and lnum are filled in later 1848 estack_push(ETYPE_AUCMD, NULL, 0); 1849 ESTACK_CHECK_SETUP; 1850 1851 const sctx_T save_current_sctx = current_sctx; 1852 1853 if (do_profiling == PROF_YES) { 1854 prof_child_enter(&wait_time); // doesn't count for the caller itself 1855 } 1856 1857 // Don't use local function variables, if called from a function. 1858 funccal_entry_T funccal_entry; 1859 save_funccal(&funccal_entry); 1860 1861 // When starting to execute autocommands, save the search patterns. 1862 if (!autocmd_busy) { 1863 save_search_patterns(); 1864 if (!ins_compl_active()) { 1865 saveRedobuff(&save_redo); 1866 did_save_redobuff = true; 1867 } 1868 curbuf->b_did_filetype = curbuf->b_keep_filetype; 1869 } 1870 1871 // Note that we are applying autocmds. Some commands need to know. 1872 autocmd_busy = true; 1873 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL); 1874 nesting++; // see matching decrement below 1875 1876 // Remember that FileType was triggered. Used for did_filetype(). 1877 if (event == EVENT_FILETYPE) { 1878 curbuf->b_did_filetype = true; 1879 } 1880 1881 char *tail = path_tail(fname); 1882 1883 // Find first autocommand that matches 1884 AutoPatCmd patcmd = { 1885 // aucmd_next will set lastpat back to NULL if there are no more autocommands left to run 1886 .lastpat = NULL, 1887 // current autocommand index 1888 .auidx = 0, 1889 // save vector size, to avoid an endless loop when more patterns 1890 // are added when executing autocommands 1891 .ausize = kv_size(autocmds[(int)event]), 1892 .afile_orig = afile_orig, 1893 .fname = fname, 1894 .sfname = sfname, 1895 .tail = tail, 1896 .group = group, 1897 .event = event, 1898 .arg_bufnr = autocmd_bufnr, 1899 }; 1900 aucmd_next(&patcmd); 1901 1902 // Found first autocommand, start executing them 1903 if (patcmd.lastpat != NULL) { 1904 // add to active_apc_list 1905 patcmd.next = active_apc_list; 1906 active_apc_list = &patcmd; 1907 1908 // Attach data to command 1909 patcmd.data = data; 1910 1911 // set v:cmdarg (only when there is a matching pattern) 1912 varnumber_T save_cmdbang = get_vim_var_nr(VV_CMDBANG); 1913 if (eap != NULL) { 1914 save_cmdarg = set_cmdarg(eap, NULL); 1915 set_vim_var_nr(VV_CMDBANG, eap->forceit); 1916 } else { 1917 save_cmdarg = NULL; // avoid gcc warning 1918 } 1919 retval = true; 1920 1921 // Make sure cursor and topline are valid. The first time the current 1922 // values are saved, restored by reset_lnums(). When nested only the 1923 // values are corrected when needed. 1924 if (nesting == 1) { 1925 check_lnums(true); 1926 } else { 1927 check_lnums_nested(true); 1928 } 1929 1930 const int save_did_emsg = did_emsg; 1931 const bool save_ex_pressedreturn = get_pressedreturn(); 1932 1933 // Execute the autocmd. The `getnextac` callback handles iteration. 1934 do_cmdline(NULL, getnextac, &patcmd, DOCMD_NOWAIT | DOCMD_VERBOSE | DOCMD_REPEAT); 1935 1936 did_emsg += save_did_emsg; 1937 set_pressedreturn(save_ex_pressedreturn); 1938 1939 if (nesting == 1) { 1940 // restore cursor and topline, unless they were changed 1941 reset_lnums(); 1942 } 1943 1944 if (eap != NULL) { 1945 set_cmdarg(NULL, save_cmdarg); 1946 set_vim_var_nr(VV_CMDBANG, save_cmdbang); 1947 } 1948 // delete from active_apc_list 1949 if (active_apc_list == &patcmd) { // just in case 1950 active_apc_list = patcmd.next; 1951 } 1952 } 1953 1954 RedrawingDisabled--; 1955 autocmd_busy = save_autocmd_busy; 1956 filechangeshell_busy = false; 1957 autocmd_nested = save_autocmd_nested; 1958 xfree(SOURCING_NAME); 1959 ESTACK_CHECK_NOW; 1960 estack_pop(); 1961 xfree(afile_orig); 1962 xfree(autocmd_fname); 1963 autocmd_fname = save_autocmd_fname; 1964 autocmd_fname_full = save_autocmd_fname_full; 1965 autocmd_bufnr = save_autocmd_bufnr; 1966 autocmd_match = save_autocmd_match; 1967 current_sctx = save_current_sctx; 1968 restore_funccal(); 1969 if (do_profiling == PROF_YES) { 1970 prof_child_exit(&wait_time); 1971 } 1972 KeyTyped = save_KeyTyped; 1973 xfree(fname); 1974 xfree(sfname); 1975 nesting--; // see matching increment above 1976 1977 // When stopping to execute autocommands, restore the search patterns and 1978 // the redo buffer. Free any buffers in the au_pending_free_buf list and 1979 // free any windows in the au_pending_free_win list. 1980 if (!autocmd_busy) { 1981 restore_search_patterns(); 1982 if (did_save_redobuff) { 1983 restoreRedobuff(&save_redo); 1984 } 1985 curbuf->b_did_filetype = false; 1986 while (au_pending_free_buf != NULL) { 1987 buf_T *b = au_pending_free_buf->b_next; 1988 1989 xfree(au_pending_free_buf); 1990 au_pending_free_buf = b; 1991 } 1992 while (au_pending_free_win != NULL) { 1993 win_T *w = au_pending_free_win->w_next; 1994 1995 xfree(au_pending_free_win); 1996 au_pending_free_win = w; 1997 } 1998 } 1999 2000 // Some events don't set or reset the Changed flag. 2001 // Check if still in the same buffer! 2002 if (curbuf == old_curbuf 2003 && (event == EVENT_BUFREADPOST || event == EVENT_BUFWRITEPOST 2004 || event == EVENT_FILEAPPENDPOST || event == EVENT_VIMLEAVE 2005 || event == EVENT_VIMLEAVEPRE)) { 2006 if (curbuf->b_changed != save_changed) { 2007 need_maketitle = true; 2008 } 2009 curbuf->b_changed = save_changed; 2010 } 2011 2012 au_cleanup(); // may really delete removed patterns/commands now 2013 2014 BYPASS_AU: 2015 // When wiping out a buffer make sure all its buffer-local autocommands 2016 // are deleted. 2017 if (event == EVENT_BUFWIPEOUT && buf != NULL) { 2018 aubuflocal_remove(buf); 2019 } 2020 2021 if (retval == OK && event == EVENT_FILETYPE) { 2022 curbuf->b_au_did_filetype = true; 2023 } 2024 2025 return retval; 2026 } 2027 2028 void do_termresponse_autocmd(const String sequence) 2029 { 2030 MAXSIZE_TEMP_DICT(data, 1); 2031 PUT_C(data, "sequence", STRING_OBJ(sequence)); 2032 apply_autocmds_group(EVENT_TERMRESPONSE, NULL, NULL, true, AUGROUP_ALL, NULL, NULL, 2033 &DICT_OBJ(data)); 2034 termresponse_changed = true; 2035 } 2036 2037 // Block triggering autocommands until unblock_autocmd() is called. 2038 // Can be used recursively, so long as it's symmetric. 2039 void block_autocmds(void) 2040 { 2041 // Detect if v:termresponse is set while blocked. 2042 if (!is_autocmd_blocked()) { 2043 termresponse_changed = false; 2044 } 2045 autocmd_blocked++; 2046 } 2047 2048 void unblock_autocmds(void) 2049 { 2050 autocmd_blocked--; 2051 2052 // When v:termresponse was set while autocommands were blocked, trigger 2053 // the autocommands now. Esp. useful when executing a shell command 2054 // during startup (nvim -d). 2055 if (!is_autocmd_blocked() && termresponse_changed && has_event(EVENT_TERMRESPONSE)) { 2056 // Copied to a new allocation, as termresponse may be freed during the event. 2057 const String sequence = cstr_to_string(get_vim_var_str(VV_TERMRESPONSE)); 2058 do_termresponse_autocmd(sequence); 2059 api_free_string(sequence); 2060 } 2061 } 2062 2063 bool is_autocmd_blocked(void) 2064 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT 2065 { 2066 return autocmd_blocked != 0; 2067 } 2068 2069 /// Find next matching autocommand. 2070 /// If next autocommand was not found, sets lastpat to NULL and cmdidx to SIZE_MAX on apc. 2071 static void aucmd_next(AutoPatCmd *apc) 2072 { 2073 estack_T *const entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1; 2074 2075 AutoCmdVec *const acs = &autocmds[(int)apc->event]; 2076 assert(apc->ausize <= kv_size(*acs)); 2077 for (size_t i = apc->auidx; i < apc->ausize && !got_int; i++) { 2078 AutoCmd *const ac = &kv_A(*acs, i); 2079 AutoPat *const ap = ac->pat; 2080 2081 // Skip deleted autocommands. 2082 if (ap == NULL) { 2083 continue; 2084 } 2085 // Skip matching if pattern didn't change. 2086 if (ap != apc->lastpat) { 2087 // Skip autocommands that don't match the group. 2088 if (apc->group != AUGROUP_ALL && apc->group != ap->group) { 2089 continue; 2090 } 2091 // Skip autocommands that don't match the pattern or buffer number. 2092 if (ap->buflocal_nr == 0 2093 ? !match_file_pat(NULL, &ap->reg_prog, apc->fname, apc->sfname, apc->tail, ap->allow_dirs) 2094 : ap->buflocal_nr != apc->arg_bufnr) { 2095 continue; 2096 } 2097 2098 const char *const name = event_nr2name(apc->event); 2099 const char *const s = _("%s Autocommands for \"%s\""); 2100 2101 const size_t sourcing_name_len = strlen(s) + strlen(name) + (size_t)ap->patlen + 1; 2102 char *const namep = xmalloc(sourcing_name_len); 2103 snprintf(namep, sourcing_name_len, s, name, ap->pat); 2104 if (p_verbose >= 8) { 2105 verbose_enter(); 2106 smsg(0, _("Executing %s"), namep); 2107 verbose_leave(); 2108 } 2109 2110 // Update the exestack entry for this autocmd. 2111 XFREE_CLEAR(entry->es_name); 2112 entry->es_name = namep; 2113 entry->es_info.aucmd = apc; 2114 } 2115 2116 apc->lastpat = ap; 2117 apc->auidx = i; 2118 2119 line_breakcheck(); 2120 return; 2121 } 2122 2123 // Clear the exestack entry for this ETYPE_AUCMD entry. 2124 XFREE_CLEAR(entry->es_name); 2125 entry->es_info.aucmd = NULL; 2126 2127 apc->lastpat = NULL; 2128 apc->auidx = SIZE_MAX; 2129 } 2130 2131 /// Executes an autocmd callback function (as opposed to an Ex command). 2132 static bool au_callback(const AutoCmd *ac, const AutoPatCmd *apc) 2133 { 2134 Callback callback = ac->handler_fn; 2135 if (callback.type == kCallbackLua) { 2136 MAXSIZE_TEMP_DICT(data, 7); 2137 PUT_C(data, "id", INTEGER_OBJ(ac->id)); 2138 PUT_C(data, "event", CSTR_AS_OBJ(event_nr2name(apc->event))); 2139 PUT_C(data, "file", CSTR_AS_OBJ(apc->afile_orig)); 2140 PUT_C(data, "match", CSTR_AS_OBJ(autocmd_match)); 2141 PUT_C(data, "buf", INTEGER_OBJ(autocmd_bufnr)); 2142 2143 if (apc->data) { 2144 PUT_C(data, "data", *apc->data); 2145 } 2146 2147 int group = ac->pat->group; 2148 switch (group) { 2149 case AUGROUP_ERROR: 2150 abort(); // unreachable 2151 case AUGROUP_DEFAULT: 2152 case AUGROUP_ALL: 2153 case AUGROUP_DELETED: 2154 // omit group in these cases 2155 break; 2156 default: 2157 PUT_C(data, "group", INTEGER_OBJ(group)); 2158 break; 2159 } 2160 2161 MAXSIZE_TEMP_ARRAY(args, 1); 2162 ADD_C(args, DICT_OBJ(data)); 2163 2164 Object result = nlua_call_ref(callback.data.luaref, NULL, args, kRetNilBool, NULL, NULL); 2165 return LUARET_TRUTHY(result); 2166 } else { 2167 typval_T argsin = TV_INITIAL_VALUE; 2168 typval_T rettv = TV_INITIAL_VALUE; 2169 callback_call(&callback, 0, &argsin, &rettv); 2170 return false; 2171 } 2172 } 2173 2174 /// Get next autocommand command. 2175 /// Called by do_cmdline() to get the next line for ":if". 2176 /// @return allocated string, or NULL for end of autocommands. 2177 char *getnextac(int c, void *cookie, int indent, bool do_concat) 2178 { 2179 // These arguments are required for do_cmdline. 2180 (void)c; 2181 (void)indent; 2182 (void)do_concat; 2183 2184 AutoPatCmd *const apc = (AutoPatCmd *)cookie; 2185 AutoCmdVec *const acs = &autocmds[(int)apc->event]; 2186 2187 aucmd_next(apc); 2188 if (apc->lastpat == NULL) { 2189 return NULL; 2190 } 2191 2192 assert(apc->auidx < kv_size(*acs)); 2193 AutoCmd *const ac = &kv_A(*acs, apc->auidx); 2194 assert(ac->pat != NULL); 2195 bool oneshot = ac->once; 2196 2197 if (p_verbose >= 9) { 2198 verbose_enter_scroll(); 2199 char *handler_str = aucmd_handler_to_string(ac); 2200 smsg(0, _("autocommand %s"), handler_str); 2201 msg_puts("\n"); // don't overwrite this either 2202 XFREE_CLEAR(handler_str); 2203 verbose_leave_scroll(); 2204 } 2205 2206 // Make sure to set autocmd_nested before executing 2207 // lua code, so that it works properly 2208 autocmd_nested = ac->nested; 2209 current_sctx = ac->script_ctx; 2210 apc->script_ctx = current_sctx; 2211 2212 char *retval; 2213 if (ac->handler_cmd) { 2214 retval = xstrdup(ac->handler_cmd); 2215 } else { 2216 AutoCmd ac_copy = *ac; 2217 // Mark oneshot handler as "removed" now, to prevent recursion by e.g. `:doautocmd`. #25526 2218 ac->pat = oneshot ? NULL : ac->pat; 2219 // May reallocate `acs` kvec_t data and invalidate the `ac` pointer. 2220 bool rv = au_callback(&ac_copy, apc); 2221 if (oneshot) { 2222 // Restore `pat`. Use `acs` because `ac` may have been invalidated by the callback. 2223 kv_A(*acs, apc->auidx).pat = ac_copy.pat; 2224 } 2225 // If an autocommand callback returns true, delete the autocommand 2226 oneshot = oneshot || rv; 2227 2228 // HACK(tjdevries): 2229 // We just return "not-null" and continue going. 2230 // This would be a good candidate for a refactor. You would need to refactor: 2231 // 1. do_cmdline to accept something besides a string 2232 // OR 2233 // 2. make where we call do_cmdline for autocmds not have to return anything, 2234 // and instead we loop over all the matches and just execute one-by-one. 2235 // However, my expectation would be that could be expensive. 2236 retval = xcalloc(1, 1); 2237 } 2238 2239 // Remove one-shot ("once") autocmd in anticipation of its execution. 2240 if (oneshot) { 2241 aucmd_del(&kv_A(*acs, apc->auidx)); 2242 } 2243 2244 if (apc->auidx < apc->ausize) { 2245 apc->auidx++; 2246 } else { 2247 apc->auidx = SIZE_MAX; 2248 } 2249 2250 return retval; 2251 } 2252 2253 /// Return true if there is a matching autocommand for "fname". 2254 /// To account for buffer-local autocommands, function needs to know 2255 /// in which buffer the file will be opened. 2256 /// 2257 /// @param event event that occurred. 2258 /// @param sfname filename the event occurred in. 2259 /// @param buf buffer the file is open in 2260 bool has_autocmd(event_T event, char *sfname, buf_T *buf) 2261 FUNC_ATTR_WARN_UNUSED_RESULT 2262 { 2263 char *tail = path_tail(sfname); 2264 bool retval = false; 2265 2266 char *fname = FullName_save(sfname, false); 2267 if (fname == NULL) { 2268 return false; 2269 } 2270 2271 #ifdef BACKSLASH_IN_FILENAME 2272 // Replace all backslashes with forward slashes. This makes the 2273 // autocommand patterns portable between Unix and Windows. 2274 sfname = xstrdup(sfname); 2275 forward_slash(sfname); 2276 forward_slash(fname); 2277 #endif 2278 2279 AutoCmdVec *const acs = &autocmds[(int)event]; 2280 for (size_t i = 0; i < kv_size(*acs); i++) { 2281 AutoPat *const ap = kv_A(*acs, i).pat; 2282 if (ap != NULL 2283 && (ap->buflocal_nr == 0 2284 ? match_file_pat(NULL, &ap->reg_prog, fname, sfname, tail, ap->allow_dirs) 2285 : buf != NULL && ap->buflocal_nr == buf->b_fnum)) { 2286 retval = true; 2287 break; 2288 } 2289 } 2290 2291 xfree(fname); 2292 #ifdef BACKSLASH_IN_FILENAME 2293 xfree(sfname); 2294 #endif 2295 2296 return retval; 2297 } 2298 2299 // Function given to ExpandGeneric() to obtain the list of autocommand group names. 2300 char *expand_get_augroup_name(expand_T *xp, int idx) 2301 { 2302 (void)xp; // Required for ExpandGeneric 2303 return augroup_name(idx + 1); 2304 } 2305 2306 /// @param doautocmd true for :doauto*, false for :autocmd 2307 char *set_context_in_autocmd(expand_T *xp, char *arg, bool doautocmd) 2308 { 2309 // check for a group name, skip it if present 2310 autocmd_include_groups = false; 2311 char *p = arg; 2312 int group = arg_augroup_get(&arg); 2313 2314 // If there only is a group name that's what we expand. 2315 if (*arg == NUL && group != AUGROUP_ALL && !ascii_iswhite(arg[-1])) { 2316 arg = p; 2317 group = AUGROUP_ALL; 2318 } 2319 2320 // skip over event name 2321 for (p = arg; *p != NUL && !ascii_iswhite(*p); p++) { 2322 if (*p == ',') { 2323 arg = p + 1; 2324 } 2325 } 2326 if (*p == NUL) { 2327 if (group == AUGROUP_ALL) { 2328 autocmd_include_groups = true; 2329 } 2330 xp->xp_context = EXPAND_EVENTS; // expand event name 2331 xp->xp_pattern = arg; 2332 return NULL; 2333 } 2334 2335 // skip over pattern 2336 arg = skipwhite(p); 2337 while (*arg && (!ascii_iswhite(*arg) || arg[-1] == '\\')) { 2338 arg++; 2339 } 2340 if (*arg) { 2341 return arg; // expand (next) command 2342 } 2343 2344 if (doautocmd) { 2345 xp->xp_context = EXPAND_FILES; // expand file names 2346 } else { 2347 xp->xp_context = EXPAND_NOTHING; // pattern is not expanded 2348 } 2349 return NULL; 2350 } 2351 2352 /// Function given to ExpandGeneric() to obtain the list of event names. 2353 char *expand_get_event_name(expand_T *xp, int idx) 2354 { 2355 (void)xp; // xp is a required parameter to be used with ExpandGeneric 2356 2357 // List group names 2358 char *name = augroup_name(idx + 1); 2359 if (name != NULL) { 2360 // skip when not including groups or skip deleted entries 2361 if (!autocmd_include_groups || name == get_deleted_augroup()) { 2362 return ""; 2363 } 2364 2365 return name; 2366 } 2367 2368 int i = idx - next_augroup_id; 2369 if (i < 0 || i >= NUM_EVENTS) { 2370 return NULL; 2371 } 2372 2373 // List event names 2374 return event_names[i].name; 2375 } 2376 2377 /// Function given to ExpandGeneric() to obtain the list of event names. Don't 2378 /// include groups. 2379 char *get_event_name_no_group(expand_T *xp FUNC_ATTR_UNUSED, int idx, bool win) 2380 { 2381 if (idx < 0 || idx >= NUM_EVENTS) { 2382 return NULL; 2383 } 2384 2385 if (!win) { 2386 return event_names[idx].name; 2387 } 2388 2389 // Need to check subset of allowed values for 'eventignorewin'. 2390 int j = 0; 2391 for (int i = 0; i < NUM_EVENTS; i++) { 2392 j += event_names[i].event <= 0; 2393 if (j == idx + 1) { 2394 return event_names[i].name; 2395 } 2396 } 2397 return NULL; 2398 } 2399 2400 /// Check whether given autocommand is supported 2401 /// 2402 /// @param[in] event Event to check. 2403 /// 2404 /// @return True if it is, false otherwise. 2405 bool autocmd_supported(const char *const event) 2406 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT 2407 { 2408 char *p; 2409 return event_name2nr(event, &p) != NUM_EVENTS; 2410 } 2411 2412 /// Return true if an autocommand is defined for a group, event and 2413 /// pattern: The group can be omitted to accept any group. 2414 /// `event` and `pattern` can be omitted to accept any event and pattern. 2415 /// Buffer-local patterns <buffer> or <buffer=N> are accepted. 2416 /// Used for: 2417 /// exists("#Group") or 2418 /// exists("#Group#Event") or 2419 /// exists("#Group#Event#pat") or 2420 /// exists("#Event") or 2421 /// exists("#Event#pat") 2422 /// 2423 /// @param arg autocommand string 2424 bool au_exists(const char *const arg) 2425 FUNC_ATTR_WARN_UNUSED_RESULT 2426 { 2427 buf_T *buflocal_buf = NULL; 2428 bool retval = false; 2429 2430 // Make a copy so that we can change the '#' chars to a NUL. 2431 char *const arg_save = xstrdup(arg); 2432 char *p = strchr(arg_save, '#'); 2433 if (p != NULL) { 2434 *p++ = NUL; 2435 } 2436 2437 // First, look for an autocmd group name. 2438 int group = augroup_find(arg_save); 2439 char *event_name; 2440 if (group == AUGROUP_ERROR) { 2441 // Didn't match a group name, assume the first argument is an event. 2442 group = AUGROUP_ALL; 2443 event_name = arg_save; 2444 } else { 2445 if (p == NULL) { 2446 // "Group": group name is present and it's recognized 2447 retval = true; 2448 goto theend; 2449 } 2450 2451 // Must be "Group#Event" or "Group#Event#pat". 2452 event_name = p; 2453 p = strchr(event_name, '#'); 2454 if (p != NULL) { 2455 *p++ = NUL; // "Group#Event#pat" 2456 } 2457 } 2458 2459 char *pattern = p; // "pattern" is NULL when there is no pattern. 2460 2461 // Find the index (enum) for the event name. 2462 event_T event = event_name2nr(event_name, &p); 2463 2464 // return false if the event name is not recognized 2465 if (event == NUM_EVENTS) { 2466 goto theend; 2467 } 2468 2469 // Find the first autocommand for this event. 2470 // If there isn't any, return false; 2471 // If there is one and no pattern given, return true; 2472 AutoCmdVec *const acs = &autocmds[(int)event]; 2473 if (kv_size(*acs) == 0) { 2474 goto theend; 2475 } 2476 2477 // if pattern is "<buffer>", special handling is needed which uses curbuf 2478 // for pattern "<buffer=N>, path_fnamecmp() will work fine 2479 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0) { 2480 buflocal_buf = curbuf; 2481 } 2482 2483 // Check if there is an autocommand with the given pattern. 2484 for (size_t i = 0; i < kv_size(*acs); i++) { 2485 AutoPat *const ap = kv_A(*acs, i).pat; 2486 // Only use a pattern when it has not been removed. 2487 // For buffer-local autocommands, path_fnamecmp() works fine. 2488 if (ap != NULL 2489 && (group == AUGROUP_ALL || ap->group == group) 2490 && (pattern == NULL 2491 || (buflocal_buf == NULL 2492 ? path_fnamecmp(ap->pat, pattern) == 0 2493 : ap->buflocal_nr == buflocal_buf->b_fnum))) { 2494 retval = true; 2495 break; 2496 } 2497 } 2498 2499 theend: 2500 xfree(arg_save); 2501 return retval; 2502 } 2503 2504 // Checks if a pattern is buflocal 2505 bool aupat_is_buflocal(const char *pat, int patlen) 2506 FUNC_ATTR_PURE 2507 { 2508 return patlen >= 8 && strncmp(pat, "<buffer", 7) == 0 && (pat)[patlen - 1] == '>'; 2509 } 2510 2511 int aupat_get_buflocal_nr(const char *pat, int patlen) 2512 { 2513 assert(aupat_is_buflocal(pat, patlen)); 2514 2515 // "<buffer>" 2516 if (patlen == 8) { 2517 return curbuf->b_fnum; 2518 } 2519 2520 if (patlen > 9 && (pat)[7] == '=') { 2521 // "<buffer=abuf>" 2522 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13) == 0) { 2523 return autocmd_bufnr; 2524 } 2525 2526 // "<buffer=123>" 2527 if (skipdigits(pat + 8) == pat + patlen - 1) { 2528 return atoi(pat + 8); 2529 } 2530 } 2531 2532 return 0; 2533 } 2534 2535 // normalize buffer pattern 2536 void aupat_normalize_buflocal_pat(char *dest, const char *pat, int patlen, int buflocal_nr) 2537 { 2538 assert(aupat_is_buflocal(pat, patlen)); 2539 2540 if (buflocal_nr == 0) { 2541 buflocal_nr = curbuf->handle; 2542 } 2543 2544 // normalize pat into standard "<buffer>#N" form 2545 snprintf(dest, BUFLOCAL_PAT_LEN, "<buffer=%d>", buflocal_nr); 2546 } 2547 2548 int autocmd_delete_event(int group, event_T event, const char *pat) 2549 FUNC_ATTR_NONNULL_ALL 2550 { 2551 return do_autocmd_event(event, pat, false, false, "", true, group); 2552 } 2553 2554 /// Deletes an autocmd by ID. 2555 /// Only autocmds created via the API have IDs associated with them. There 2556 /// is no way to delete a specific autocmd created via :autocmd 2557 bool autocmd_delete_id(int64_t id) 2558 { 2559 assert(id > 0); 2560 bool success = false; 2561 2562 // Note that since multiple AutoCmd objects can have the same ID, we need to do a full scan. 2563 FOR_ALL_AUEVENTS(event) { 2564 AutoCmdVec *const acs = &autocmds[(int)event]; 2565 for (size_t i = 0; i < kv_size(*acs); i++) { 2566 AutoCmd *const ac = &kv_A(*acs, i); 2567 if (ac->id == id) { 2568 aucmd_del(ac); 2569 success = true; 2570 } 2571 } 2572 } 2573 return success; 2574 } 2575 2576 /// Gets an (allocated) string representation of an autocmd command/callback. 2577 char *aucmd_handler_to_string(AutoCmd *ac) 2578 FUNC_ATTR_PURE 2579 { 2580 if (ac->handler_cmd) { 2581 return xstrdup(ac->handler_cmd); 2582 } 2583 return callback_to_string(&ac->handler_fn, NULL); 2584 } 2585 2586 // Arg Parsing Functions 2587 2588 /// Scan over the events. "*" stands for all events. 2589 /// true when group name was found 2590 static char *arg_event_skip(char *arg, bool have_group) 2591 { 2592 char *pat; 2593 char *p; 2594 2595 if (*arg == '*') { 2596 if (arg[1] && !ascii_iswhite(arg[1])) { 2597 semsg(_("E215: Illegal character after *: %s"), arg); 2598 return NULL; 2599 } 2600 pat = arg + 1; 2601 } else { 2602 for (pat = arg; *pat && *pat != '|' && !ascii_iswhite(*pat); pat = p) { 2603 if ((int)event_name2nr(pat, &p) >= NUM_EVENTS) { 2604 if (have_group) { 2605 semsg(_("E216: No such event: %s"), pat); 2606 } else { 2607 semsg(_("E216: No such group or event: %s"), pat); 2608 } 2609 return NULL; 2610 } 2611 } 2612 } 2613 return pat; 2614 } 2615 2616 // Find the group ID in a ":autocmd" or ":doautocmd" argument. 2617 // The "argp" argument is advanced to the following argument. 2618 // 2619 // Returns the group ID or AUGROUP_ALL. 2620 static int arg_augroup_get(char **argp) 2621 { 2622 char *p; 2623 char *arg = *argp; 2624 2625 for (p = arg; *p && !ascii_iswhite(*p) && *p != '|'; p++) {} 2626 if (p <= arg) { 2627 return AUGROUP_ALL; 2628 } 2629 2630 char *group_name = xmemdupz(arg, (size_t)(p - arg)); 2631 int group = augroup_find(group_name); 2632 if (group == AUGROUP_ERROR) { 2633 group = AUGROUP_ALL; // no match, use all groups 2634 } else { 2635 *argp = skipwhite(p); // match, skip over group name 2636 } 2637 xfree(group_name); 2638 return group; 2639 } 2640 2641 /// Handles grabbing arguments from `:autocmd` such as ++once and ++nested 2642 static bool arg_autocmd_flag_get(bool *flag, char **cmd_ptr, char *pattern, int len) 2643 { 2644 if (strncmp(*cmd_ptr, pattern, (size_t)len) == 0 && ascii_iswhite((*cmd_ptr)[len])) { 2645 if (*flag) { 2646 semsg(_(e_duparg2), pattern); 2647 return true; 2648 } 2649 2650 *flag = true; 2651 *cmd_ptr = skipwhite(*cmd_ptr + len); 2652 } 2653 2654 return false; 2655 } 2656 2657 /// When kFalse: VimSuspend should be triggered next. 2658 /// When kTrue: VimResume should be triggered next. 2659 /// When kNone: Currently triggering VimSuspend or VimResume. 2660 static TriState pending_vimresume = kFalse; 2661 2662 static void vimresume_event(void **argv) 2663 { 2664 apply_autocmds(EVENT_VIMRESUME, NULL, NULL, false, NULL); 2665 pending_vimresume = kFalse; 2666 } 2667 2668 /// Trigger VimSuspend or VimResume autocommand. 2669 void may_trigger_vim_suspend_resume(bool suspend) 2670 { 2671 if (suspend && pending_vimresume == kFalse) { 2672 pending_vimresume = kNone; 2673 apply_autocmds(EVENT_VIMSUSPEND, NULL, NULL, false, NULL); 2674 pending_vimresume = kTrue; 2675 } else if (!suspend && pending_vimresume == kTrue) { 2676 pending_vimresume = kNone; 2677 multiqueue_put(main_loop.events, vimresume_event, NULL); 2678 } 2679 } 2680 2681 // UI Enter 2682 void do_autocmd_uienter(uint64_t chanid, bool attached) 2683 { 2684 static bool recursive = false; 2685 2686 #ifdef EXITFREE 2687 if (entered_free_all_mem) { 2688 return; 2689 } 2690 #endif 2691 if (starting == NO_SCREEN) { 2692 return; // user config hasn't been sourced yet 2693 } 2694 if (recursive) { 2695 return; // disallow recursion 2696 } 2697 recursive = true; 2698 2699 save_v_event_T save_v_event; 2700 dict_T *dict = get_v_event(&save_v_event); 2701 assert(chanid < VARNUMBER_MAX); 2702 tv_dict_add_nr(dict, S_LEN("chan"), (varnumber_T)chanid); 2703 tv_dict_set_keys_readonly(dict); 2704 apply_autocmds(attached ? EVENT_UIENTER : EVENT_UILEAVE, NULL, NULL, false, curbuf); 2705 restore_v_event(dict, &save_v_event); 2706 2707 recursive = false; 2708 } 2709 2710 // FocusGained 2711 2712 void do_autocmd_focusgained(bool gained) 2713 { 2714 static bool recursive = false; 2715 static Timestamp last_time = 0; 2716 2717 if (recursive) { 2718 return; // disallow recursion 2719 } 2720 recursive = true; 2721 apply_autocmds((gained ? EVENT_FOCUSGAINED : EVENT_FOCUSLOST), NULL, NULL, false, curbuf); 2722 2723 // When activated: Check if any file was modified outside of Vim. 2724 // Only do this when not done within the last two seconds as: 2725 // 1. Some filesystems have modification time granularity in seconds. Fat32 2726 // has a granularity of 2 seconds. 2727 // 2. We could get multiple notifications in a row. 2728 if (gained && last_time + (Timestamp)2000 < os_now()) { 2729 check_timestamps(true); 2730 last_time = os_now(); 2731 } 2732 2733 recursive = false; 2734 } 2735 2736 void do_filetype_autocmd(buf_T *buf, bool force) 2737 { 2738 static int ft_recursive = 0; 2739 2740 if (ft_recursive > 0 && !force) { 2741 return; // disallow recursion 2742 } 2743 2744 int secure_save = secure; 2745 2746 // Reset the secure flag, since the value of 'filetype' has 2747 // been checked to be safe. 2748 secure = 0; 2749 2750 ft_recursive++; 2751 buf->b_did_filetype = true; 2752 // Only pass true for "force" when it is true or 2753 // used recursively, to avoid endless recurrence. 2754 apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname, force || ft_recursive == 1, buf); 2755 ft_recursive--; 2756 2757 secure = secure_save; 2758 }