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