1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * cmdexpand.c: functions for command-line completion 12 */ 13 14 #include "vim.h" 15 16 static int cmd_showtail; // Only show path tail in lists ? 17 18 static void set_expand_context(expand_T *xp); 19 static int ExpandGeneric(expand_T *xp, regmatch_T *regmatch, 20 int *num_file, char_u ***file, 21 char_u *((*func)(expand_T *, int)), int escaped); 22 static int ExpandFromContext(expand_T *xp, char_u *, int *, char_u ***, int); 23 static int expand_showtail(expand_T *xp); 24 static int expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int flagsarg); 25 #if defined(FEAT_EVAL) 26 static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file); 27 static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file); 28 #endif 29 30 static int 31 sort_func_compare(const void *s1, const void *s2) 32 { 33 char_u *p1 = *(char_u **)s1; 34 char_u *p2 = *(char_u **)s2; 35 36 if (*p1 != '<' && *p2 == '<') return -1; 37 if (*p1 == '<' && *p2 != '<') return 1; 38 return STRCMP(p1, p2); 39 } 40 41 static void 42 ExpandEscape( 43 expand_T *xp, 44 char_u *str, 45 int numfiles, 46 char_u **files, 47 int options) 48 { 49 int i; 50 char_u *p; 51 52 // May change home directory back to "~" 53 if (options & WILD_HOME_REPLACE) 54 tilde_replace(str, numfiles, files); 55 56 if (options & WILD_ESCAPE) 57 { 58 if (xp->xp_context == EXPAND_FILES 59 || xp->xp_context == EXPAND_FILES_IN_PATH 60 || xp->xp_context == EXPAND_SHELLCMD 61 || xp->xp_context == EXPAND_BUFFERS 62 || xp->xp_context == EXPAND_DIRECTORIES) 63 { 64 // Insert a backslash into a file name before a space, \, %, # 65 // and wildmatch characters, except '~'. 66 for (i = 0; i < numfiles; ++i) 67 { 68 // for ":set path=" we need to escape spaces twice 69 if (xp->xp_backslash == XP_BS_THREE) 70 { 71 p = vim_strsave_escaped(files[i], (char_u *)" "); 72 if (p != NULL) 73 { 74 vim_free(files[i]); 75 files[i] = p; 76 #if defined(BACKSLASH_IN_FILENAME) 77 p = vim_strsave_escaped(files[i], (char_u *)" "); 78 if (p != NULL) 79 { 80 vim_free(files[i]); 81 files[i] = p; 82 } 83 #endif 84 } 85 } 86 #ifdef BACKSLASH_IN_FILENAME 87 p = vim_strsave_fnameescape(files[i], FALSE); 88 #else 89 p = vim_strsave_fnameescape(files[i], xp->xp_shell); 90 #endif 91 if (p != NULL) 92 { 93 vim_free(files[i]); 94 files[i] = p; 95 } 96 97 // If 'str' starts with "\~", replace "~" at start of 98 // files[i] with "\~". 99 if (str[0] == '\\' && str[1] == '~' && files[i][0] == '~') 100 escape_fname(&files[i]); 101 } 102 xp->xp_backslash = XP_BS_NONE; 103 104 // If the first file starts with a '+' escape it. Otherwise it 105 // could be seen as "+cmd". 106 if (*files[0] == '+') 107 escape_fname(&files[0]); 108 } 109 else if (xp->xp_context == EXPAND_TAGS) 110 { 111 // Insert a backslash before characters in a tag name that 112 // would terminate the ":tag" command. 113 for (i = 0; i < numfiles; ++i) 114 { 115 p = vim_strsave_escaped(files[i], (char_u *)"\\|\""); 116 if (p != NULL) 117 { 118 vim_free(files[i]); 119 files[i] = p; 120 } 121 } 122 } 123 } 124 } 125 126 /* 127 * Return FAIL if this is not an appropriate context in which to do 128 * completion of anything, return OK if it is (even if there are no matches). 129 * For the caller, this means that the character is just passed through like a 130 * normal character (instead of being expanded). This allows :s/^I^D etc. 131 */ 132 int 133 nextwild( 134 expand_T *xp, 135 int type, 136 int options, // extra options for ExpandOne() 137 int escape) // if TRUE, escape the returned matches 138 { 139 cmdline_info_T *ccline = get_cmdline_info(); 140 int i, j; 141 char_u *p1; 142 char_u *p2; 143 int difflen; 144 int v; 145 146 if (xp->xp_numfiles == -1) 147 { 148 set_expand_context(xp); 149 cmd_showtail = expand_showtail(xp); 150 } 151 152 if (xp->xp_context == EXPAND_UNSUCCESSFUL) 153 { 154 beep_flush(); 155 return OK; // Something illegal on command line 156 } 157 if (xp->xp_context == EXPAND_NOTHING) 158 { 159 // Caller can use the character as a normal char instead 160 return FAIL; 161 } 162 163 msg_puts("..."); // show that we are busy 164 out_flush(); 165 166 i = (int)(xp->xp_pattern - ccline->cmdbuff); 167 xp->xp_pattern_len = ccline->cmdpos - i; 168 169 if (type == WILD_NEXT || type == WILD_PREV) 170 { 171 // Get next/previous match for a previous expanded pattern. 172 p2 = ExpandOne(xp, NULL, NULL, 0, type); 173 } 174 else 175 { 176 // Translate string into pattern and expand it. 177 if ((p1 = addstar(xp->xp_pattern, xp->xp_pattern_len, 178 xp->xp_context)) == NULL) 179 p2 = NULL; 180 else 181 { 182 int use_options = options | 183 WILD_HOME_REPLACE|WILD_ADD_SLASH|WILD_SILENT; 184 if (escape) 185 use_options |= WILD_ESCAPE; 186 187 if (p_wic) 188 use_options += WILD_ICASE; 189 p2 = ExpandOne(xp, p1, 190 vim_strnsave(&ccline->cmdbuff[i], xp->xp_pattern_len), 191 use_options, type); 192 vim_free(p1); 193 // longest match: make sure it is not shorter, happens with :help 194 if (p2 != NULL && type == WILD_LONGEST) 195 { 196 for (j = 0; j < xp->xp_pattern_len; ++j) 197 if (ccline->cmdbuff[i + j] == '*' 198 || ccline->cmdbuff[i + j] == '?') 199 break; 200 if ((int)STRLEN(p2) < j) 201 VIM_CLEAR(p2); 202 } 203 } 204 } 205 206 if (p2 != NULL && !got_int) 207 { 208 difflen = (int)STRLEN(p2) - xp->xp_pattern_len; 209 if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen) 210 { 211 v = realloc_cmdbuff(ccline->cmdlen + difflen + 4); 212 xp->xp_pattern = ccline->cmdbuff + i; 213 } 214 else 215 v = OK; 216 if (v == OK) 217 { 218 mch_memmove(&ccline->cmdbuff[ccline->cmdpos + difflen], 219 &ccline->cmdbuff[ccline->cmdpos], 220 (size_t)(ccline->cmdlen - ccline->cmdpos + 1)); 221 mch_memmove(&ccline->cmdbuff[i], p2, STRLEN(p2)); 222 ccline->cmdlen += difflen; 223 ccline->cmdpos += difflen; 224 } 225 } 226 vim_free(p2); 227 228 redrawcmd(); 229 cursorcmd(); 230 231 // When expanding a ":map" command and no matches are found, assume that 232 // the key is supposed to be inserted literally 233 if (xp->xp_context == EXPAND_MAPPINGS && p2 == NULL) 234 return FAIL; 235 236 if (xp->xp_numfiles <= 0 && p2 == NULL) 237 beep_flush(); 238 else if (xp->xp_numfiles == 1) 239 // free expanded pattern 240 (void)ExpandOne(xp, NULL, NULL, 0, WILD_FREE); 241 242 return OK; 243 } 244 245 /* 246 * Do wildcard expansion on the string 'str'. 247 * Chars that should not be expanded must be preceded with a backslash. 248 * Return a pointer to allocated memory containing the new string. 249 * Return NULL for failure. 250 * 251 * "orig" is the originally expanded string, copied to allocated memory. It 252 * should either be kept in orig_save or freed. When "mode" is WILD_NEXT or 253 * WILD_PREV "orig" should be NULL. 254 * 255 * Results are cached in xp->xp_files and xp->xp_numfiles, except when "mode" 256 * is WILD_EXPAND_FREE or WILD_ALL. 257 * 258 * mode = WILD_FREE: just free previously expanded matches 259 * mode = WILD_EXPAND_FREE: normal expansion, do not keep matches 260 * mode = WILD_EXPAND_KEEP: normal expansion, keep matches 261 * mode = WILD_NEXT: use next match in multiple match, wrap to first 262 * mode = WILD_PREV: use previous match in multiple match, wrap to first 263 * mode = WILD_ALL: return all matches concatenated 264 * mode = WILD_LONGEST: return longest matched part 265 * mode = WILD_ALL_KEEP: get all matches, keep matches 266 * 267 * options = WILD_LIST_NOTFOUND: list entries without a match 268 * options = WILD_HOME_REPLACE: do home_replace() for buffer names 269 * options = WILD_USE_NL: Use '\n' for WILD_ALL 270 * options = WILD_NO_BEEP: Don't beep for multiple matches 271 * options = WILD_ADD_SLASH: add a slash after directory names 272 * options = WILD_KEEP_ALL: don't remove 'wildignore' entries 273 * options = WILD_SILENT: don't print warning messages 274 * options = WILD_ESCAPE: put backslash before special chars 275 * options = WILD_ICASE: ignore case for files 276 * options = WILD_ALLLINKS; keep broken links 277 * 278 * The variables xp->xp_context and xp->xp_backslash must have been set! 279 */ 280 char_u * 281 ExpandOne( 282 expand_T *xp, 283 char_u *str, 284 char_u *orig, // allocated copy of original of expanded string 285 int options, 286 int mode) 287 { 288 char_u *ss = NULL; 289 static int findex; 290 static char_u *orig_save = NULL; // kept value of orig 291 int orig_saved = FALSE; 292 int i; 293 long_u len; 294 int non_suf_match; // number without matching suffix 295 296 // first handle the case of using an old match 297 if (mode == WILD_NEXT || mode == WILD_PREV) 298 { 299 if (xp->xp_numfiles > 0) 300 { 301 if (mode == WILD_PREV) 302 { 303 if (findex == -1) 304 findex = xp->xp_numfiles; 305 --findex; 306 } 307 else // mode == WILD_NEXT 308 ++findex; 309 310 // When wrapping around, return the original string, set findex to 311 // -1. 312 if (findex < 0) 313 { 314 if (orig_save == NULL) 315 findex = xp->xp_numfiles - 1; 316 else 317 findex = -1; 318 } 319 if (findex >= xp->xp_numfiles) 320 { 321 if (orig_save == NULL) 322 findex = 0; 323 else 324 findex = -1; 325 } 326 #ifdef FEAT_WILDMENU 327 if (p_wmnu) 328 win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files, 329 findex, cmd_showtail); 330 #endif 331 if (findex == -1) 332 return vim_strsave(orig_save); 333 return vim_strsave(xp->xp_files[findex]); 334 } 335 else 336 return NULL; 337 } 338 339 // free old names 340 if (xp->xp_numfiles != -1 && mode != WILD_ALL && mode != WILD_LONGEST) 341 { 342 FreeWild(xp->xp_numfiles, xp->xp_files); 343 xp->xp_numfiles = -1; 344 VIM_CLEAR(orig_save); 345 } 346 findex = 0; 347 348 if (mode == WILD_FREE) // only release file name 349 return NULL; 350 351 if (xp->xp_numfiles == -1) 352 { 353 vim_free(orig_save); 354 orig_save = orig; 355 orig_saved = TRUE; 356 357 // Do the expansion. 358 if (ExpandFromContext(xp, str, &xp->xp_numfiles, &xp->xp_files, 359 options) == FAIL) 360 { 361 #ifdef FNAME_ILLEGAL 362 // Illegal file name has been silently skipped. But when there 363 // are wildcards, the real problem is that there was no match, 364 // causing the pattern to be added, which has illegal characters. 365 if (!(options & WILD_SILENT) && (options & WILD_LIST_NOTFOUND)) 366 semsg(_(e_nomatch2), str); 367 #endif 368 } 369 else if (xp->xp_numfiles == 0) 370 { 371 if (!(options & WILD_SILENT)) 372 semsg(_(e_nomatch2), str); 373 } 374 else 375 { 376 // Escape the matches for use on the command line. 377 ExpandEscape(xp, str, xp->xp_numfiles, xp->xp_files, options); 378 379 // Check for matching suffixes in file names. 380 if (mode != WILD_ALL && mode != WILD_ALL_KEEP 381 && mode != WILD_LONGEST) 382 { 383 if (xp->xp_numfiles) 384 non_suf_match = xp->xp_numfiles; 385 else 386 non_suf_match = 1; 387 if ((xp->xp_context == EXPAND_FILES 388 || xp->xp_context == EXPAND_DIRECTORIES) 389 && xp->xp_numfiles > 1) 390 { 391 // More than one match; check suffix. 392 // The files will have been sorted on matching suffix in 393 // expand_wildcards, only need to check the first two. 394 non_suf_match = 0; 395 for (i = 0; i < 2; ++i) 396 if (match_suffix(xp->xp_files[i])) 397 ++non_suf_match; 398 } 399 if (non_suf_match != 1) 400 { 401 // Can we ever get here unless it's while expanding 402 // interactively? If not, we can get rid of this all 403 // together. Don't really want to wait for this message 404 // (and possibly have to hit return to continue!). 405 if (!(options & WILD_SILENT)) 406 emsg(_(e_toomany)); 407 else if (!(options & WILD_NO_BEEP)) 408 beep_flush(); 409 } 410 if (!(non_suf_match != 1 && mode == WILD_EXPAND_FREE)) 411 ss = vim_strsave(xp->xp_files[0]); 412 } 413 } 414 } 415 416 // Find longest common part 417 if (mode == WILD_LONGEST && xp->xp_numfiles > 0) 418 { 419 int mb_len = 1; 420 int c0, ci; 421 422 for (len = 0; xp->xp_files[0][len]; len += mb_len) 423 { 424 if (has_mbyte) 425 { 426 mb_len = (*mb_ptr2len)(&xp->xp_files[0][len]); 427 c0 =(* mb_ptr2char)(&xp->xp_files[0][len]); 428 } 429 else 430 c0 = xp->xp_files[0][len]; 431 for (i = 1; i < xp->xp_numfiles; ++i) 432 { 433 if (has_mbyte) 434 ci =(* mb_ptr2char)(&xp->xp_files[i][len]); 435 else 436 ci = xp->xp_files[i][len]; 437 if (p_fic && (xp->xp_context == EXPAND_DIRECTORIES 438 || xp->xp_context == EXPAND_FILES 439 || xp->xp_context == EXPAND_SHELLCMD 440 || xp->xp_context == EXPAND_BUFFERS)) 441 { 442 if (MB_TOLOWER(c0) != MB_TOLOWER(ci)) 443 break; 444 } 445 else if (c0 != ci) 446 break; 447 } 448 if (i < xp->xp_numfiles) 449 { 450 if (!(options & WILD_NO_BEEP)) 451 vim_beep(BO_WILD); 452 break; 453 } 454 } 455 456 ss = alloc(len + 1); 457 if (ss) 458 vim_strncpy(ss, xp->xp_files[0], (size_t)len); 459 findex = -1; // next p_wc gets first one 460 } 461 462 // Concatenate all matching names 463 if (mode == WILD_ALL && xp->xp_numfiles > 0) 464 { 465 len = 0; 466 for (i = 0; i < xp->xp_numfiles; ++i) 467 len += (long_u)STRLEN(xp->xp_files[i]) + 1; 468 ss = alloc(len); 469 if (ss != NULL) 470 { 471 *ss = NUL; 472 for (i = 0; i < xp->xp_numfiles; ++i) 473 { 474 STRCAT(ss, xp->xp_files[i]); 475 if (i != xp->xp_numfiles - 1) 476 STRCAT(ss, (options & WILD_USE_NL) ? "\n" : " "); 477 } 478 } 479 } 480 481 if (mode == WILD_EXPAND_FREE || mode == WILD_ALL) 482 ExpandCleanup(xp); 483 484 // Free "orig" if it wasn't stored in "orig_save". 485 if (!orig_saved) 486 vim_free(orig); 487 488 return ss; 489 } 490 491 /* 492 * Prepare an expand structure for use. 493 */ 494 void 495 ExpandInit(expand_T *xp) 496 { 497 CLEAR_POINTER(xp); 498 xp->xp_backslash = XP_BS_NONE; 499 xp->xp_numfiles = -1; 500 } 501 502 /* 503 * Cleanup an expand structure after use. 504 */ 505 void 506 ExpandCleanup(expand_T *xp) 507 { 508 if (xp->xp_numfiles >= 0) 509 { 510 FreeWild(xp->xp_numfiles, xp->xp_files); 511 xp->xp_numfiles = -1; 512 } 513 } 514 515 /* 516 * Show all matches for completion on the command line. 517 * Returns EXPAND_NOTHING when the character that triggered expansion should 518 * be inserted like a normal character. 519 */ 520 int 521 showmatches(expand_T *xp, int wildmenu UNUSED) 522 { 523 cmdline_info_T *ccline = get_cmdline_info(); 524 #define L_SHOWFILE(m) (showtail ? sm_gettail(files_found[m]) : files_found[m]) 525 int num_files; 526 char_u **files_found; 527 int i, j, k; 528 int maxlen; 529 int lines; 530 int columns; 531 char_u *p; 532 int lastlen; 533 int attr; 534 int showtail; 535 536 if (xp->xp_numfiles == -1) 537 { 538 set_expand_context(xp); 539 i = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos, 540 &num_files, &files_found); 541 showtail = expand_showtail(xp); 542 if (i != EXPAND_OK) 543 return i; 544 545 } 546 else 547 { 548 num_files = xp->xp_numfiles; 549 files_found = xp->xp_files; 550 showtail = cmd_showtail; 551 } 552 553 #ifdef FEAT_WILDMENU 554 if (!wildmenu) 555 { 556 #endif 557 msg_didany = FALSE; // lines_left will be set 558 msg_start(); // prepare for paging 559 msg_putchar('\n'); 560 out_flush(); 561 cmdline_row = msg_row; 562 msg_didany = FALSE; // lines_left will be set again 563 msg_start(); // prepare for paging 564 #ifdef FEAT_WILDMENU 565 } 566 #endif 567 568 if (got_int) 569 got_int = FALSE; // only int. the completion, not the cmd line 570 #ifdef FEAT_WILDMENU 571 else if (wildmenu) 572 win_redr_status_matches(xp, num_files, files_found, -1, showtail); 573 #endif 574 else 575 { 576 // find the length of the longest file name 577 maxlen = 0; 578 for (i = 0; i < num_files; ++i) 579 { 580 if (!showtail && (xp->xp_context == EXPAND_FILES 581 || xp->xp_context == EXPAND_SHELLCMD 582 || xp->xp_context == EXPAND_BUFFERS)) 583 { 584 home_replace(NULL, files_found[i], NameBuff, MAXPATHL, TRUE); 585 j = vim_strsize(NameBuff); 586 } 587 else 588 j = vim_strsize(L_SHOWFILE(i)); 589 if (j > maxlen) 590 maxlen = j; 591 } 592 593 if (xp->xp_context == EXPAND_TAGS_LISTFILES) 594 lines = num_files; 595 else 596 { 597 // compute the number of columns and lines for the listing 598 maxlen += 2; // two spaces between file names 599 columns = ((int)Columns + 2) / maxlen; 600 if (columns < 1) 601 columns = 1; 602 lines = (num_files + columns - 1) / columns; 603 } 604 605 attr = HL_ATTR(HLF_D); // find out highlighting for directories 606 607 if (xp->xp_context == EXPAND_TAGS_LISTFILES) 608 { 609 msg_puts_attr(_("tagname"), HL_ATTR(HLF_T)); 610 msg_clr_eos(); 611 msg_advance(maxlen - 3); 612 msg_puts_attr(_(" kind file\n"), HL_ATTR(HLF_T)); 613 } 614 615 // list the files line by line 616 for (i = 0; i < lines; ++i) 617 { 618 lastlen = 999; 619 for (k = i; k < num_files; k += lines) 620 { 621 if (xp->xp_context == EXPAND_TAGS_LISTFILES) 622 { 623 msg_outtrans_attr(files_found[k], HL_ATTR(HLF_D)); 624 p = files_found[k] + STRLEN(files_found[k]) + 1; 625 msg_advance(maxlen + 1); 626 msg_puts((char *)p); 627 msg_advance(maxlen + 3); 628 msg_outtrans_long_attr(p + 2, HL_ATTR(HLF_D)); 629 break; 630 } 631 for (j = maxlen - lastlen; --j >= 0; ) 632 msg_putchar(' '); 633 if (xp->xp_context == EXPAND_FILES 634 || xp->xp_context == EXPAND_SHELLCMD 635 || xp->xp_context == EXPAND_BUFFERS) 636 { 637 // highlight directories 638 if (xp->xp_numfiles != -1) 639 { 640 char_u *halved_slash; 641 char_u *exp_path; 642 char_u *path; 643 644 // Expansion was done before and special characters 645 // were escaped, need to halve backslashes. Also 646 // $HOME has been replaced with ~/. 647 exp_path = expand_env_save_opt(files_found[k], TRUE); 648 path = exp_path != NULL ? exp_path : files_found[k]; 649 halved_slash = backslash_halve_save(path); 650 j = mch_isdir(halved_slash != NULL ? halved_slash 651 : files_found[k]); 652 vim_free(exp_path); 653 if (halved_slash != path) 654 vim_free(halved_slash); 655 } 656 else 657 // Expansion was done here, file names are literal. 658 j = mch_isdir(files_found[k]); 659 if (showtail) 660 p = L_SHOWFILE(k); 661 else 662 { 663 home_replace(NULL, files_found[k], NameBuff, MAXPATHL, 664 TRUE); 665 p = NameBuff; 666 } 667 } 668 else 669 { 670 j = FALSE; 671 p = L_SHOWFILE(k); 672 } 673 lastlen = msg_outtrans_attr(p, j ? attr : 0); 674 } 675 if (msg_col > 0) // when not wrapped around 676 { 677 msg_clr_eos(); 678 msg_putchar('\n'); 679 } 680 out_flush(); // show one line at a time 681 if (got_int) 682 { 683 got_int = FALSE; 684 break; 685 } 686 } 687 688 // we redraw the command below the lines that we have just listed 689 // This is a bit tricky, but it saves a lot of screen updating. 690 cmdline_row = msg_row; // will put it back later 691 } 692 693 if (xp->xp_numfiles == -1) 694 FreeWild(num_files, files_found); 695 696 return EXPAND_OK; 697 } 698 699 /* 700 * Private gettail for showmatches() (and win_redr_status_matches()): 701 * Find tail of file name path, but ignore trailing "/". 702 */ 703 char_u * 704 sm_gettail(char_u *s) 705 { 706 char_u *p; 707 char_u *t = s; 708 int had_sep = FALSE; 709 710 for (p = s; *p != NUL; ) 711 { 712 if (vim_ispathsep(*p) 713 #ifdef BACKSLASH_IN_FILENAME 714 && !rem_backslash(p) 715 #endif 716 ) 717 had_sep = TRUE; 718 else if (had_sep) 719 { 720 t = p; 721 had_sep = FALSE; 722 } 723 MB_PTR_ADV(p); 724 } 725 return t; 726 } 727 728 /* 729 * Return TRUE if we only need to show the tail of completion matches. 730 * When not completing file names or there is a wildcard in the path FALSE is 731 * returned. 732 */ 733 static int 734 expand_showtail(expand_T *xp) 735 { 736 char_u *s; 737 char_u *end; 738 739 // When not completing file names a "/" may mean something different. 740 if (xp->xp_context != EXPAND_FILES 741 && xp->xp_context != EXPAND_SHELLCMD 742 && xp->xp_context != EXPAND_DIRECTORIES) 743 return FALSE; 744 745 end = gettail(xp->xp_pattern); 746 if (end == xp->xp_pattern) // there is no path separator 747 return FALSE; 748 749 for (s = xp->xp_pattern; s < end; s++) 750 { 751 // Skip escaped wildcards. Only when the backslash is not a path 752 // separator, on DOS the '*' "path\*\file" must not be skipped. 753 if (rem_backslash(s)) 754 ++s; 755 else if (vim_strchr((char_u *)"*?[", *s) != NULL) 756 return FALSE; 757 } 758 return TRUE; 759 } 760 761 /* 762 * Prepare a string for expansion. 763 * When expanding file names: The string will be used with expand_wildcards(). 764 * Copy "fname[len]" into allocated memory and add a '*' at the end. 765 * When expanding other names: The string will be used with regcomp(). Copy 766 * the name into allocated memory and prepend "^". 767 */ 768 char_u * 769 addstar( 770 char_u *fname, 771 int len, 772 int context) // EXPAND_FILES etc. 773 { 774 char_u *retval; 775 int i, j; 776 int new_len; 777 char_u *tail; 778 int ends_in_star; 779 780 if (context != EXPAND_FILES 781 && context != EXPAND_FILES_IN_PATH 782 && context != EXPAND_SHELLCMD 783 && context != EXPAND_DIRECTORIES) 784 { 785 // Matching will be done internally (on something other than files). 786 // So we convert the file-matching-type wildcards into our kind for 787 // use with vim_regcomp(). First work out how long it will be: 788 789 // For help tags the translation is done in find_help_tags(). 790 // For a tag pattern starting with "/" no translation is needed. 791 if (context == EXPAND_HELP 792 || context == EXPAND_COLORS 793 || context == EXPAND_COMPILER 794 || context == EXPAND_OWNSYNTAX 795 || context == EXPAND_FILETYPE 796 || context == EXPAND_PACKADD 797 || ((context == EXPAND_TAGS_LISTFILES 798 || context == EXPAND_TAGS) 799 && fname[0] == '/')) 800 retval = vim_strnsave(fname, len); 801 else 802 { 803 new_len = len + 2; // +2 for '^' at start, NUL at end 804 for (i = 0; i < len; i++) 805 { 806 if (fname[i] == '*' || fname[i] == '~') 807 new_len++; // '*' needs to be replaced by ".*" 808 // '~' needs to be replaced by "\~" 809 810 // Buffer names are like file names. "." should be literal 811 if (context == EXPAND_BUFFERS && fname[i] == '.') 812 new_len++; // "." becomes "\." 813 814 // Custom expansion takes care of special things, match 815 // backslashes literally (perhaps also for other types?) 816 if ((context == EXPAND_USER_DEFINED 817 || context == EXPAND_USER_LIST) && fname[i] == '\\') 818 new_len++; // '\' becomes "\\" 819 } 820 retval = alloc(new_len); 821 if (retval != NULL) 822 { 823 retval[0] = '^'; 824 j = 1; 825 for (i = 0; i < len; i++, j++) 826 { 827 // Skip backslash. But why? At least keep it for custom 828 // expansion. 829 if (context != EXPAND_USER_DEFINED 830 && context != EXPAND_USER_LIST 831 && fname[i] == '\\' 832 && ++i == len) 833 break; 834 835 switch (fname[i]) 836 { 837 case '*': retval[j++] = '.'; 838 break; 839 case '~': retval[j++] = '\\'; 840 break; 841 case '?': retval[j] = '.'; 842 continue; 843 case '.': if (context == EXPAND_BUFFERS) 844 retval[j++] = '\\'; 845 break; 846 case '\\': if (context == EXPAND_USER_DEFINED 847 || context == EXPAND_USER_LIST) 848 retval[j++] = '\\'; 849 break; 850 } 851 retval[j] = fname[i]; 852 } 853 retval[j] = NUL; 854 } 855 } 856 } 857 else 858 { 859 retval = alloc(len + 4); 860 if (retval != NULL) 861 { 862 vim_strncpy(retval, fname, len); 863 864 // Don't add a star to *, ~, ~user, $var or `cmd`. 865 // * would become **, which walks the whole tree. 866 // ~ would be at the start of the file name, but not the tail. 867 // $ could be anywhere in the tail. 868 // ` could be anywhere in the file name. 869 // When the name ends in '$' don't add a star, remove the '$'. 870 tail = gettail(retval); 871 ends_in_star = (len > 0 && retval[len - 1] == '*'); 872 #ifndef BACKSLASH_IN_FILENAME 873 for (i = len - 2; i >= 0; --i) 874 { 875 if (retval[i] != '\\') 876 break; 877 ends_in_star = !ends_in_star; 878 } 879 #endif 880 if ((*retval != '~' || tail != retval) 881 && !ends_in_star 882 && vim_strchr(tail, '$') == NULL 883 && vim_strchr(retval, '`') == NULL) 884 retval[len++] = '*'; 885 else if (len > 0 && retval[len - 1] == '$') 886 --len; 887 retval[len] = NUL; 888 } 889 } 890 return retval; 891 } 892 893 /* 894 * Must parse the command line so far to work out what context we are in. 895 * Completion can then be done based on that context. 896 * This routine sets the variables: 897 * xp->xp_pattern The start of the pattern to be expanded within 898 * the command line (ends at the cursor). 899 * xp->xp_context The type of thing to expand. Will be one of: 900 * 901 * EXPAND_UNSUCCESSFUL Used sometimes when there is something illegal on 902 * the command line, like an unknown command. Caller 903 * should beep. 904 * EXPAND_NOTHING Unrecognised context for completion, use char like 905 * a normal char, rather than for completion. eg 906 * :s/^I/ 907 * EXPAND_COMMANDS Cursor is still touching the command, so complete 908 * it. 909 * EXPAND_BUFFERS Complete file names for :buf and :sbuf commands. 910 * EXPAND_FILES After command with EX_XFILE set, or after setting 911 * with P_EXPAND set. eg :e ^I, :w>>^I 912 * EXPAND_DIRECTORIES In some cases this is used instead of the latter 913 * when we know only directories are of interest. eg 914 * :set dir=^I 915 * EXPAND_SHELLCMD After ":!cmd", ":r !cmd" or ":w !cmd". 916 * EXPAND_SETTINGS Complete variable names. eg :set d^I 917 * EXPAND_BOOL_SETTINGS Complete boolean variables only, eg :set no^I 918 * EXPAND_TAGS Complete tags from the files in p_tags. eg :ta a^I 919 * EXPAND_TAGS_LISTFILES As above, but list filenames on ^D, after :tselect 920 * EXPAND_HELP Complete tags from the file 'helpfile'/tags 921 * EXPAND_EVENTS Complete event names 922 * EXPAND_SYNTAX Complete :syntax command arguments 923 * EXPAND_HIGHLIGHT Complete highlight (syntax) group names 924 * EXPAND_AUGROUP Complete autocommand group names 925 * EXPAND_USER_VARS Complete user defined variable names, eg :unlet a^I 926 * EXPAND_MAPPINGS Complete mapping and abbreviation names, 927 * eg :unmap a^I , :cunab x^I 928 * EXPAND_FUNCTIONS Complete internal or user defined function names, 929 * eg :call sub^I 930 * EXPAND_USER_FUNC Complete user defined function names, eg :delf F^I 931 * EXPAND_EXPRESSION Complete internal or user defined function/variable 932 * names in expressions, eg :while s^I 933 * EXPAND_ENV_VARS Complete environment variable names 934 * EXPAND_USER Complete user names 935 */ 936 static void 937 set_expand_context(expand_T *xp) 938 { 939 cmdline_info_T *ccline = get_cmdline_info(); 940 941 // only expansion for ':', '>' and '=' command-lines 942 if (ccline->cmdfirstc != ':' 943 #ifdef FEAT_EVAL 944 && ccline->cmdfirstc != '>' && ccline->cmdfirstc != '=' 945 && !ccline->input_fn 946 #endif 947 ) 948 { 949 xp->xp_context = EXPAND_NOTHING; 950 return; 951 } 952 set_cmd_context(xp, ccline->cmdbuff, ccline->cmdlen, ccline->cmdpos, TRUE); 953 } 954 955 /* 956 * This is all pretty much copied from do_one_cmd(), with all the extra stuff 957 * we don't need/want deleted. Maybe this could be done better if we didn't 958 * repeat all this stuff. The only problem is that they may not stay 959 * perfectly compatible with each other, but then the command line syntax 960 * probably won't change that much -- webb. 961 */ 962 static char_u * 963 set_one_cmd_context( 964 expand_T *xp, 965 char_u *buff) // buffer for command string 966 { 967 char_u *p; 968 char_u *cmd, *arg; 969 int len = 0; 970 exarg_T ea; 971 int compl = EXPAND_NOTHING; 972 int delim; 973 int forceit = FALSE; 974 int usefilter = FALSE; // filter instead of file name 975 976 ExpandInit(xp); 977 xp->xp_pattern = buff; 978 xp->xp_context = EXPAND_COMMANDS; // Default until we get past command 979 ea.argt = 0; 980 981 // 1. skip comment lines and leading space, colons or bars 982 for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++) 983 ; 984 xp->xp_pattern = cmd; 985 986 if (*cmd == NUL) 987 return NULL; 988 if (*cmd == '"') // ignore comment lines 989 { 990 xp->xp_context = EXPAND_NOTHING; 991 return NULL; 992 } 993 994 // 3. Skip over the range to find the command. 995 cmd = skip_range(cmd, &xp->xp_context); 996 xp->xp_pattern = cmd; 997 if (*cmd == NUL) 998 return NULL; 999 if (*cmd == '"') 1000 { 1001 xp->xp_context = EXPAND_NOTHING; 1002 return NULL; 1003 } 1004 1005 if (*cmd == '|' || *cmd == '\n') 1006 return cmd + 1; // There's another command 1007 1008 // Isolate the command and search for it in the command table. 1009 // Exceptions: 1010 // - the 'k' command can directly be followed by any character, but 1011 // do accept "keepmarks", "keepalt" and "keepjumps". 1012 // - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' 1013 if (*cmd == 'k' && cmd[1] != 'e') 1014 { 1015 ea.cmdidx = CMD_k; 1016 p = cmd + 1; 1017 } 1018 else 1019 { 1020 p = cmd; 1021 while (ASCII_ISALPHA(*p) || *p == '*') // Allow * wild card 1022 ++p; 1023 // a user command may contain digits 1024 if (ASCII_ISUPPER(cmd[0])) 1025 while (ASCII_ISALNUM(*p) || *p == '*') 1026 ++p; 1027 // for python 3.x: ":py3*" commands completion 1028 if (cmd[0] == 'p' && cmd[1] == 'y' && p == cmd + 2 && *p == '3') 1029 { 1030 ++p; 1031 while (ASCII_ISALPHA(*p) || *p == '*') 1032 ++p; 1033 } 1034 // check for non-alpha command 1035 if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) 1036 ++p; 1037 len = (int)(p - cmd); 1038 1039 if (len == 0) 1040 { 1041 xp->xp_context = EXPAND_UNSUCCESSFUL; 1042 return NULL; 1043 } 1044 1045 ea.cmdidx = excmd_get_cmdidx(cmd, len); 1046 1047 if (cmd[0] >= 'A' && cmd[0] <= 'Z') 1048 while (ASCII_ISALNUM(*p) || *p == '*') // Allow * wild card 1049 ++p; 1050 } 1051 1052 // If the cursor is touching the command, and it ends in an alpha-numeric 1053 // character, complete the command name. 1054 if (*p == NUL && ASCII_ISALNUM(p[-1])) 1055 return NULL; 1056 1057 if (ea.cmdidx == CMD_SIZE) 1058 { 1059 if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) 1060 { 1061 ea.cmdidx = CMD_substitute; 1062 p = cmd + 1; 1063 } 1064 else if (cmd[0] >= 'A' && cmd[0] <= 'Z') 1065 { 1066 ea.cmd = cmd; 1067 p = find_ucmd(&ea, p, NULL, xp, &compl); 1068 if (p == NULL) 1069 ea.cmdidx = CMD_SIZE; // ambiguous user command 1070 } 1071 } 1072 if (ea.cmdidx == CMD_SIZE) 1073 { 1074 // Not still touching the command and it was an illegal one 1075 xp->xp_context = EXPAND_UNSUCCESSFUL; 1076 return NULL; 1077 } 1078 1079 xp->xp_context = EXPAND_NOTHING; // Default now that we're past command 1080 1081 if (*p == '!') // forced commands 1082 { 1083 forceit = TRUE; 1084 ++p; 1085 } 1086 1087 // 6. parse arguments 1088 if (!IS_USER_CMDIDX(ea.cmdidx)) 1089 ea.argt = excmd_get_argt(ea.cmdidx); 1090 1091 arg = skipwhite(p); 1092 1093 // Skip over ++argopt argument 1094 if ((ea.argt & EX_ARGOPT) && *arg != NUL && STRNCMP(arg, "++", 2) == 0) 1095 { 1096 p = arg; 1097 while (*p && !vim_isspace(*p)) 1098 MB_PTR_ADV(p); 1099 arg = skipwhite(p); 1100 } 1101 1102 if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) 1103 { 1104 if (*arg == '>') // append 1105 { 1106 if (*++arg == '>') 1107 ++arg; 1108 arg = skipwhite(arg); 1109 } 1110 else if (*arg == '!' && ea.cmdidx == CMD_write) // :w !filter 1111 { 1112 ++arg; 1113 usefilter = TRUE; 1114 } 1115 } 1116 1117 if (ea.cmdidx == CMD_read) 1118 { 1119 usefilter = forceit; // :r! filter if forced 1120 if (*arg == '!') // :r !filter 1121 { 1122 ++arg; 1123 usefilter = TRUE; 1124 } 1125 } 1126 1127 if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) 1128 { 1129 while (*arg == *cmd) // allow any number of '>' or '<' 1130 ++arg; 1131 arg = skipwhite(arg); 1132 } 1133 1134 // Does command allow "+command"? 1135 if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') 1136 { 1137 // Check if we're in the +command 1138 p = arg + 1; 1139 arg = skip_cmd_arg(arg, FALSE); 1140 1141 // Still touching the command after '+'? 1142 if (*arg == NUL) 1143 return p; 1144 1145 // Skip space(s) after +command to get to the real argument 1146 arg = skipwhite(arg); 1147 } 1148 1149 1150 // Check for '|' to separate commands and '"' to start comments. 1151 // Don't do this for ":read !cmd" and ":write !cmd". 1152 if ((ea.argt & EX_TRLBAR) && !usefilter) 1153 { 1154 p = arg; 1155 // ":redir @" is not the start of a comment 1156 if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"') 1157 p += 2; 1158 while (*p) 1159 { 1160 if (*p == Ctrl_V) 1161 { 1162 if (p[1] != NUL) 1163 ++p; 1164 } 1165 else if ( (*p == '"' && !(ea.argt & EX_NOTRLCOM)) 1166 || *p == '|' || *p == '\n') 1167 { 1168 if (*(p - 1) != '\\') 1169 { 1170 if (*p == '|' || *p == '\n') 1171 return p + 1; 1172 return NULL; // It's a comment 1173 } 1174 } 1175 MB_PTR_ADV(p); 1176 } 1177 } 1178 1179 if (!(ea.argt & EX_EXTRA) && *arg != NUL 1180 && vim_strchr((char_u *)"|\"", *arg) == NULL) 1181 // no arguments allowed but there is something 1182 return NULL; 1183 1184 // Find start of last argument (argument just before cursor): 1185 p = buff; 1186 xp->xp_pattern = p; 1187 len = (int)STRLEN(buff); 1188 while (*p && p < buff + len) 1189 { 1190 if (*p == ' ' || *p == TAB) 1191 { 1192 // argument starts after a space 1193 xp->xp_pattern = ++p; 1194 } 1195 else 1196 { 1197 if (*p == '\\' && *(p + 1) != NUL) 1198 ++p; // skip over escaped character 1199 MB_PTR_ADV(p); 1200 } 1201 } 1202 1203 if (ea.argt & EX_XFILE) 1204 { 1205 int c; 1206 int in_quote = FALSE; 1207 char_u *bow = NULL; // Beginning of word 1208 1209 // Allow spaces within back-quotes to count as part of the argument 1210 // being expanded. 1211 xp->xp_pattern = skipwhite(arg); 1212 p = xp->xp_pattern; 1213 while (*p != NUL) 1214 { 1215 if (has_mbyte) 1216 c = mb_ptr2char(p); 1217 else 1218 c = *p; 1219 if (c == '\\' && p[1] != NUL) 1220 ++p; 1221 else if (c == '`') 1222 { 1223 if (!in_quote) 1224 { 1225 xp->xp_pattern = p; 1226 bow = p + 1; 1227 } 1228 in_quote = !in_quote; 1229 } 1230 // An argument can contain just about everything, except 1231 // characters that end the command and white space. 1232 else if (c == '|' || c == '\n' || c == '"' || (VIM_ISWHITE(c) 1233 #ifdef SPACE_IN_FILENAME 1234 && (!(ea.argt & EX_NOSPC) || usefilter) 1235 #endif 1236 )) 1237 { 1238 len = 0; // avoid getting stuck when space is in 'isfname' 1239 while (*p != NUL) 1240 { 1241 if (has_mbyte) 1242 c = mb_ptr2char(p); 1243 else 1244 c = *p; 1245 if (c == '`' || vim_isfilec_or_wc(c)) 1246 break; 1247 if (has_mbyte) 1248 len = (*mb_ptr2len)(p); 1249 else 1250 len = 1; 1251 MB_PTR_ADV(p); 1252 } 1253 if (in_quote) 1254 bow = p; 1255 else 1256 xp->xp_pattern = p; 1257 p -= len; 1258 } 1259 MB_PTR_ADV(p); 1260 } 1261 1262 // If we are still inside the quotes, and we passed a space, just 1263 // expand from there. 1264 if (bow != NULL && in_quote) 1265 xp->xp_pattern = bow; 1266 xp->xp_context = EXPAND_FILES; 1267 1268 // For a shell command more chars need to be escaped. 1269 if (usefilter || ea.cmdidx == CMD_bang || ea.cmdidx == CMD_terminal) 1270 { 1271 #ifndef BACKSLASH_IN_FILENAME 1272 xp->xp_shell = TRUE; 1273 #endif 1274 // When still after the command name expand executables. 1275 if (xp->xp_pattern == skipwhite(arg)) 1276 xp->xp_context = EXPAND_SHELLCMD; 1277 } 1278 1279 // Check for environment variable 1280 if (*xp->xp_pattern == '$' 1281 #if defined(MSWIN) 1282 || *xp->xp_pattern == '%' 1283 #endif 1284 ) 1285 { 1286 for (p = xp->xp_pattern + 1; *p != NUL; ++p) 1287 if (!vim_isIDc(*p)) 1288 break; 1289 if (*p == NUL) 1290 { 1291 xp->xp_context = EXPAND_ENV_VARS; 1292 ++xp->xp_pattern; 1293 // Avoid that the assignment uses EXPAND_FILES again. 1294 if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST) 1295 compl = EXPAND_ENV_VARS; 1296 } 1297 } 1298 // Check for user names 1299 if (*xp->xp_pattern == '~') 1300 { 1301 for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p) 1302 ; 1303 // Complete ~user only if it partially matches a user name. 1304 // A full match ~user<Tab> will be replaced by user's home 1305 // directory i.e. something like ~user<Tab> -> /home/user/ 1306 if (*p == NUL && p > xp->xp_pattern + 1 1307 && match_user(xp->xp_pattern + 1) >= 1) 1308 { 1309 xp->xp_context = EXPAND_USER; 1310 ++xp->xp_pattern; 1311 } 1312 } 1313 } 1314 1315 // 6. Switch on command name. 1316 switch (ea.cmdidx) 1317 { 1318 case CMD_find: 1319 case CMD_sfind: 1320 case CMD_tabfind: 1321 if (xp->xp_context == EXPAND_FILES) 1322 xp->xp_context = EXPAND_FILES_IN_PATH; 1323 break; 1324 case CMD_cd: 1325 case CMD_chdir: 1326 case CMD_tcd: 1327 case CMD_tchdir: 1328 case CMD_lcd: 1329 case CMD_lchdir: 1330 if (xp->xp_context == EXPAND_FILES) 1331 xp->xp_context = EXPAND_DIRECTORIES; 1332 break; 1333 case CMD_help: 1334 xp->xp_context = EXPAND_HELP; 1335 xp->xp_pattern = arg; 1336 break; 1337 1338 // Command modifiers: return the argument. 1339 // Also for commands with an argument that is a command. 1340 case CMD_aboveleft: 1341 case CMD_argdo: 1342 case CMD_belowright: 1343 case CMD_botright: 1344 case CMD_browse: 1345 case CMD_bufdo: 1346 case CMD_cdo: 1347 case CMD_cfdo: 1348 case CMD_confirm: 1349 case CMD_debug: 1350 case CMD_folddoclosed: 1351 case CMD_folddoopen: 1352 case CMD_hide: 1353 case CMD_keepalt: 1354 case CMD_keepjumps: 1355 case CMD_keepmarks: 1356 case CMD_keeppatterns: 1357 case CMD_ldo: 1358 case CMD_leftabove: 1359 case CMD_lfdo: 1360 case CMD_lockmarks: 1361 case CMD_noautocmd: 1362 case CMD_noswapfile: 1363 case CMD_rightbelow: 1364 case CMD_sandbox: 1365 case CMD_silent: 1366 case CMD_tab: 1367 case CMD_tabdo: 1368 case CMD_topleft: 1369 case CMD_verbose: 1370 case CMD_vertical: 1371 case CMD_windo: 1372 return arg; 1373 1374 case CMD_filter: 1375 if (*arg != NUL) 1376 arg = skip_vimgrep_pat(arg, NULL, NULL); 1377 if (arg == NULL || *arg == NUL) 1378 { 1379 xp->xp_context = EXPAND_NOTHING; 1380 return NULL; 1381 } 1382 return skipwhite(arg); 1383 1384 #ifdef FEAT_SEARCH_EXTRA 1385 case CMD_match: 1386 if (*arg == NUL || !ends_excmd(*arg)) 1387 { 1388 // also complete "None" 1389 set_context_in_echohl_cmd(xp, arg); 1390 arg = skipwhite(skiptowhite(arg)); 1391 if (*arg != NUL) 1392 { 1393 xp->xp_context = EXPAND_NOTHING; 1394 arg = skip_regexp(arg + 1, *arg, p_magic); 1395 } 1396 } 1397 return find_nextcmd(arg); 1398 #endif 1399 1400 // All completion for the +cmdline_compl feature goes here. 1401 1402 case CMD_command: 1403 return set_context_in_user_cmd(xp, arg); 1404 1405 case CMD_delcommand: 1406 xp->xp_context = EXPAND_USER_COMMANDS; 1407 xp->xp_pattern = arg; 1408 break; 1409 1410 case CMD_global: 1411 case CMD_vglobal: 1412 delim = *arg; // get the delimiter 1413 if (delim) 1414 ++arg; // skip delimiter if there is one 1415 1416 while (arg[0] != NUL && arg[0] != delim) 1417 { 1418 if (arg[0] == '\\' && arg[1] != NUL) 1419 ++arg; 1420 ++arg; 1421 } 1422 if (arg[0] != NUL) 1423 return arg + 1; 1424 break; 1425 case CMD_and: 1426 case CMD_substitute: 1427 delim = *arg; 1428 if (delim) 1429 { 1430 // skip "from" part 1431 ++arg; 1432 arg = skip_regexp(arg, delim, p_magic); 1433 } 1434 // skip "to" part 1435 while (arg[0] != NUL && arg[0] != delim) 1436 { 1437 if (arg[0] == '\\' && arg[1] != NUL) 1438 ++arg; 1439 ++arg; 1440 } 1441 if (arg[0] != NUL) // skip delimiter 1442 ++arg; 1443 while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL) 1444 ++arg; 1445 if (arg[0] != NUL) 1446 return arg; 1447 break; 1448 case CMD_isearch: 1449 case CMD_dsearch: 1450 case CMD_ilist: 1451 case CMD_dlist: 1452 case CMD_ijump: 1453 case CMD_psearch: 1454 case CMD_djump: 1455 case CMD_isplit: 1456 case CMD_dsplit: 1457 arg = skipwhite(skipdigits(arg)); // skip count 1458 if (*arg == '/') // Match regexp, not just whole words 1459 { 1460 for (++arg; *arg && *arg != '/'; arg++) 1461 if (*arg == '\\' && arg[1] != NUL) 1462 arg++; 1463 if (*arg) 1464 { 1465 arg = skipwhite(arg + 1); 1466 1467 // Check for trailing illegal characters 1468 if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL) 1469 xp->xp_context = EXPAND_NOTHING; 1470 else 1471 return arg; 1472 } 1473 } 1474 break; 1475 1476 case CMD_autocmd: 1477 return set_context_in_autocmd(xp, arg, FALSE); 1478 case CMD_doautocmd: 1479 case CMD_doautoall: 1480 return set_context_in_autocmd(xp, arg, TRUE); 1481 case CMD_set: 1482 set_context_in_set_cmd(xp, arg, 0); 1483 break; 1484 case CMD_setglobal: 1485 set_context_in_set_cmd(xp, arg, OPT_GLOBAL); 1486 break; 1487 case CMD_setlocal: 1488 set_context_in_set_cmd(xp, arg, OPT_LOCAL); 1489 break; 1490 case CMD_tag: 1491 case CMD_stag: 1492 case CMD_ptag: 1493 case CMD_ltag: 1494 case CMD_tselect: 1495 case CMD_stselect: 1496 case CMD_ptselect: 1497 case CMD_tjump: 1498 case CMD_stjump: 1499 case CMD_ptjump: 1500 if (*p_wop != NUL) 1501 xp->xp_context = EXPAND_TAGS_LISTFILES; 1502 else 1503 xp->xp_context = EXPAND_TAGS; 1504 xp->xp_pattern = arg; 1505 break; 1506 case CMD_augroup: 1507 xp->xp_context = EXPAND_AUGROUP; 1508 xp->xp_pattern = arg; 1509 break; 1510 #ifdef FEAT_SYN_HL 1511 case CMD_syntax: 1512 set_context_in_syntax_cmd(xp, arg); 1513 break; 1514 #endif 1515 #ifdef FEAT_EVAL 1516 case CMD_const: 1517 case CMD_let: 1518 case CMD_if: 1519 case CMD_elseif: 1520 case CMD_while: 1521 case CMD_for: 1522 case CMD_echo: 1523 case CMD_echon: 1524 case CMD_execute: 1525 case CMD_echomsg: 1526 case CMD_echoerr: 1527 case CMD_call: 1528 case CMD_return: 1529 case CMD_cexpr: 1530 case CMD_caddexpr: 1531 case CMD_cgetexpr: 1532 case CMD_lexpr: 1533 case CMD_laddexpr: 1534 case CMD_lgetexpr: 1535 set_context_for_expression(xp, arg, ea.cmdidx); 1536 break; 1537 1538 case CMD_unlet: 1539 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) 1540 arg = xp->xp_pattern + 1; 1541 1542 xp->xp_context = EXPAND_USER_VARS; 1543 xp->xp_pattern = arg; 1544 1545 if (*xp->xp_pattern == '$') 1546 { 1547 xp->xp_context = EXPAND_ENV_VARS; 1548 ++xp->xp_pattern; 1549 } 1550 1551 break; 1552 1553 case CMD_function: 1554 case CMD_delfunction: 1555 case CMD_disassemble: 1556 xp->xp_context = EXPAND_USER_FUNC; 1557 xp->xp_pattern = arg; 1558 break; 1559 1560 case CMD_echohl: 1561 set_context_in_echohl_cmd(xp, arg); 1562 break; 1563 #endif 1564 case CMD_highlight: 1565 set_context_in_highlight_cmd(xp, arg); 1566 break; 1567 #ifdef FEAT_CSCOPE 1568 case CMD_cscope: 1569 case CMD_lcscope: 1570 case CMD_scscope: 1571 set_context_in_cscope_cmd(xp, arg, ea.cmdidx); 1572 break; 1573 #endif 1574 #ifdef FEAT_SIGNS 1575 case CMD_sign: 1576 set_context_in_sign_cmd(xp, arg); 1577 break; 1578 #endif 1579 case CMD_bdelete: 1580 case CMD_bwipeout: 1581 case CMD_bunload: 1582 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) 1583 arg = xp->xp_pattern + 1; 1584 // FALLTHROUGH 1585 case CMD_buffer: 1586 case CMD_sbuffer: 1587 case CMD_checktime: 1588 xp->xp_context = EXPAND_BUFFERS; 1589 xp->xp_pattern = arg; 1590 break; 1591 #ifdef FEAT_DIFF 1592 case CMD_diffget: 1593 case CMD_diffput: 1594 // If current buffer is in diff mode, complete buffer names 1595 // which are in diff mode, and different than current buffer. 1596 xp->xp_context = EXPAND_DIFF_BUFFERS; 1597 xp->xp_pattern = arg; 1598 break; 1599 #endif 1600 case CMD_USER: 1601 case CMD_USER_BUF: 1602 if (compl != EXPAND_NOTHING) 1603 { 1604 // EX_XFILE: file names are handled above 1605 if (!(ea.argt & EX_XFILE)) 1606 { 1607 #ifdef FEAT_MENU 1608 if (compl == EXPAND_MENUS) 1609 return set_context_in_menu_cmd(xp, cmd, arg, forceit); 1610 #endif 1611 if (compl == EXPAND_COMMANDS) 1612 return arg; 1613 if (compl == EXPAND_MAPPINGS) 1614 return set_context_in_map_cmd(xp, (char_u *)"map", 1615 arg, forceit, FALSE, FALSE, CMD_map); 1616 // Find start of last argument. 1617 p = arg; 1618 while (*p) 1619 { 1620 if (*p == ' ') 1621 // argument starts after a space 1622 arg = p + 1; 1623 else if (*p == '\\' && *(p + 1) != NUL) 1624 ++p; // skip over escaped character 1625 MB_PTR_ADV(p); 1626 } 1627 xp->xp_pattern = arg; 1628 } 1629 xp->xp_context = compl; 1630 } 1631 break; 1632 1633 case CMD_map: case CMD_noremap: 1634 case CMD_nmap: case CMD_nnoremap: 1635 case CMD_vmap: case CMD_vnoremap: 1636 case CMD_omap: case CMD_onoremap: 1637 case CMD_imap: case CMD_inoremap: 1638 case CMD_cmap: case CMD_cnoremap: 1639 case CMD_lmap: case CMD_lnoremap: 1640 case CMD_smap: case CMD_snoremap: 1641 case CMD_tmap: case CMD_tnoremap: 1642 case CMD_xmap: case CMD_xnoremap: 1643 return set_context_in_map_cmd(xp, cmd, arg, forceit, 1644 FALSE, FALSE, ea.cmdidx); 1645 case CMD_unmap: 1646 case CMD_nunmap: 1647 case CMD_vunmap: 1648 case CMD_ounmap: 1649 case CMD_iunmap: 1650 case CMD_cunmap: 1651 case CMD_lunmap: 1652 case CMD_sunmap: 1653 case CMD_tunmap: 1654 case CMD_xunmap: 1655 return set_context_in_map_cmd(xp, cmd, arg, forceit, 1656 FALSE, TRUE, ea.cmdidx); 1657 case CMD_mapclear: 1658 case CMD_nmapclear: 1659 case CMD_vmapclear: 1660 case CMD_omapclear: 1661 case CMD_imapclear: 1662 case CMD_cmapclear: 1663 case CMD_lmapclear: 1664 case CMD_smapclear: 1665 case CMD_tmapclear: 1666 case CMD_xmapclear: 1667 xp->xp_context = EXPAND_MAPCLEAR; 1668 xp->xp_pattern = arg; 1669 break; 1670 1671 case CMD_abbreviate: case CMD_noreabbrev: 1672 case CMD_cabbrev: case CMD_cnoreabbrev: 1673 case CMD_iabbrev: case CMD_inoreabbrev: 1674 return set_context_in_map_cmd(xp, cmd, arg, forceit, 1675 TRUE, FALSE, ea.cmdidx); 1676 case CMD_unabbreviate: 1677 case CMD_cunabbrev: 1678 case CMD_iunabbrev: 1679 return set_context_in_map_cmd(xp, cmd, arg, forceit, 1680 TRUE, TRUE, ea.cmdidx); 1681 #ifdef FEAT_MENU 1682 case CMD_menu: case CMD_noremenu: case CMD_unmenu: 1683 case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu: 1684 case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu: 1685 case CMD_vmenu: case CMD_vnoremenu: case CMD_vunmenu: 1686 case CMD_omenu: case CMD_onoremenu: case CMD_ounmenu: 1687 case CMD_imenu: case CMD_inoremenu: case CMD_iunmenu: 1688 case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu: 1689 case CMD_tlmenu: case CMD_tlnoremenu: case CMD_tlunmenu: 1690 case CMD_tmenu: case CMD_tunmenu: 1691 case CMD_popup: case CMD_tearoff: case CMD_emenu: 1692 return set_context_in_menu_cmd(xp, cmd, arg, forceit); 1693 #endif 1694 1695 case CMD_colorscheme: 1696 xp->xp_context = EXPAND_COLORS; 1697 xp->xp_pattern = arg; 1698 break; 1699 1700 case CMD_compiler: 1701 xp->xp_context = EXPAND_COMPILER; 1702 xp->xp_pattern = arg; 1703 break; 1704 1705 case CMD_ownsyntax: 1706 xp->xp_context = EXPAND_OWNSYNTAX; 1707 xp->xp_pattern = arg; 1708 break; 1709 1710 case CMD_setfiletype: 1711 xp->xp_context = EXPAND_FILETYPE; 1712 xp->xp_pattern = arg; 1713 break; 1714 1715 case CMD_packadd: 1716 xp->xp_context = EXPAND_PACKADD; 1717 xp->xp_pattern = arg; 1718 break; 1719 1720 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 1721 case CMD_language: 1722 p = skiptowhite(arg); 1723 if (*p == NUL) 1724 { 1725 xp->xp_context = EXPAND_LANGUAGE; 1726 xp->xp_pattern = arg; 1727 } 1728 else 1729 { 1730 if ( STRNCMP(arg, "messages", p - arg) == 0 1731 || STRNCMP(arg, "ctype", p - arg) == 0 1732 || STRNCMP(arg, "time", p - arg) == 0 1733 || STRNCMP(arg, "collate", p - arg) == 0) 1734 { 1735 xp->xp_context = EXPAND_LOCALES; 1736 xp->xp_pattern = skipwhite(p); 1737 } 1738 else 1739 xp->xp_context = EXPAND_NOTHING; 1740 } 1741 break; 1742 #endif 1743 #if defined(FEAT_PROFILE) 1744 case CMD_profile: 1745 set_context_in_profile_cmd(xp, arg); 1746 break; 1747 #endif 1748 case CMD_behave: 1749 xp->xp_context = EXPAND_BEHAVE; 1750 xp->xp_pattern = arg; 1751 break; 1752 1753 case CMD_messages: 1754 xp->xp_context = EXPAND_MESSAGES; 1755 xp->xp_pattern = arg; 1756 break; 1757 1758 case CMD_history: 1759 xp->xp_context = EXPAND_HISTORY; 1760 xp->xp_pattern = arg; 1761 break; 1762 #if defined(FEAT_PROFILE) 1763 case CMD_syntime: 1764 xp->xp_context = EXPAND_SYNTIME; 1765 xp->xp_pattern = arg; 1766 break; 1767 #endif 1768 1769 case CMD_argdelete: 1770 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) 1771 arg = xp->xp_pattern + 1; 1772 xp->xp_context = EXPAND_ARGLIST; 1773 xp->xp_pattern = arg; 1774 break; 1775 1776 default: 1777 break; 1778 } 1779 return NULL; 1780 } 1781 1782 void 1783 set_cmd_context( 1784 expand_T *xp, 1785 char_u *str, // start of command line 1786 int len, // length of command line (excl. NUL) 1787 int col, // position of cursor 1788 int use_ccline UNUSED) // use ccline for info 1789 { 1790 #ifdef FEAT_EVAL 1791 cmdline_info_T *ccline = get_cmdline_info(); 1792 #endif 1793 int old_char = NUL; 1794 char_u *nextcomm; 1795 1796 // Avoid a UMR warning from Purify, only save the character if it has been 1797 // written before. 1798 if (col < len) 1799 old_char = str[col]; 1800 str[col] = NUL; 1801 nextcomm = str; 1802 1803 #ifdef FEAT_EVAL 1804 if (use_ccline && ccline->cmdfirstc == '=') 1805 { 1806 // pass CMD_SIZE because there is no real command 1807 set_context_for_expression(xp, str, CMD_SIZE); 1808 } 1809 else if (use_ccline && ccline->input_fn) 1810 { 1811 xp->xp_context = ccline->xp_context; 1812 xp->xp_pattern = ccline->cmdbuff; 1813 xp->xp_arg = ccline->xp_arg; 1814 } 1815 else 1816 #endif 1817 while (nextcomm != NULL) 1818 nextcomm = set_one_cmd_context(xp, nextcomm); 1819 1820 // Store the string here so that call_user_expand_func() can get to them 1821 // easily. 1822 xp->xp_line = str; 1823 xp->xp_col = col; 1824 1825 str[col] = old_char; 1826 } 1827 1828 /* 1829 * Expand the command line "str" from context "xp". 1830 * "xp" must have been set by set_cmd_context(). 1831 * xp->xp_pattern points into "str", to where the text that is to be expanded 1832 * starts. 1833 * Returns EXPAND_UNSUCCESSFUL when there is something illegal before the 1834 * cursor. 1835 * Returns EXPAND_NOTHING when there is nothing to expand, might insert the 1836 * key that triggered expansion literally. 1837 * Returns EXPAND_OK otherwise. 1838 */ 1839 int 1840 expand_cmdline( 1841 expand_T *xp, 1842 char_u *str, // start of command line 1843 int col, // position of cursor 1844 int *matchcount, // return: nr of matches 1845 char_u ***matches) // return: array of pointers to matches 1846 { 1847 char_u *file_str = NULL; 1848 int options = WILD_ADD_SLASH|WILD_SILENT; 1849 1850 if (xp->xp_context == EXPAND_UNSUCCESSFUL) 1851 { 1852 beep_flush(); 1853 return EXPAND_UNSUCCESSFUL; // Something illegal on command line 1854 } 1855 if (xp->xp_context == EXPAND_NOTHING) 1856 { 1857 // Caller can use the character as a normal char instead 1858 return EXPAND_NOTHING; 1859 } 1860 1861 // add star to file name, or convert to regexp if not exp. files. 1862 xp->xp_pattern_len = (int)(str + col - xp->xp_pattern); 1863 file_str = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context); 1864 if (file_str == NULL) 1865 return EXPAND_UNSUCCESSFUL; 1866 1867 if (p_wic) 1868 options += WILD_ICASE; 1869 1870 // find all files that match the description 1871 if (ExpandFromContext(xp, file_str, matchcount, matches, options) == FAIL) 1872 { 1873 *matchcount = 0; 1874 *matches = NULL; 1875 } 1876 vim_free(file_str); 1877 1878 return EXPAND_OK; 1879 } 1880 1881 /* 1882 * Function given to ExpandGeneric() to obtain the possible arguments of the 1883 * ":behave {mswin,xterm}" command. 1884 */ 1885 static char_u * 1886 get_behave_arg(expand_T *xp UNUSED, int idx) 1887 { 1888 if (idx == 0) 1889 return (char_u *)"mswin"; 1890 if (idx == 1) 1891 return (char_u *)"xterm"; 1892 return NULL; 1893 } 1894 1895 /* 1896 * Function given to ExpandGeneric() to obtain the possible arguments of the 1897 * ":messages {clear}" command. 1898 */ 1899 static char_u * 1900 get_messages_arg(expand_T *xp UNUSED, int idx) 1901 { 1902 if (idx == 0) 1903 return (char_u *)"clear"; 1904 return NULL; 1905 } 1906 1907 static char_u * 1908 get_mapclear_arg(expand_T *xp UNUSED, int idx) 1909 { 1910 if (idx == 0) 1911 return (char_u *)"<buffer>"; 1912 return NULL; 1913 } 1914 1915 /* 1916 * Do the expansion based on xp->xp_context and "pat". 1917 */ 1918 static int 1919 ExpandFromContext( 1920 expand_T *xp, 1921 char_u *pat, 1922 int *num_file, 1923 char_u ***file, 1924 int options) // WILD_ flags 1925 { 1926 regmatch_T regmatch; 1927 int ret; 1928 int flags; 1929 char_u *tofree = NULL; 1930 1931 flags = EW_DIR; // include directories 1932 if (options & WILD_LIST_NOTFOUND) 1933 flags |= EW_NOTFOUND; 1934 if (options & WILD_ADD_SLASH) 1935 flags |= EW_ADDSLASH; 1936 if (options & WILD_KEEP_ALL) 1937 flags |= EW_KEEPALL; 1938 if (options & WILD_SILENT) 1939 flags |= EW_SILENT; 1940 if (options & WILD_NOERROR) 1941 flags |= EW_NOERROR; 1942 if (options & WILD_ALLLINKS) 1943 flags |= EW_ALLLINKS; 1944 1945 if (xp->xp_context == EXPAND_FILES 1946 || xp->xp_context == EXPAND_DIRECTORIES 1947 || xp->xp_context == EXPAND_FILES_IN_PATH) 1948 { 1949 // Expand file or directory names. 1950 int free_pat = FALSE; 1951 int i; 1952 1953 // for ":set path=" and ":set tags=" halve backslashes for escaped 1954 // space 1955 if (xp->xp_backslash != XP_BS_NONE) 1956 { 1957 free_pat = TRUE; 1958 pat = vim_strsave(pat); 1959 for (i = 0; pat[i]; ++i) 1960 if (pat[i] == '\\') 1961 { 1962 if (xp->xp_backslash == XP_BS_THREE 1963 && pat[i + 1] == '\\' 1964 && pat[i + 2] == '\\' 1965 && pat[i + 3] == ' ') 1966 STRMOVE(pat + i, pat + i + 3); 1967 if (xp->xp_backslash == XP_BS_ONE 1968 && pat[i + 1] == ' ') 1969 STRMOVE(pat + i, pat + i + 1); 1970 } 1971 } 1972 1973 if (xp->xp_context == EXPAND_FILES) 1974 flags |= EW_FILE; 1975 else if (xp->xp_context == EXPAND_FILES_IN_PATH) 1976 flags |= (EW_FILE | EW_PATH); 1977 else 1978 flags = (flags | EW_DIR) & ~EW_FILE; 1979 if (options & WILD_ICASE) 1980 flags |= EW_ICASE; 1981 1982 // Expand wildcards, supporting %:h and the like. 1983 ret = expand_wildcards_eval(&pat, num_file, file, flags); 1984 if (free_pat) 1985 vim_free(pat); 1986 #ifdef BACKSLASH_IN_FILENAME 1987 if (p_csl[0] != NUL && (options & WILD_IGNORE_COMPLETESLASH) == 0) 1988 { 1989 int i; 1990 1991 for (i = 0; i < *num_file; ++i) 1992 { 1993 char_u *ptr = (*file)[i]; 1994 1995 while (*ptr != NUL) 1996 { 1997 if (p_csl[0] == 's' && *ptr == '\\') 1998 *ptr = '/'; 1999 else if (p_csl[0] == 'b' && *ptr == '/') 2000 *ptr = '\\'; 2001 ptr += (*mb_ptr2len)(ptr); 2002 } 2003 } 2004 } 2005 #endif 2006 return ret; 2007 } 2008 2009 *file = (char_u **)""; 2010 *num_file = 0; 2011 if (xp->xp_context == EXPAND_HELP) 2012 { 2013 // With an empty argument we would get all the help tags, which is 2014 // very slow. Get matches for "help" instead. 2015 if (find_help_tags(*pat == NUL ? (char_u *)"help" : pat, 2016 num_file, file, FALSE) == OK) 2017 { 2018 #ifdef FEAT_MULTI_LANG 2019 cleanup_help_tags(*num_file, *file); 2020 #endif 2021 return OK; 2022 } 2023 return FAIL; 2024 } 2025 2026 if (xp->xp_context == EXPAND_SHELLCMD) 2027 return expand_shellcmd(pat, num_file, file, flags); 2028 if (xp->xp_context == EXPAND_OLD_SETTING) 2029 return ExpandOldSetting(num_file, file); 2030 if (xp->xp_context == EXPAND_BUFFERS) 2031 return ExpandBufnames(pat, num_file, file, options); 2032 #ifdef FEAT_DIFF 2033 if (xp->xp_context == EXPAND_DIFF_BUFFERS) 2034 return ExpandBufnames(pat, num_file, file, options | BUF_DIFF_FILTER); 2035 #endif 2036 if (xp->xp_context == EXPAND_TAGS 2037 || xp->xp_context == EXPAND_TAGS_LISTFILES) 2038 return expand_tags(xp->xp_context == EXPAND_TAGS, pat, num_file, file); 2039 if (xp->xp_context == EXPAND_COLORS) 2040 { 2041 char *directories[] = {"colors", NULL}; 2042 return ExpandRTDir(pat, DIP_START + DIP_OPT, num_file, file, 2043 directories); 2044 } 2045 if (xp->xp_context == EXPAND_COMPILER) 2046 { 2047 char *directories[] = {"compiler", NULL}; 2048 return ExpandRTDir(pat, 0, num_file, file, directories); 2049 } 2050 if (xp->xp_context == EXPAND_OWNSYNTAX) 2051 { 2052 char *directories[] = {"syntax", NULL}; 2053 return ExpandRTDir(pat, 0, num_file, file, directories); 2054 } 2055 if (xp->xp_context == EXPAND_FILETYPE) 2056 { 2057 char *directories[] = {"syntax", "indent", "ftplugin", NULL}; 2058 return ExpandRTDir(pat, 0, num_file, file, directories); 2059 } 2060 # if defined(FEAT_EVAL) 2061 if (xp->xp_context == EXPAND_USER_LIST) 2062 return ExpandUserList(xp, num_file, file); 2063 # endif 2064 if (xp->xp_context == EXPAND_PACKADD) 2065 return ExpandPackAddDir(pat, num_file, file); 2066 2067 // When expanding a function name starting with s:, match the <SNR>nr_ 2068 // prefix. 2069 if (xp->xp_context == EXPAND_USER_FUNC && STRNCMP(pat, "^s:", 3) == 0) 2070 { 2071 int len = (int)STRLEN(pat) + 20; 2072 2073 tofree = alloc(len); 2074 vim_snprintf((char *)tofree, len, "^<SNR>\\d\\+_%s", pat + 3); 2075 pat = tofree; 2076 } 2077 2078 regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0); 2079 if (regmatch.regprog == NULL) 2080 return FAIL; 2081 2082 // set ignore-case according to p_ic, p_scs and pat 2083 regmatch.rm_ic = ignorecase(pat); 2084 2085 if (xp->xp_context == EXPAND_SETTINGS 2086 || xp->xp_context == EXPAND_BOOL_SETTINGS) 2087 ret = ExpandSettings(xp, ®match, num_file, file); 2088 else if (xp->xp_context == EXPAND_MAPPINGS) 2089 ret = ExpandMappings(®match, num_file, file); 2090 # if defined(FEAT_EVAL) 2091 else if (xp->xp_context == EXPAND_USER_DEFINED) 2092 ret = ExpandUserDefined(xp, ®match, num_file, file); 2093 # endif 2094 else 2095 { 2096 static struct expgen 2097 { 2098 int context; 2099 char_u *((*func)(expand_T *, int)); 2100 int ic; 2101 int escaped; 2102 } tab[] = 2103 { 2104 {EXPAND_COMMANDS, get_command_name, FALSE, TRUE}, 2105 {EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE}, 2106 {EXPAND_MAPCLEAR, get_mapclear_arg, TRUE, TRUE}, 2107 {EXPAND_MESSAGES, get_messages_arg, TRUE, TRUE}, 2108 {EXPAND_HISTORY, get_history_arg, TRUE, TRUE}, 2109 {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE}, 2110 {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE}, 2111 {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE}, 2112 {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE}, 2113 {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE}, 2114 # ifdef FEAT_EVAL 2115 {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE}, 2116 {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE}, 2117 {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE}, 2118 {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE}, 2119 # endif 2120 # ifdef FEAT_MENU 2121 {EXPAND_MENUS, get_menu_name, FALSE, TRUE}, 2122 {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE}, 2123 # endif 2124 # ifdef FEAT_SYN_HL 2125 {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE}, 2126 # endif 2127 # ifdef FEAT_PROFILE 2128 {EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE}, 2129 # endif 2130 {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE}, 2131 {EXPAND_EVENTS, get_event_name, TRUE, TRUE}, 2132 {EXPAND_AUGROUP, get_augroup_name, TRUE, TRUE}, 2133 # ifdef FEAT_CSCOPE 2134 {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE}, 2135 # endif 2136 # ifdef FEAT_SIGNS 2137 {EXPAND_SIGN, get_sign_name, TRUE, TRUE}, 2138 # endif 2139 # ifdef FEAT_PROFILE 2140 {EXPAND_PROFILE, get_profile_name, TRUE, TRUE}, 2141 # endif 2142 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 2143 {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE}, 2144 {EXPAND_LOCALES, get_locales, TRUE, FALSE}, 2145 # endif 2146 {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE}, 2147 {EXPAND_USER, get_users, TRUE, FALSE}, 2148 {EXPAND_ARGLIST, get_arglist_name, TRUE, FALSE}, 2149 }; 2150 int i; 2151 2152 // Find a context in the table and call the ExpandGeneric() with the 2153 // right function to do the expansion. 2154 ret = FAIL; 2155 for (i = 0; i < (int)(sizeof(tab) / sizeof(struct expgen)); ++i) 2156 if (xp->xp_context == tab[i].context) 2157 { 2158 if (tab[i].ic) 2159 regmatch.rm_ic = TRUE; 2160 ret = ExpandGeneric(xp, ®match, num_file, file, 2161 tab[i].func, tab[i].escaped); 2162 break; 2163 } 2164 } 2165 2166 vim_regfree(regmatch.regprog); 2167 vim_free(tofree); 2168 2169 return ret; 2170 } 2171 2172 /* 2173 * Expand a list of names. 2174 * 2175 * Generic function for command line completion. It calls a function to 2176 * obtain strings, one by one. The strings are matched against a regexp 2177 * program. Matching strings are copied into an array, which is returned. 2178 * 2179 * Returns OK when no problems encountered, FAIL for error (out of memory). 2180 */ 2181 static int 2182 ExpandGeneric( 2183 expand_T *xp, 2184 regmatch_T *regmatch, 2185 int *num_file, 2186 char_u ***file, 2187 char_u *((*func)(expand_T *, int)), 2188 // returns a string from the list 2189 int escaped) 2190 { 2191 int i; 2192 int count = 0; 2193 int round; 2194 char_u *str; 2195 2196 // do this loop twice: 2197 // round == 0: count the number of matching names 2198 // round == 1: copy the matching names into allocated memory 2199 for (round = 0; round <= 1; ++round) 2200 { 2201 for (i = 0; ; ++i) 2202 { 2203 str = (*func)(xp, i); 2204 if (str == NULL) // end of list 2205 break; 2206 if (*str == NUL) // skip empty strings 2207 continue; 2208 2209 if (vim_regexec(regmatch, str, (colnr_T)0)) 2210 { 2211 if (round) 2212 { 2213 if (escaped) 2214 str = vim_strsave_escaped(str, (char_u *)" \t\\."); 2215 else 2216 str = vim_strsave(str); 2217 if (str == NULL) 2218 { 2219 FreeWild(count, *file); 2220 *num_file = 0; 2221 *file = NULL; 2222 return FAIL; 2223 } 2224 (*file)[count] = str; 2225 # ifdef FEAT_MENU 2226 if (func == get_menu_names && str != NULL) 2227 { 2228 // test for separator added by get_menu_names() 2229 str += STRLEN(str) - 1; 2230 if (*str == '\001') 2231 *str = '.'; 2232 } 2233 # endif 2234 } 2235 ++count; 2236 } 2237 } 2238 if (round == 0) 2239 { 2240 if (count == 0) 2241 return OK; 2242 *file = ALLOC_MULT(char_u *, count); 2243 if (*file == NULL) 2244 { 2245 *num_file = 0; 2246 *file = NULL; 2247 return FAIL; 2248 } 2249 *num_file = count; 2250 count = 0; 2251 } 2252 } 2253 2254 // Sort the results. Keep menu's in the specified order. 2255 if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS) 2256 { 2257 if (xp->xp_context == EXPAND_EXPRESSION 2258 || xp->xp_context == EXPAND_FUNCTIONS 2259 || xp->xp_context == EXPAND_USER_FUNC) 2260 // <SNR> functions should be sorted to the end. 2261 qsort((void *)*file, (size_t)*num_file, sizeof(char_u *), 2262 sort_func_compare); 2263 else 2264 sort_strings(*file, *num_file); 2265 } 2266 2267 #if defined(FEAT_SYN_HL) 2268 // Reset the variables used for special highlight names expansion, so that 2269 // they don't show up when getting normal highlight names by ID. 2270 reset_expand_highlight(); 2271 #endif 2272 return OK; 2273 } 2274 2275 /* 2276 * Complete a shell command. 2277 * Returns FAIL or OK; 2278 */ 2279 static int 2280 expand_shellcmd( 2281 char_u *filepat, // pattern to match with command names 2282 int *num_file, // return: number of matches 2283 char_u ***file, // return: array with matches 2284 int flagsarg) // EW_ flags 2285 { 2286 char_u *pat; 2287 int i; 2288 char_u *path = NULL; 2289 int mustfree = FALSE; 2290 garray_T ga; 2291 char_u *buf; 2292 size_t l; 2293 char_u *s, *e; 2294 int flags = flagsarg; 2295 int ret; 2296 int did_curdir = FALSE; 2297 hashtab_T found_ht; 2298 hashitem_T *hi; 2299 hash_T hash; 2300 2301 buf = alloc(MAXPATHL); 2302 if (buf == NULL) 2303 return FAIL; 2304 2305 // for ":set path=" and ":set tags=" halve backslashes for escaped space 2306 pat = vim_strsave(filepat); 2307 if (pat == NULL) 2308 { 2309 vim_free(buf); 2310 return FAIL; 2311 } 2312 2313 for (i = 0; pat[i]; ++i) 2314 if (pat[i] == '\\' && pat[i + 1] == ' ') 2315 STRMOVE(pat + i, pat + i + 1); 2316 2317 flags |= EW_FILE | EW_EXEC | EW_SHELLCMD; 2318 2319 if (pat[0] == '.' && (vim_ispathsep(pat[1]) 2320 || (pat[1] == '.' && vim_ispathsep(pat[2])))) 2321 path = (char_u *)"."; 2322 else 2323 { 2324 // For an absolute name we don't use $PATH. 2325 if (!mch_isFullName(pat)) 2326 path = vim_getenv((char_u *)"PATH", &mustfree); 2327 if (path == NULL) 2328 path = (char_u *)""; 2329 } 2330 2331 // Go over all directories in $PATH. Expand matches in that directory and 2332 // collect them in "ga". When "." is not in $PATH also expand for the 2333 // current directory, to find "subdir/cmd". 2334 ga_init2(&ga, (int)sizeof(char *), 10); 2335 hash_init(&found_ht); 2336 for (s = path; ; s = e) 2337 { 2338 # if defined(MSWIN) 2339 e = vim_strchr(s, ';'); 2340 # else 2341 e = vim_strchr(s, ':'); 2342 # endif 2343 if (e == NULL) 2344 e = s + STRLEN(s); 2345 2346 if (*s == NUL) 2347 { 2348 if (did_curdir) 2349 break; 2350 // Find directories in the current directory, path is empty. 2351 did_curdir = TRUE; 2352 flags |= EW_DIR; 2353 } 2354 else if (STRNCMP(s, ".", (int)(e - s)) == 0) 2355 { 2356 did_curdir = TRUE; 2357 flags |= EW_DIR; 2358 } 2359 else 2360 // Do not match directories inside a $PATH item. 2361 flags &= ~EW_DIR; 2362 2363 l = e - s; 2364 if (l > MAXPATHL - 5) 2365 break; 2366 vim_strncpy(buf, s, l); 2367 add_pathsep(buf); 2368 l = STRLEN(buf); 2369 vim_strncpy(buf + l, pat, MAXPATHL - 1 - l); 2370 2371 // Expand matches in one directory of $PATH. 2372 ret = expand_wildcards(1, &buf, num_file, file, flags); 2373 if (ret == OK) 2374 { 2375 if (ga_grow(&ga, *num_file) == FAIL) 2376 FreeWild(*num_file, *file); 2377 else 2378 { 2379 for (i = 0; i < *num_file; ++i) 2380 { 2381 char_u *name = (*file)[i]; 2382 2383 if (STRLEN(name) > l) 2384 { 2385 // Check if this name was already found. 2386 hash = hash_hash(name + l); 2387 hi = hash_lookup(&found_ht, name + l, hash); 2388 if (HASHITEM_EMPTY(hi)) 2389 { 2390 // Remove the path that was prepended. 2391 STRMOVE(name, name + l); 2392 ((char_u **)ga.ga_data)[ga.ga_len++] = name; 2393 hash_add_item(&found_ht, hi, name, hash); 2394 name = NULL; 2395 } 2396 } 2397 vim_free(name); 2398 } 2399 vim_free(*file); 2400 } 2401 } 2402 if (*e != NUL) 2403 ++e; 2404 } 2405 *file = ga.ga_data; 2406 *num_file = ga.ga_len; 2407 2408 vim_free(buf); 2409 vim_free(pat); 2410 if (mustfree) 2411 vim_free(path); 2412 hash_clear(&found_ht); 2413 return OK; 2414 } 2415 2416 # if defined(FEAT_EVAL) 2417 /* 2418 * Call "user_expand_func()" to invoke a user defined Vim script function and 2419 * return the result (either a string, a List or NULL). 2420 */ 2421 static void * 2422 call_user_expand_func( 2423 void *(*user_expand_func)(char_u *, int, typval_T *), 2424 expand_T *xp, 2425 int *num_file, 2426 char_u ***file) 2427 { 2428 cmdline_info_T *ccline = get_cmdline_info(); 2429 int keep = 0; 2430 typval_T args[4]; 2431 sctx_T save_current_sctx = current_sctx; 2432 char_u *pat = NULL; 2433 void *ret; 2434 2435 if (xp->xp_arg == NULL || xp->xp_arg[0] == '\0' || xp->xp_line == NULL) 2436 return NULL; 2437 *num_file = 0; 2438 *file = NULL; 2439 2440 if (ccline->cmdbuff != NULL) 2441 { 2442 keep = ccline->cmdbuff[ccline->cmdlen]; 2443 ccline->cmdbuff[ccline->cmdlen] = 0; 2444 } 2445 2446 pat = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len); 2447 2448 args[0].v_type = VAR_STRING; 2449 args[0].vval.v_string = pat; 2450 args[1].v_type = VAR_STRING; 2451 args[1].vval.v_string = xp->xp_line; 2452 args[2].v_type = VAR_NUMBER; 2453 args[2].vval.v_number = xp->xp_col; 2454 args[3].v_type = VAR_UNKNOWN; 2455 2456 current_sctx = xp->xp_script_ctx; 2457 2458 ret = user_expand_func(xp->xp_arg, 3, args); 2459 2460 current_sctx = save_current_sctx; 2461 if (ccline->cmdbuff != NULL) 2462 ccline->cmdbuff[ccline->cmdlen] = keep; 2463 2464 vim_free(pat); 2465 return ret; 2466 } 2467 2468 /* 2469 * Expand names with a function defined by the user. 2470 */ 2471 static int 2472 ExpandUserDefined( 2473 expand_T *xp, 2474 regmatch_T *regmatch, 2475 int *num_file, 2476 char_u ***file) 2477 { 2478 char_u *retstr; 2479 char_u *s; 2480 char_u *e; 2481 int keep; 2482 garray_T ga; 2483 int skip; 2484 2485 retstr = call_user_expand_func(call_func_retstr, xp, num_file, file); 2486 if (retstr == NULL) 2487 return FAIL; 2488 2489 ga_init2(&ga, (int)sizeof(char *), 3); 2490 for (s = retstr; *s != NUL; s = e) 2491 { 2492 e = vim_strchr(s, '\n'); 2493 if (e == NULL) 2494 e = s + STRLEN(s); 2495 keep = *e; 2496 *e = NUL; 2497 2498 skip = xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0; 2499 *e = keep; 2500 2501 if (!skip) 2502 { 2503 if (ga_grow(&ga, 1) == FAIL) 2504 break; 2505 ((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, e - s); 2506 ++ga.ga_len; 2507 } 2508 2509 if (*e != NUL) 2510 ++e; 2511 } 2512 vim_free(retstr); 2513 *file = ga.ga_data; 2514 *num_file = ga.ga_len; 2515 return OK; 2516 } 2517 2518 /* 2519 * Expand names with a list returned by a function defined by the user. 2520 */ 2521 static int 2522 ExpandUserList( 2523 expand_T *xp, 2524 int *num_file, 2525 char_u ***file) 2526 { 2527 list_T *retlist; 2528 listitem_T *li; 2529 garray_T ga; 2530 2531 retlist = call_user_expand_func(call_func_retlist, xp, num_file, file); 2532 if (retlist == NULL) 2533 return FAIL; 2534 2535 ga_init2(&ga, (int)sizeof(char *), 3); 2536 // Loop over the items in the list. 2537 FOR_ALL_LIST_ITEMS(retlist, li) 2538 { 2539 if (li->li_tv.v_type != VAR_STRING || li->li_tv.vval.v_string == NULL) 2540 continue; // Skip non-string items and empty strings 2541 2542 if (ga_grow(&ga, 1) == FAIL) 2543 break; 2544 2545 ((char_u **)ga.ga_data)[ga.ga_len] = 2546 vim_strsave(li->li_tv.vval.v_string); 2547 ++ga.ga_len; 2548 } 2549 list_unref(retlist); 2550 2551 *file = ga.ga_data; 2552 *num_file = ga.ga_len; 2553 return OK; 2554 } 2555 # endif 2556 2557 /* 2558 * Expand "file" for all comma-separated directories in "path". 2559 * Adds the matches to "ga". Caller must init "ga". 2560 */ 2561 void 2562 globpath( 2563 char_u *path, 2564 char_u *file, 2565 garray_T *ga, 2566 int expand_options) 2567 { 2568 expand_T xpc; 2569 char_u *buf; 2570 int i; 2571 int num_p; 2572 char_u **p; 2573 2574 buf = alloc(MAXPATHL); 2575 if (buf == NULL) 2576 return; 2577 2578 ExpandInit(&xpc); 2579 xpc.xp_context = EXPAND_FILES; 2580 2581 // Loop over all entries in {path}. 2582 while (*path != NUL) 2583 { 2584 // Copy one item of the path to buf[] and concatenate the file name. 2585 copy_option_part(&path, buf, MAXPATHL, ","); 2586 if (STRLEN(buf) + STRLEN(file) + 2 < MAXPATHL) 2587 { 2588 # if defined(MSWIN) 2589 // Using the platform's path separator (\) makes vim incorrectly 2590 // treat it as an escape character, use '/' instead. 2591 if (*buf != NUL && !after_pathsep(buf, buf + STRLEN(buf))) 2592 STRCAT(buf, "/"); 2593 # else 2594 add_pathsep(buf); 2595 # endif 2596 STRCAT(buf, file); 2597 if (ExpandFromContext(&xpc, buf, &num_p, &p, 2598 WILD_SILENT|expand_options) != FAIL && num_p > 0) 2599 { 2600 ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options); 2601 2602 if (ga_grow(ga, num_p) == OK) 2603 // take over the pointers and put them in "ga" 2604 for (i = 0; i < num_p; ++i) 2605 { 2606 ((char_u **)ga->ga_data)[ga->ga_len] = p[i]; 2607 ++ga->ga_len; 2608 } 2609 vim_free(p); 2610 } 2611 } 2612 } 2613 2614 vim_free(buf); 2615 } 2616 2617 #if defined(FEAT_EVAL) || defined(PROTO) 2618 /* 2619 * "getcompletion()" function 2620 */ 2621 void 2622 f_getcompletion(typval_T *argvars, typval_T *rettv) 2623 { 2624 char_u *pat; 2625 char_u *type; 2626 expand_T xpc; 2627 int filtered = FALSE; 2628 int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH 2629 | WILD_NO_BEEP; 2630 2631 if (argvars[1].v_type != VAR_STRING) 2632 { 2633 semsg(_(e_invarg2), "type must be a string"); 2634 return; 2635 } 2636 type = tv_get_string(&argvars[1]); 2637 2638 if (argvars[2].v_type != VAR_UNKNOWN) 2639 filtered = tv_get_number_chk(&argvars[2], NULL); 2640 2641 if (p_wic) 2642 options |= WILD_ICASE; 2643 2644 // For filtered results, 'wildignore' is used 2645 if (!filtered) 2646 options |= WILD_KEEP_ALL; 2647 2648 ExpandInit(&xpc); 2649 if (STRCMP(type, "cmdline") == 0) 2650 { 2651 set_one_cmd_context(&xpc, tv_get_string(&argvars[0])); 2652 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); 2653 } 2654 else 2655 { 2656 xpc.xp_pattern = tv_get_string(&argvars[0]); 2657 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); 2658 2659 xpc.xp_context = cmdcomplete_str_to_type(type); 2660 if (xpc.xp_context == EXPAND_NOTHING) 2661 { 2662 semsg(_(e_invarg2), type); 2663 return; 2664 } 2665 2666 # if defined(FEAT_MENU) 2667 if (xpc.xp_context == EXPAND_MENUS) 2668 { 2669 set_context_in_menu_cmd(&xpc, (char_u *)"menu", xpc.xp_pattern, FALSE); 2670 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); 2671 } 2672 # endif 2673 # ifdef FEAT_CSCOPE 2674 if (xpc.xp_context == EXPAND_CSCOPE) 2675 { 2676 set_context_in_cscope_cmd(&xpc, xpc.xp_pattern, CMD_cscope); 2677 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); 2678 } 2679 # endif 2680 # ifdef FEAT_SIGNS 2681 if (xpc.xp_context == EXPAND_SIGN) 2682 { 2683 set_context_in_sign_cmd(&xpc, xpc.xp_pattern); 2684 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); 2685 } 2686 # endif 2687 } 2688 2689 pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context); 2690 if ((rettv_list_alloc(rettv) != FAIL) && (pat != NULL)) 2691 { 2692 int i; 2693 2694 ExpandOne(&xpc, pat, NULL, options, WILD_ALL_KEEP); 2695 2696 for (i = 0; i < xpc.xp_numfiles; i++) 2697 list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); 2698 } 2699 vim_free(pat); 2700 ExpandCleanup(&xpc); 2701 } 2702 #endif // FEAT_EVAL 2703