ex_cmds2.c (25540B)
1 /// @file ex_cmds2.c 2 /// 3 /// Some more functions for command line commands 4 5 #include <assert.h> 6 #include <inttypes.h> 7 #include <stdbool.h> 8 #include <stdio.h> 9 #include <string.h> 10 11 #include "nvim/arglist.h" 12 #include "nvim/ascii_defs.h" 13 #include "nvim/autocmd.h" 14 #include "nvim/autocmd_defs.h" 15 #include "nvim/buffer.h" 16 #include "nvim/buffer_defs.h" 17 #include "nvim/bufwrite.h" 18 #include "nvim/change.h" 19 #include "nvim/channel.h" 20 #include "nvim/errors.h" 21 #include "nvim/eval.h" 22 #include "nvim/eval/typval.h" 23 #include "nvim/eval/typval_defs.h" 24 #include "nvim/eval/vars.h" 25 #include "nvim/ex_cmds.h" 26 #include "nvim/ex_cmds2.h" 27 #include "nvim/ex_cmds_defs.h" 28 #include "nvim/ex_docmd.h" 29 #include "nvim/ex_getln.h" 30 #include "nvim/fileio.h" 31 #include "nvim/gettext_defs.h" 32 #include "nvim/globals.h" 33 #include "nvim/highlight_defs.h" 34 #include "nvim/macros_defs.h" 35 #include "nvim/mark.h" 36 #include "nvim/memline_defs.h" 37 #include "nvim/memory.h" 38 #include "nvim/message.h" 39 #include "nvim/move.h" 40 #include "nvim/normal.h" 41 #include "nvim/option_vars.h" 42 #include "nvim/os/os_defs.h" 43 #include "nvim/path.h" 44 #include "nvim/pos_defs.h" 45 #include "nvim/quickfix.h" 46 #include "nvim/runtime.h" 47 #include "nvim/types_defs.h" 48 #include "nvim/undo.h" 49 #include "nvim/vim_defs.h" 50 #include "nvim/window.h" 51 52 #include "ex_cmds2.c.generated.h" 53 54 static const char e_compiler_not_supported_str[] 55 = N_("E666: Compiler not supported: %s"); 56 57 void ex_ruby(exarg_T *eap) 58 { 59 script_host_execute("ruby", eap); 60 } 61 62 void ex_rubyfile(exarg_T *eap) 63 { 64 script_host_execute_file("ruby", eap); 65 } 66 67 void ex_rubydo(exarg_T *eap) 68 { 69 script_host_do_range("ruby", eap); 70 } 71 72 void ex_python3(exarg_T *eap) 73 { 74 script_host_execute("python3", eap); 75 } 76 77 void ex_py3file(exarg_T *eap) 78 { 79 script_host_execute_file("python3", eap); 80 } 81 82 void ex_pydo3(exarg_T *eap) 83 { 84 script_host_do_range("python3", eap); 85 } 86 87 void ex_perl(exarg_T *eap) 88 { 89 script_host_execute("perl", eap); 90 } 91 92 void ex_perlfile(exarg_T *eap) 93 { 94 script_host_execute_file("perl", eap); 95 } 96 97 void ex_perldo(exarg_T *eap) 98 { 99 script_host_do_range("perl", eap); 100 } 101 102 /// If 'autowrite' option set, try to write the file. 103 /// Careful: autocommands may make "buf" invalid! 104 /// 105 /// @return FAIL for failure, OK otherwise 106 int autowrite(buf_T *buf, bool forceit) 107 { 108 bufref_T bufref; 109 110 if (!(p_aw || p_awa) || !p_write 111 // never autowrite a "nofile" or "nowrite" buffer 112 || bt_dontwrite(buf) 113 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL) { 114 return FAIL; 115 } 116 set_bufref(&bufref, buf); 117 int r = buf_write_all(buf, forceit); 118 119 // Writing may succeed but the buffer still changed, e.g., when there is a 120 // conversion error. We do want to return FAIL then. 121 if (bufref_valid(&bufref) && bufIsChanged(buf)) { 122 r = FAIL; 123 } 124 return r; 125 } 126 127 /// Flush all buffers, except the ones that are readonly or are never written. 128 void autowrite_all(void) 129 { 130 if (!(p_aw || p_awa) || !p_write) { 131 return; 132 } 133 134 FOR_ALL_BUFFERS(buf) { 135 if (bufIsChanged(buf) && !buf->b_p_ro && !bt_dontwrite(buf)) { 136 bufref_T bufref; 137 set_bufref(&bufref, buf); 138 buf_write_all(buf, false); 139 // an autocommand may have deleted the buffer 140 if (!bufref_valid(&bufref)) { 141 buf = firstbuf; 142 } 143 } 144 } 145 } 146 147 /// @return true if buffer was changed and cannot be abandoned. 148 /// For flags use the CCGD_ values. 149 bool check_changed(buf_T *buf, int flags) 150 { 151 bool forceit = (flags & CCGD_FORCEIT); 152 bufref_T bufref; 153 set_bufref(&bufref, buf); 154 155 if (!forceit 156 && bufIsChanged(buf) 157 && ((flags & CCGD_MULTWIN) || buf->b_nwindows <= 1) 158 && (!(flags & CCGD_AW) || autowrite(buf, forceit) == FAIL)) { 159 if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write) { 160 int count = 0; 161 162 if (flags & CCGD_ALLBUF) { 163 FOR_ALL_BUFFERS(buf2) { 164 if (bufIsChanged(buf2) && (buf2->b_ffname != NULL)) { 165 count++; 166 } 167 } 168 } 169 if (!bufref_valid(&bufref)) { 170 // Autocommand deleted buffer, oops! It's not changed now. 171 return false; 172 } 173 dialog_changed(buf, count > 1); 174 if (!bufref_valid(&bufref)) { 175 // Autocommand deleted buffer, oops! It's not changed now. 176 return false; 177 } 178 return bufIsChanged(buf); 179 } 180 if (flags & CCGD_EXCMD) { 181 no_write_message(); 182 } else { 183 no_write_message_nobang(curbuf); 184 } 185 return true; 186 } 187 return false; 188 } 189 190 /// Ask the user what to do when abandoning a changed buffer. 191 /// Must check 'write' option first! 192 /// 193 /// @param buf 194 /// @param checkall may abandon all changed buffers 195 void dialog_changed(buf_T *buf, bool checkall) 196 { 197 char buff[DIALOG_MSG_SIZE]; 198 int ret; 199 // Init ea pseudo-structure, this is needed for the check_overwrite() 200 // function. 201 exarg_T ea = { 202 .append = false, 203 .forceit = false, 204 }; 205 206 dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname); 207 if (checkall) { 208 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1); 209 } else { 210 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1); 211 } 212 213 if (ret == VIM_YES) { 214 bool empty_bufname = buf->b_fname == NULL; 215 if (empty_bufname) { 216 buf_set_name(buf->b_fnum, "Untitled"); 217 } 218 219 if (check_overwrite(&ea, buf, buf->b_fname, buf->b_ffname, false) == OK) { 220 // didn't hit Cancel 221 if (buf_write_all(buf, false) == OK) { 222 return; 223 } 224 } 225 226 // restore to empty when write failed 227 if (empty_bufname) { 228 buf->b_fname = NULL; 229 XFREE_CLEAR(buf->b_ffname); 230 XFREE_CLEAR(buf->b_sfname); 231 unchanged(buf, true, false); 232 } 233 } else if (ret == VIM_NO) { 234 unchanged(buf, true, false); 235 } else if (ret == VIM_ALL) { 236 // Write all modified files that can be written. 237 // Skip readonly buffers, these need to be confirmed 238 // individually. 239 FOR_ALL_BUFFERS(buf2) { 240 if (bufIsChanged(buf2) && (buf2->b_ffname != NULL) && !buf2->b_p_ro) { 241 bufref_T bufref; 242 set_bufref(&bufref, buf2); 243 244 if (buf2->b_fname != NULL 245 && check_overwrite(&ea, buf2, buf2->b_fname, buf2->b_ffname, false) == OK) { 246 // didn't hit Cancel 247 buf_write_all(buf2, false); 248 } 249 // an autocommand may have deleted the buffer 250 if (!bufref_valid(&bufref)) { 251 buf2 = firstbuf; 252 } 253 } 254 } 255 } else if (ret == VIM_DISCARDALL) { 256 // mark all buffers as unchanged 257 FOR_ALL_BUFFERS(buf2) { 258 unchanged(buf2, true, false); 259 } 260 } 261 } 262 263 /// Ask the user whether to close the terminal buffer or not. 264 /// 265 /// @param buf The terminal buffer. 266 /// @return bool Whether to close the buffer or not. 267 bool dialog_close_terminal(buf_T *buf) 268 { 269 char buff[DIALOG_MSG_SIZE]; 270 271 dialog_msg(buff, _("Close \"%s\"?"), 272 (buf->b_fname != NULL) ? buf->b_fname : "?"); 273 274 int ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1); 275 276 return ret == VIM_YES; 277 } 278 279 /// @return true if the buffer "buf" can be abandoned, either by making it 280 /// hidden, autowriting it or unloading it. 281 bool can_abandon(buf_T *buf, bool forceit) 282 { 283 return buf_hide(buf) 284 || !bufIsChanged(buf) 285 || buf->b_nwindows > 1 286 || autowrite(buf, forceit) == OK 287 || forceit; 288 } 289 290 /// Add a buffer number to "bufnrs", unless it's already there. 291 static void add_bufnum(int *bufnrs, int *bufnump, int nr) 292 { 293 for (int i = 0; i < *bufnump; i++) { 294 if (bufnrs[i] == nr) { 295 return; 296 } 297 } 298 bufnrs[*bufnump] = nr; 299 *bufnump = *bufnump + 1; 300 } 301 302 /// Check if any buffer was changed and cannot be abandoned. 303 /// That changed buffer becomes the current buffer. 304 /// When "unload" is true the current buffer is unloaded instead of making it 305 /// hidden. This is used for ":q!". 306 /// 307 /// @param[in] hidden specifies whether to check only hidden buffers. 308 /// @param[in] unload specifies whether to unload, instead of hide, the buffer. 309 /// 310 /// @returns true if any buffer is changed and cannot be abandoned 311 bool check_changed_any(bool hidden, bool unload) 312 { 313 bool ret = false; 314 int i; 315 int bufnum = 0; 316 size_t bufcount = 0; 317 318 // Make a list of all buffers, with the most important ones first. 319 FOR_ALL_BUFFERS(buf) { 320 bufcount++; 321 } 322 323 if (bufcount == 0) { 324 return false; 325 } 326 327 int *bufnrs = xmalloc(sizeof(*bufnrs) * bufcount); 328 329 // curbuf 330 bufnrs[bufnum++] = curbuf->b_fnum; 331 332 // buffers in current tab 333 FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { 334 if (wp->w_buffer != curbuf) { 335 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum); 336 } 337 } 338 339 // buffers in other tabs 340 FOR_ALL_TABS(tp) { 341 if (tp != curtab) { 342 FOR_ALL_WINDOWS_IN_TAB(wp, tp) { 343 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum); 344 } 345 } 346 } 347 348 // any other buffer 349 FOR_ALL_BUFFERS(buf) { 350 add_bufnum(bufnrs, &bufnum, buf->b_fnum); 351 } 352 353 buf_T *buf = NULL; 354 for (i = 0; i < bufnum; i++) { 355 buf = buflist_findnr(bufnrs[i]); 356 if (buf == NULL) { 357 continue; 358 } 359 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf)) { 360 bufref_T bufref; 361 set_bufref(&bufref, buf); 362 363 // Try auto-writing the buffer. If this fails but the buffer no 364 // longer exists it's not changed, that's OK. 365 if (check_changed(buf, (p_awa ? CCGD_AW : 0) 366 | CCGD_MULTWIN 367 | CCGD_ALLBUF) && bufref_valid(&bufref)) { 368 break; // didn't save - still changes 369 } 370 } 371 } 372 373 if (i >= bufnum) { 374 goto theend; 375 } 376 377 // Get here if "buf" cannot be abandoned. 378 ret = true; 379 exiting = false; 380 // When ":confirm" used, don't give an error message. 381 if (!(p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM))) { 382 // There must be a wait_return() for this message, do_buffer() 383 // may cause a redraw. But wait_return() is a no-op when vgetc() 384 // is busy (Quit used from window menu), then make sure we don't 385 // cause a scroll up. 386 if (vgetc_busy > 0) { 387 msg_row = cmdline_row; 388 msg_col = 0; 389 msg_didout = false; 390 } 391 if (((buf->terminal && channel_job_running((uint64_t)buf->b_p_channel)) 392 ? semsg(_("E947: Job still running in buffer \"%s\""), buf->b_fname) 393 : semsg(_("E162: No write since last change for buffer \"%s\""), 394 buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname)) 395 // Only makes sense if error is shown, which cause_errthrow() may prevent. 396 && msg_didany) { 397 int save = no_wait_return; 398 no_wait_return = false; 399 wait_return(false); 400 no_wait_return = save; 401 } 402 } 403 404 // Try to find a window that contains the buffer. 405 if (buf != curbuf) { 406 FOR_ALL_TAB_WINDOWS(tp, wp) { 407 if (wp->w_buffer == buf) { 408 bufref_T bufref; 409 set_bufref(&bufref, buf); 410 goto_tabpage_win(tp, wp); 411 // Paranoia: did autocmds wipe out the buffer with changes? 412 if (!bufref_valid(&bufref)) { 413 goto theend; 414 } 415 goto buf_found; 416 } 417 } 418 } 419 buf_found: 420 421 // Open the changed buffer in the current window. 422 if (buf != curbuf) { 423 set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO, true); 424 } 425 426 theend: 427 xfree(bufnrs); 428 return ret; 429 } 430 431 /// @return FAIL if there is no file name, OK if there is one. 432 /// Give error message for FAIL. 433 int check_fname(void) 434 { 435 if (curbuf->b_ffname == NULL) { 436 emsg(_(e_noname)); 437 return FAIL; 438 } 439 return OK; 440 } 441 442 /// Flush the contents of a buffer, unless it has no file name. 443 /// 444 /// @return FAIL for failure, OK otherwise 445 int buf_write_all(buf_T *buf, bool forceit) 446 { 447 buf_T *old_curbuf = curbuf; 448 449 int retval = (buf_write(buf, buf->b_ffname, buf->b_fname, 450 1, buf->b_ml.ml_line_count, NULL, 451 false, forceit, true, false)); 452 if (curbuf != old_curbuf) { 453 msg_source(HLF_W); 454 msg(_("Warning: Entered other buffer unexpectedly (check autocommands)"), 0); 455 } 456 return retval; 457 } 458 459 /// ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo" 460 void ex_listdo(exarg_T *eap) 461 { 462 if (curwin->w_p_wfb) { 463 if ((eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) && !eap->forceit) { 464 // Disallow :ldo if 'winfixbuf' is applied 465 emsg(_(e_winfixbuf_cannot_go_to_buffer)); 466 return; 467 } 468 469 if (win_valid(prevwin) && !prevwin->w_p_wfb) { 470 // 'winfixbuf' is set; attempt to change to a window without it. 471 win_goto(prevwin); 472 } 473 if (curwin->w_p_wfb) { 474 // Split the window, which will be 'nowinfixbuf', and set curwin to that 475 (void)win_split(0, 0); 476 477 if (curwin->w_p_wfb) { 478 // Autocommands set 'winfixbuf' or sent us to another window 479 // with it set, or we failed to split the window. Give up. 480 emsg(_(e_winfixbuf_cannot_go_to_buffer)); 481 return; 482 } 483 } 484 } 485 486 char *save_ei = NULL; 487 488 // Temporarily override SHM_OVER and SHM_OVERALL to avoid that file 489 // message overwrites output from the command. 490 msg_listdo_overwrite++; 491 492 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo) { 493 // Don't do syntax HL autocommands. Skipping the syntax file is a 494 // great speed improvement. 495 save_ei = au_event_disable(",Syntax"); 496 497 FOR_ALL_BUFFERS(buf) { 498 buf->b_flags &= ~BF_SYN_SET; 499 } 500 } 501 502 if (eap->cmdidx == CMD_windo 503 || eap->cmdidx == CMD_tabdo 504 || buf_hide(curbuf) 505 || !check_changed(curbuf, CCGD_AW 506 | (eap->forceit ? CCGD_FORCEIT : 0) 507 | CCGD_EXCMD)) { 508 int next_fnum = 0; 509 int i = 0; 510 // start at the eap->line1 argument/window/buffer 511 win_T *wp = firstwin; 512 tabpage_T *tp = first_tabpage; 513 switch (eap->cmdidx) { 514 case CMD_windo: 515 for (; wp != NULL && i + 1 < eap->line1; wp = wp->w_next) { 516 i++; 517 } 518 break; 519 case CMD_tabdo: 520 for (; tp != NULL && i + 1 < eap->line1; tp = tp->tp_next) { 521 i++; 522 } 523 break; 524 case CMD_argdo: 525 i = (int)eap->line1 - 1; 526 break; 527 default: 528 break; 529 } 530 531 buf_T *buf = curbuf; 532 size_t qf_size = 0; 533 534 // set pcmark now 535 if (eap->cmdidx == CMD_bufdo) { 536 // Advance to the first listed buffer after "eap->line1". 537 for (buf = firstbuf; 538 buf != NULL && (buf->b_fnum < eap->line1 || !buf->b_p_bl); 539 buf = buf->b_next) { 540 if (buf->b_fnum > eap->line2) { 541 buf = NULL; 542 break; 543 } 544 } 545 if (buf != NULL) { 546 goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum); 547 } 548 } else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo 549 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) { 550 qf_size = qf_get_valid_size(eap); 551 assert(eap->line1 >= 0); 552 if (qf_size == 0 || (size_t)eap->line1 > qf_size) { 553 buf = NULL; 554 } else { 555 ex_cc(eap); 556 557 buf = curbuf; 558 i = (int)eap->line1 - 1; 559 if (eap->addr_count <= 0) { 560 // Default to all quickfix/location list entries. 561 assert(qf_size < MAXLNUM); 562 eap->line2 = (linenr_T)qf_size; 563 } 564 } 565 } else { 566 setpcmark(); 567 } 568 listcmd_busy = true; // avoids setting pcmark below 569 570 while (!got_int && buf != NULL) { 571 bool execute = true; 572 if (eap->cmdidx == CMD_argdo) { 573 // go to argument "i" 574 if (i == ARGCOUNT) { 575 break; 576 } 577 // Don't call do_argfile() when already there, it will try 578 // reloading the file. 579 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin)) { 580 // Clear 'shm' to avoid that the file message overwrites 581 // any output from the command. 582 do_argfile(eap, i); 583 } 584 if (curwin->w_arg_idx != i) { 585 break; 586 } 587 } else if (eap->cmdidx == CMD_windo) { 588 // go to window "wp" 589 if (!win_valid(wp)) { 590 break; 591 } 592 assert(wp); 593 execute = !wp->w_floating || (!wp->w_config.hide && wp->w_config.focusable); 594 if (execute) { 595 win_goto(wp); 596 if (curwin != wp) { 597 break; // something must be wrong 598 } 599 } 600 wp = wp->w_next; 601 } else if (eap->cmdidx == CMD_tabdo) { 602 // go to window "tp" 603 if (!valid_tabpage(tp)) { 604 break; 605 } 606 assert(tp); 607 goto_tabpage_tp(tp, true, true); 608 tp = tp->tp_next; 609 } else if (eap->cmdidx == CMD_bufdo) { 610 // Remember the number of the next listed buffer, in case 611 // ":bwipe" is used or autocommands do something strange. 612 next_fnum = -1; 613 for (buf_T *bp = curbuf->b_next; bp != NULL; bp = bp->b_next) { 614 if (bp->b_p_bl) { 615 next_fnum = bp->b_fnum; 616 break; 617 } 618 } 619 } 620 621 i++; 622 // execute the command 623 if (execute) { 624 do_cmdline(eap->arg, eap->ea_getline, eap->cookie, DOCMD_VERBOSE + DOCMD_NOWAIT); 625 } 626 627 if (eap->cmdidx == CMD_bufdo) { 628 // Done? 629 if (next_fnum < 0 || next_fnum > eap->line2) { 630 break; 631 } 632 633 // Check if the buffer still exists. 634 bool buf_still_exists = false; 635 FOR_ALL_BUFFERS(bp) { 636 if (bp->b_fnum == next_fnum) { 637 buf_still_exists = true; 638 break; 639 } 640 } 641 if (!buf_still_exists) { 642 break; 643 } 644 645 // Go to the next buffer. 646 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum); 647 648 // If autocommands took us elsewhere, quit here. 649 if (curbuf->b_fnum != next_fnum) { 650 break; 651 } 652 } 653 654 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo 655 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) { 656 assert(i >= 0); 657 if ((size_t)i >= qf_size || i >= eap->line2) { 658 break; 659 } 660 661 size_t qf_idx = qf_get_cur_idx(eap); 662 663 ex_cnext(eap); 664 665 // If jumping to the next quickfix entry fails, quit here. 666 if (qf_get_cur_idx(eap) == qf_idx) { 667 break; 668 } 669 } 670 671 if (eap->cmdidx == CMD_windo && execute) { 672 validate_cursor(curwin); // cursor may have moved 673 // required when 'scrollbind' has been set 674 if (curwin->w_p_scb) { 675 do_check_scrollbind(true); 676 } 677 } 678 if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo) { 679 if (i + 1 > eap->line2) { 680 break; 681 } 682 } 683 if (eap->cmdidx == CMD_argdo && i >= eap->line2) { 684 break; 685 } 686 } 687 listcmd_busy = false; 688 } 689 690 msg_listdo_overwrite--; 691 if (save_ei != NULL) { 692 buf_T *bnext; 693 aco_save_T aco; 694 695 au_event_restore(save_ei); 696 697 for (buf_T *buf = firstbuf; buf != NULL; buf = bnext) { 698 bnext = buf->b_next; 699 if (buf->b_nwindows > 0 && (buf->b_flags & BF_SYN_SET)) { 700 buf->b_flags &= ~BF_SYN_SET; 701 702 // buffer was opened while Syntax autocommands were disabled, 703 // need to trigger them now. 704 if (buf == curbuf) { 705 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname, true, 706 curbuf); 707 } else { 708 aucmd_prepbuf(&aco, buf); 709 apply_autocmds(EVENT_SYNTAX, buf->b_p_syn, buf->b_fname, true, buf); 710 aucmd_restbuf(&aco); 711 } 712 713 // start over, in case autocommands messed things up. 714 bnext = firstbuf; 715 } 716 } 717 } 718 } 719 720 /// ":compiler[!] {name}" 721 void ex_compiler(exarg_T *eap) 722 { 723 char *old_cur_comp = NULL; 724 725 if (*eap->arg == NUL) { 726 // List all compiler scripts. 727 do_cmdline_cmd("echo globpath(&rtp, 'compiler/*.vim')"); // NOLINT 728 do_cmdline_cmd("echo globpath(&rtp, 'compiler/*.lua')"); // NOLINT 729 return; 730 } 731 732 size_t bufsize = strlen(eap->arg) + 14; 733 char *buf = xmalloc(bufsize); 734 735 if (eap->forceit) { 736 // ":compiler! {name}" sets global options 737 do_cmdline_cmd("command -nargs=* -keepscript CompilerSet set <args>"); 738 } else { 739 // ":compiler! {name}" sets local options. 740 // To remain backwards compatible "current_compiler" is always 741 // used. A user's compiler plugin may set it, the distributed 742 // plugin will then skip the settings. Afterwards set 743 // "b:current_compiler" and restore "current_compiler". 744 // Explicitly prepend "g:" to make it work in a function. 745 old_cur_comp = get_var_value("g:current_compiler"); 746 if (old_cur_comp != NULL) { 747 old_cur_comp = xstrdup(old_cur_comp); 748 } 749 do_cmdline_cmd("command -nargs=* -keepscript CompilerSet setlocal <args>"); 750 } 751 do_unlet(S_LEN("g:current_compiler"), true); 752 do_unlet(S_LEN("b:current_compiler"), true); 753 754 snprintf(buf, bufsize, "compiler/%s.*", eap->arg); 755 if (source_runtime_vim_lua(buf, DIP_ALL) == FAIL) { 756 semsg(_(e_compiler_not_supported_str), eap->arg); 757 } 758 xfree(buf); 759 760 do_cmdline_cmd(":delcommand CompilerSet"); 761 762 // Set "b:current_compiler" from "current_compiler". 763 char *p = get_var_value("g:current_compiler"); 764 if (p != NULL) { 765 set_internal_string_var("b:current_compiler", p); 766 } 767 768 // Restore "current_compiler" for ":compiler {name}". 769 if (!eap->forceit) { 770 if (old_cur_comp != NULL) { 771 set_internal_string_var("g:current_compiler", old_cur_comp); 772 xfree(old_cur_comp); 773 } else { 774 do_unlet(S_LEN("g:current_compiler"), true); 775 } 776 } 777 } 778 779 /// ":checktime [buffer]" 780 void ex_checktime(exarg_T *eap) 781 { 782 int save_no_check_timestamps = no_check_timestamps; 783 784 no_check_timestamps = 0; 785 if (eap->addr_count == 0) { // default is all buffers 786 check_timestamps(false); 787 } else { 788 buf_T *buf = buflist_findnr((int)eap->line2); 789 if (buf != NULL) { // cannot happen? 790 buf_check_timestamp(buf); 791 } 792 } 793 no_check_timestamps = save_no_check_timestamps; 794 } 795 796 static void script_host_execute(char *name, exarg_T *eap) 797 { 798 size_t len; 799 char *const script = script_get(eap, &len); 800 801 if (script != NULL) { 802 list_T *const args = tv_list_alloc(3); 803 // script 804 tv_list_append_allocated_string(args, script); 805 // current range 806 tv_list_append_number(args, (int)eap->line1); 807 tv_list_append_number(args, (int)eap->line2); 808 809 eval_call_provider(name, "execute", args, true); 810 } 811 } 812 813 static void script_host_execute_file(char *name, exarg_T *eap) 814 { 815 if (!eap->skip) { 816 uint8_t buffer[MAXPATHL]; 817 vim_FullName(eap->arg, (char *)buffer, sizeof(buffer), false); 818 819 list_T *args = tv_list_alloc(3); 820 // filename 821 tv_list_append_string(args, (const char *)buffer, -1); 822 // current range 823 tv_list_append_number(args, (int)eap->line1); 824 tv_list_append_number(args, (int)eap->line2); 825 eval_call_provider(name, "execute_file", args, true); 826 } 827 } 828 829 static void script_host_do_range(char *name, exarg_T *eap) 830 { 831 if (!eap->skip) { 832 list_T *args = tv_list_alloc(3); 833 tv_list_append_number(args, (int)eap->line1); 834 tv_list_append_number(args, (int)eap->line2); 835 tv_list_append_string(args, eap->arg, -1); 836 eval_call_provider(name, "do_range", args, true); 837 } 838 } 839 840 /// ":drop" 841 /// Opens the first argument in a window, and the argument list is redefined. 842 void ex_drop(exarg_T *eap) 843 { 844 bool split = false; 845 846 // Check if the first argument is already being edited in a window. If 847 // so, jump to that window. 848 // We would actually need to check all arguments, but that's complicated 849 // and mostly only one file is dropped. 850 // This also ignores wildcards, since it is very unlikely the user is 851 // editing a file name with a wildcard character. 852 set_arglist(eap->arg); 853 854 // Expanding wildcards may result in an empty argument list. E.g. when 855 // editing "foo.pyc" and ".pyc" is in 'wildignore'. Assume that we 856 // already did an error message for this. 857 if (ARGCOUNT == 0) { 858 return; 859 } 860 861 if (cmdmod.cmod_tab) { 862 // ":tab drop file ...": open a tab for each argument that isn't 863 // edited in a window yet. It's like ":tab all" but without closing 864 // windows or tabs. 865 ex_all(eap); 866 cmdmod.cmod_tab = 0; 867 ex_rewind(eap); 868 return; 869 } 870 871 // ":drop file ...": Edit the first argument. Jump to an existing 872 // window if possible, edit in current window if the current buffer 873 // can be abandoned, otherwise open a new window. 874 buf_T *buf = buflist_findnr(ARGLIST[0].ae_fnum); 875 876 FOR_ALL_TAB_WINDOWS(tp, wp) { 877 if (wp->w_buffer == buf) { 878 goto_tabpage_win(tp, wp); 879 curwin->w_arg_idx = 0; 880 if (!bufIsChanged(curbuf)) { 881 const int save_ar = curbuf->b_p_ar; 882 883 // reload the file if it is newer 884 curbuf->b_p_ar = true; 885 buf_check_timestamp(curbuf); 886 curbuf->b_p_ar = save_ar; 887 } 888 if (curbuf->b_ml.ml_flags & ML_EMPTY) { 889 ex_rewind(eap); 890 } 891 892 // execute [+cmd] 893 if (eap->do_ecmd_cmd) { 894 bool did_set_swapcommand = set_swapcommand(eap->do_ecmd_cmd, 0); 895 do_cmdline(eap->do_ecmd_cmd, NULL, NULL, DOCMD_VERBOSE); 896 if (did_set_swapcommand) { 897 set_vim_var_string(VV_SWAPCOMMAND, NULL, -1); 898 } 899 } 900 901 // no need to execute [++opts] - they only apply for newly loaded buffers. 902 return; 903 } 904 } 905 906 // Check whether the current buffer is changed. If so, we will need 907 // to split the current window or data could be lost. 908 // Skip the check if the 'hidden' option is set, as in this case the 909 // buffer won't be lost. 910 if (!buf_hide(curbuf)) { 911 emsg_off++; 912 split = check_changed(curbuf, CCGD_AW | CCGD_EXCMD); 913 emsg_off--; 914 } 915 916 // Fake a ":sfirst" or ":first" command edit the first argument. 917 if (split) { 918 eap->cmdidx = CMD_sfirst; 919 eap->cmd[0] = 's'; 920 } else { 921 eap->cmdidx = CMD_first; 922 } 923 ex_rewind(eap); 924 }