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, TRUE, &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 alphanumeric 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, magic_isset()); 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, magic_isset()); 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_final: 1517 case CMD_const: 1518 case CMD_let: 1519 case CMD_var: 1520 case CMD_if: 1521 case CMD_elseif: 1522 case CMD_while: 1523 case CMD_for: 1524 case CMD_echo: 1525 case CMD_echon: 1526 case CMD_execute: 1527 case CMD_echomsg: 1528 case CMD_echoerr: 1529 case CMD_call: 1530 case CMD_return: 1531 case CMD_cexpr: 1532 case CMD_caddexpr: 1533 case CMD_cgetexpr: 1534 case CMD_lexpr: 1535 case CMD_laddexpr: 1536 case CMD_lgetexpr: 1537 set_context_for_expression(xp, arg, ea.cmdidx); 1538 break; 1539 1540 case CMD_unlet: 1541 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) 1542 arg = xp->xp_pattern + 1; 1543 1544 xp->xp_context = EXPAND_USER_VARS; 1545 xp->xp_pattern = arg; 1546 1547 if (*xp->xp_pattern == '$') 1548 { 1549 xp->xp_context = EXPAND_ENV_VARS; 1550 ++xp->xp_pattern; 1551 } 1552 1553 break; 1554 1555 case CMD_function: 1556 case CMD_delfunction: 1557 case CMD_disassemble: 1558 xp->xp_context = EXPAND_USER_FUNC; 1559 xp->xp_pattern = arg; 1560 break; 1561 1562 case CMD_echohl: 1563 set_context_in_echohl_cmd(xp, arg); 1564 break; 1565 #endif 1566 case CMD_highlight: 1567 set_context_in_highlight_cmd(xp, arg); 1568 break; 1569 #ifdef FEAT_CSCOPE 1570 case CMD_cscope: 1571 case CMD_lcscope: 1572 case CMD_scscope: 1573 set_context_in_cscope_cmd(xp, arg, ea.cmdidx); 1574 break; 1575 #endif 1576 #ifdef FEAT_SIGNS 1577 case CMD_sign: 1578 set_context_in_sign_cmd(xp, arg); 1579 break; 1580 #endif 1581 case CMD_bdelete: 1582 case CMD_bwipeout: 1583 case CMD_bunload: 1584 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) 1585 arg = xp->xp_pattern + 1; 1586 // FALLTHROUGH 1587 case CMD_buffer: 1588 case CMD_sbuffer: 1589 case CMD_checktime: 1590 xp->xp_context = EXPAND_BUFFERS; 1591 xp->xp_pattern = arg; 1592 break; 1593 #ifdef FEAT_DIFF 1594 case CMD_diffget: 1595 case CMD_diffput: 1596 // If current buffer is in diff mode, complete buffer names 1597 // which are in diff mode, and different than current buffer. 1598 xp->xp_context = EXPAND_DIFF_BUFFERS; 1599 xp->xp_pattern = arg; 1600 break; 1601 #endif 1602 case CMD_USER: 1603 case CMD_USER_BUF: 1604 if (compl != EXPAND_NOTHING) 1605 { 1606 // EX_XFILE: file names are handled above 1607 if (!(ea.argt & EX_XFILE)) 1608 { 1609 #ifdef FEAT_MENU 1610 if (compl == EXPAND_MENUS) 1611 return set_context_in_menu_cmd(xp, cmd, arg, forceit); 1612 #endif 1613 if (compl == EXPAND_COMMANDS) 1614 return arg; 1615 if (compl == EXPAND_MAPPINGS) 1616 return set_context_in_map_cmd(xp, (char_u *)"map", 1617 arg, forceit, FALSE, FALSE, CMD_map); 1618 // Find start of last argument. 1619 p = arg; 1620 while (*p) 1621 { 1622 if (*p == ' ') 1623 // argument starts after a space 1624 arg = p + 1; 1625 else if (*p == '\\' && *(p + 1) != NUL) 1626 ++p; // skip over escaped character 1627 MB_PTR_ADV(p); 1628 } 1629 xp->xp_pattern = arg; 1630 } 1631 xp->xp_context = compl; 1632 } 1633 break; 1634 1635 case CMD_map: case CMD_noremap: 1636 case CMD_nmap: case CMD_nnoremap: 1637 case CMD_vmap: case CMD_vnoremap: 1638 case CMD_omap: case CMD_onoremap: 1639 case CMD_imap: case CMD_inoremap: 1640 case CMD_cmap: case CMD_cnoremap: 1641 case CMD_lmap: case CMD_lnoremap: 1642 case CMD_smap: case CMD_snoremap: 1643 case CMD_tmap: case CMD_tnoremap: 1644 case CMD_xmap: case CMD_xnoremap: 1645 return set_context_in_map_cmd(xp, cmd, arg, forceit, 1646 FALSE, FALSE, ea.cmdidx); 1647 case CMD_unmap: 1648 case CMD_nunmap: 1649 case CMD_vunmap: 1650 case CMD_ounmap: 1651 case CMD_iunmap: 1652 case CMD_cunmap: 1653 case CMD_lunmap: 1654 case CMD_sunmap: 1655 case CMD_tunmap: 1656 case CMD_xunmap: 1657 return set_context_in_map_cmd(xp, cmd, arg, forceit, 1658 FALSE, TRUE, ea.cmdidx); 1659 case CMD_mapclear: 1660 case CMD_nmapclear: 1661 case CMD_vmapclear: 1662 case CMD_omapclear: 1663 case CMD_imapclear: 1664 case CMD_cmapclear: 1665 case CMD_lmapclear: 1666 case CMD_smapclear: 1667 case CMD_tmapclear: 1668 case CMD_xmapclear: 1669 xp->xp_context = EXPAND_MAPCLEAR; 1670 xp->xp_pattern = arg; 1671 break; 1672 1673 case CMD_abbreviate: case CMD_noreabbrev: 1674 case CMD_cabbrev: case CMD_cnoreabbrev: 1675 case CMD_iabbrev: case CMD_inoreabbrev: 1676 return set_context_in_map_cmd(xp, cmd, arg, forceit, 1677 TRUE, FALSE, ea.cmdidx); 1678 case CMD_unabbreviate: 1679 case CMD_cunabbrev: 1680 case CMD_iunabbrev: 1681 return set_context_in_map_cmd(xp, cmd, arg, forceit, 1682 TRUE, TRUE, ea.cmdidx); 1683 #ifdef FEAT_MENU 1684 case CMD_menu: case CMD_noremenu: case CMD_unmenu: 1685 case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu: 1686 case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu: 1687 case CMD_vmenu: case CMD_vnoremenu: case CMD_vunmenu: 1688 case CMD_omenu: case CMD_onoremenu: case CMD_ounmenu: 1689 case CMD_imenu: case CMD_inoremenu: case CMD_iunmenu: 1690 case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu: 1691 case CMD_tlmenu: case CMD_tlnoremenu: case CMD_tlunmenu: 1692 case CMD_tmenu: case CMD_tunmenu: 1693 case CMD_popup: case CMD_tearoff: case CMD_emenu: 1694 return set_context_in_menu_cmd(xp, cmd, arg, forceit); 1695 #endif 1696 1697 case CMD_colorscheme: 1698 xp->xp_context = EXPAND_COLORS; 1699 xp->xp_pattern = arg; 1700 break; 1701 1702 case CMD_compiler: 1703 xp->xp_context = EXPAND_COMPILER; 1704 xp->xp_pattern = arg; 1705 break; 1706 1707 case CMD_ownsyntax: 1708 xp->xp_context = EXPAND_OWNSYNTAX; 1709 xp->xp_pattern = arg; 1710 break; 1711 1712 case CMD_setfiletype: 1713 xp->xp_context = EXPAND_FILETYPE; 1714 xp->xp_pattern = arg; 1715 break; 1716 1717 case CMD_packadd: 1718 xp->xp_context = EXPAND_PACKADD; 1719 xp->xp_pattern = arg; 1720 break; 1721 1722 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 1723 case CMD_language: 1724 p = skiptowhite(arg); 1725 if (*p == NUL) 1726 { 1727 xp->xp_context = EXPAND_LANGUAGE; 1728 xp->xp_pattern = arg; 1729 } 1730 else 1731 { 1732 if ( STRNCMP(arg, "messages", p - arg) == 0 1733 || STRNCMP(arg, "ctype", p - arg) == 0 1734 || STRNCMP(arg, "time", p - arg) == 0 1735 || STRNCMP(arg, "collate", p - arg) == 0) 1736 { 1737 xp->xp_context = EXPAND_LOCALES; 1738 xp->xp_pattern = skipwhite(p); 1739 } 1740 else 1741 xp->xp_context = EXPAND_NOTHING; 1742 } 1743 break; 1744 #endif 1745 #if defined(FEAT_PROFILE) 1746 case CMD_profile: 1747 set_context_in_profile_cmd(xp, arg); 1748 break; 1749 #endif 1750 case CMD_behave: 1751 xp->xp_context = EXPAND_BEHAVE; 1752 xp->xp_pattern = arg; 1753 break; 1754 1755 case CMD_messages: 1756 xp->xp_context = EXPAND_MESSAGES; 1757 xp->xp_pattern = arg; 1758 break; 1759 1760 case CMD_history: 1761 xp->xp_context = EXPAND_HISTORY; 1762 xp->xp_pattern = arg; 1763 break; 1764 #if defined(FEAT_PROFILE) 1765 case CMD_syntime: 1766 xp->xp_context = EXPAND_SYNTIME; 1767 xp->xp_pattern = arg; 1768 break; 1769 #endif 1770 1771 case CMD_argdelete: 1772 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) 1773 arg = xp->xp_pattern + 1; 1774 xp->xp_context = EXPAND_ARGLIST; 1775 xp->xp_pattern = arg; 1776 break; 1777 1778 default: 1779 break; 1780 } 1781 return NULL; 1782 } 1783 1784 void 1785 set_cmd_context( 1786 expand_T *xp, 1787 char_u *str, // start of command line 1788 int len, // length of command line (excl. NUL) 1789 int col, // position of cursor 1790 int use_ccline UNUSED) // use ccline for info 1791 { 1792 #ifdef FEAT_EVAL 1793 cmdline_info_T *ccline = get_cmdline_info(); 1794 #endif 1795 int old_char = NUL; 1796 char_u *nextcomm; 1797 1798 // Avoid a UMR warning from Purify, only save the character if it has been 1799 // written before. 1800 if (col < len) 1801 old_char = str[col]; 1802 str[col] = NUL; 1803 nextcomm = str; 1804 1805 #ifdef FEAT_EVAL 1806 if (use_ccline && ccline->cmdfirstc == '=') 1807 { 1808 // pass CMD_SIZE because there is no real command 1809 set_context_for_expression(xp, str, CMD_SIZE); 1810 } 1811 else if (use_ccline && ccline->input_fn) 1812 { 1813 xp->xp_context = ccline->xp_context; 1814 xp->xp_pattern = ccline->cmdbuff; 1815 xp->xp_arg = ccline->xp_arg; 1816 } 1817 else 1818 #endif 1819 while (nextcomm != NULL) 1820 nextcomm = set_one_cmd_context(xp, nextcomm); 1821 1822 // Store the string here so that call_user_expand_func() can get to them 1823 // easily. 1824 xp->xp_line = str; 1825 xp->xp_col = col; 1826 1827 str[col] = old_char; 1828 } 1829 1830 /* 1831 * Expand the command line "str" from context "xp". 1832 * "xp" must have been set by set_cmd_context(). 1833 * xp->xp_pattern points into "str", to where the text that is to be expanded 1834 * starts. 1835 * Returns EXPAND_UNSUCCESSFUL when there is something illegal before the 1836 * cursor. 1837 * Returns EXPAND_NOTHING when there is nothing to expand, might insert the 1838 * key that triggered expansion literally. 1839 * Returns EXPAND_OK otherwise. 1840 */ 1841 int 1842 expand_cmdline( 1843 expand_T *xp, 1844 char_u *str, // start of command line 1845 int col, // position of cursor 1846 int *matchcount, // return: nr of matches 1847 char_u ***matches) // return: array of pointers to matches 1848 { 1849 char_u *file_str = NULL; 1850 int options = WILD_ADD_SLASH|WILD_SILENT; 1851 1852 if (xp->xp_context == EXPAND_UNSUCCESSFUL) 1853 { 1854 beep_flush(); 1855 return EXPAND_UNSUCCESSFUL; // Something illegal on command line 1856 } 1857 if (xp->xp_context == EXPAND_NOTHING) 1858 { 1859 // Caller can use the character as a normal char instead 1860 return EXPAND_NOTHING; 1861 } 1862 1863 // add star to file name, or convert to regexp if not exp. files. 1864 xp->xp_pattern_len = (int)(str + col - xp->xp_pattern); 1865 file_str = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context); 1866 if (file_str == NULL) 1867 return EXPAND_UNSUCCESSFUL; 1868 1869 if (p_wic) 1870 options += WILD_ICASE; 1871 1872 // find all files that match the description 1873 if (ExpandFromContext(xp, file_str, matchcount, matches, options) == FAIL) 1874 { 1875 *matchcount = 0; 1876 *matches = NULL; 1877 } 1878 vim_free(file_str); 1879 1880 return EXPAND_OK; 1881 } 1882 1883 /* 1884 * Function given to ExpandGeneric() to obtain the possible arguments of the 1885 * ":behave {mswin,xterm}" command. 1886 */ 1887 static char_u * 1888 get_behave_arg(expand_T *xp UNUSED, int idx) 1889 { 1890 if (idx == 0) 1891 return (char_u *)"mswin"; 1892 if (idx == 1) 1893 return (char_u *)"xterm"; 1894 return NULL; 1895 } 1896 1897 /* 1898 * Function given to ExpandGeneric() to obtain the possible arguments of the 1899 * ":messages {clear}" command. 1900 */ 1901 static char_u * 1902 get_messages_arg(expand_T *xp UNUSED, int idx) 1903 { 1904 if (idx == 0) 1905 return (char_u *)"clear"; 1906 return NULL; 1907 } 1908 1909 static char_u * 1910 get_mapclear_arg(expand_T *xp UNUSED, int idx) 1911 { 1912 if (idx == 0) 1913 return (char_u *)"<buffer>"; 1914 return NULL; 1915 } 1916 1917 /* 1918 * Do the expansion based on xp->xp_context and "pat". 1919 */ 1920 static int 1921 ExpandFromContext( 1922 expand_T *xp, 1923 char_u *pat, 1924 int *num_file, 1925 char_u ***file, 1926 int options) // WILD_ flags 1927 { 1928 regmatch_T regmatch; 1929 int ret; 1930 int flags; 1931 char_u *tofree = NULL; 1932 1933 flags = EW_DIR; // include directories 1934 if (options & WILD_LIST_NOTFOUND) 1935 flags |= EW_NOTFOUND; 1936 if (options & WILD_ADD_SLASH) 1937 flags |= EW_ADDSLASH; 1938 if (options & WILD_KEEP_ALL) 1939 flags |= EW_KEEPALL; 1940 if (options & WILD_SILENT) 1941 flags |= EW_SILENT; 1942 if (options & WILD_NOERROR) 1943 flags |= EW_NOERROR; 1944 if (options & WILD_ALLLINKS) 1945 flags |= EW_ALLLINKS; 1946 1947 if (xp->xp_context == EXPAND_FILES 1948 || xp->xp_context == EXPAND_DIRECTORIES 1949 || xp->xp_context == EXPAND_FILES_IN_PATH) 1950 { 1951 // Expand file or directory names. 1952 int free_pat = FALSE; 1953 int i; 1954 1955 // for ":set path=" and ":set tags=" halve backslashes for escaped 1956 // space 1957 if (xp->xp_backslash != XP_BS_NONE) 1958 { 1959 free_pat = TRUE; 1960 pat = vim_strsave(pat); 1961 for (i = 0; pat[i]; ++i) 1962 if (pat[i] == '\\') 1963 { 1964 if (xp->xp_backslash == XP_BS_THREE 1965 && pat[i + 1] == '\\' 1966 && pat[i + 2] == '\\' 1967 && pat[i + 3] == ' ') 1968 STRMOVE(pat + i, pat + i + 3); 1969 if (xp->xp_backslash == XP_BS_ONE 1970 && pat[i + 1] == ' ') 1971 STRMOVE(pat + i, pat + i + 1); 1972 } 1973 } 1974 1975 if (xp->xp_context == EXPAND_FILES) 1976 flags |= EW_FILE; 1977 else if (xp->xp_context == EXPAND_FILES_IN_PATH) 1978 flags |= (EW_FILE | EW_PATH); 1979 else 1980 flags = (flags | EW_DIR) & ~EW_FILE; 1981 if (options & WILD_ICASE) 1982 flags |= EW_ICASE; 1983 1984 // Expand wildcards, supporting %:h and the like. 1985 ret = expand_wildcards_eval(&pat, num_file, file, flags); 1986 if (free_pat) 1987 vim_free(pat); 1988 #ifdef BACKSLASH_IN_FILENAME 1989 if (p_csl[0] != NUL && (options & WILD_IGNORE_COMPLETESLASH) == 0) 1990 { 1991 int i; 1992 1993 for (i = 0; i < *num_file; ++i) 1994 { 1995 char_u *ptr = (*file)[i]; 1996 1997 while (*ptr != NUL) 1998 { 1999 if (p_csl[0] == 's' && *ptr == '\\') 2000 *ptr = '/'; 2001 else if (p_csl[0] == 'b' && *ptr == '/') 2002 *ptr = '\\'; 2003 ptr += (*mb_ptr2len)(ptr); 2004 } 2005 } 2006 } 2007 #endif 2008 return ret; 2009 } 2010 2011 *file = (char_u **)""; 2012 *num_file = 0; 2013 if (xp->xp_context == EXPAND_HELP) 2014 { 2015 // With an empty argument we would get all the help tags, which is 2016 // very slow. Get matches for "help" instead. 2017 if (find_help_tags(*pat == NUL ? (char_u *)"help" : pat, 2018 num_file, file, FALSE) == OK) 2019 { 2020 #ifdef FEAT_MULTI_LANG 2021 cleanup_help_tags(*num_file, *file); 2022 #endif 2023 return OK; 2024 } 2025 return FAIL; 2026 } 2027 2028 if (xp->xp_context == EXPAND_SHELLCMD) 2029 return expand_shellcmd(pat, num_file, file, flags); 2030 if (xp->xp_context == EXPAND_OLD_SETTING) 2031 return ExpandOldSetting(num_file, file); 2032 if (xp->xp_context == EXPAND_BUFFERS) 2033 return ExpandBufnames(pat, num_file, file, options); 2034 #ifdef FEAT_DIFF 2035 if (xp->xp_context == EXPAND_DIFF_BUFFERS) 2036 return ExpandBufnames(pat, num_file, file, options | BUF_DIFF_FILTER); 2037 #endif 2038 if (xp->xp_context == EXPAND_TAGS 2039 || xp->xp_context == EXPAND_TAGS_LISTFILES) 2040 return expand_tags(xp->xp_context == EXPAND_TAGS, pat, num_file, file); 2041 if (xp->xp_context == EXPAND_COLORS) 2042 { 2043 char *directories[] = {"colors", NULL}; 2044 return ExpandRTDir(pat, DIP_START + DIP_OPT, num_file, file, 2045 directories); 2046 } 2047 if (xp->xp_context == EXPAND_COMPILER) 2048 { 2049 char *directories[] = {"compiler", NULL}; 2050 return ExpandRTDir(pat, 0, num_file, file, directories); 2051 } 2052 if (xp->xp_context == EXPAND_OWNSYNTAX) 2053 { 2054 char *directories[] = {"syntax", NULL}; 2055 return ExpandRTDir(pat, 0, num_file, file, directories); 2056 } 2057 if (xp->xp_context == EXPAND_FILETYPE) 2058 { 2059 char *directories[] = {"syntax", "indent", "ftplugin", NULL}; 2060 return ExpandRTDir(pat, 0, num_file, file, directories); 2061 } 2062 # if defined(FEAT_EVAL) 2063 if (xp->xp_context == EXPAND_USER_LIST) 2064 return ExpandUserList(xp, num_file, file); 2065 # endif 2066 if (xp->xp_context == EXPAND_PACKADD) 2067 return ExpandPackAddDir(pat, num_file, file); 2068 2069 // When expanding a function name starting with s:, match the <SNR>nr_ 2070 // prefix. 2071 if (xp->xp_context == EXPAND_USER_FUNC && STRNCMP(pat, "^s:", 3) == 0) 2072 { 2073 int len = (int)STRLEN(pat) + 20; 2074 2075 tofree = alloc(len); 2076 vim_snprintf((char *)tofree, len, "^<SNR>\\d\\+_%s", pat + 3); 2077 pat = tofree; 2078 } 2079 2080 regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0); 2081 if (regmatch.regprog == NULL) 2082 return FAIL; 2083 2084 // set ignore-case according to p_ic, p_scs and pat 2085 regmatch.rm_ic = ignorecase(pat); 2086 2087 if (xp->xp_context == EXPAND_SETTINGS 2088 || xp->xp_context == EXPAND_BOOL_SETTINGS) 2089 ret = ExpandSettings(xp, ®match, num_file, file); 2090 else if (xp->xp_context == EXPAND_MAPPINGS) 2091 ret = ExpandMappings(®match, num_file, file); 2092 # if defined(FEAT_EVAL) 2093 else if (xp->xp_context == EXPAND_USER_DEFINED) 2094 ret = ExpandUserDefined(xp, ®match, num_file, file); 2095 # endif 2096 else 2097 { 2098 static struct expgen 2099 { 2100 int context; 2101 char_u *((*func)(expand_T *, int)); 2102 int ic; 2103 int escaped; 2104 } tab[] = 2105 { 2106 {EXPAND_COMMANDS, get_command_name, FALSE, TRUE}, 2107 {EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE}, 2108 {EXPAND_MAPCLEAR, get_mapclear_arg, TRUE, TRUE}, 2109 {EXPAND_MESSAGES, get_messages_arg, TRUE, TRUE}, 2110 {EXPAND_HISTORY, get_history_arg, TRUE, TRUE}, 2111 {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE}, 2112 {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE}, 2113 {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE}, 2114 {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE}, 2115 {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE}, 2116 # ifdef FEAT_EVAL 2117 {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE}, 2118 {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE}, 2119 {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE}, 2120 {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE}, 2121 # endif 2122 # ifdef FEAT_MENU 2123 {EXPAND_MENUS, get_menu_name, FALSE, TRUE}, 2124 {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE}, 2125 # endif 2126 # ifdef FEAT_SYN_HL 2127 {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE}, 2128 # endif 2129 # ifdef FEAT_PROFILE 2130 {EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE}, 2131 # endif 2132 {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE}, 2133 {EXPAND_EVENTS, get_event_name, TRUE, TRUE}, 2134 {EXPAND_AUGROUP, get_augroup_name, TRUE, TRUE}, 2135 # ifdef FEAT_CSCOPE 2136 {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE}, 2137 # endif 2138 # ifdef FEAT_SIGNS 2139 {EXPAND_SIGN, get_sign_name, TRUE, TRUE}, 2140 # endif 2141 # ifdef FEAT_PROFILE 2142 {EXPAND_PROFILE, get_profile_name, TRUE, TRUE}, 2143 # endif 2144 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 2145 {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE}, 2146 {EXPAND_LOCALES, get_locales, TRUE, FALSE}, 2147 # endif 2148 {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE}, 2149 {EXPAND_USER, get_users, TRUE, FALSE}, 2150 {EXPAND_ARGLIST, get_arglist_name, TRUE, FALSE}, 2151 }; 2152 int i; 2153 2154 // Find a context in the table and call the ExpandGeneric() with the 2155 // right function to do the expansion. 2156 ret = FAIL; 2157 for (i = 0; i < (int)(sizeof(tab) / sizeof(struct expgen)); ++i) 2158 if (xp->xp_context == tab[i].context) 2159 { 2160 if (tab[i].ic) 2161 regmatch.rm_ic = TRUE; 2162 ret = ExpandGeneric(xp, ®match, num_file, file, 2163 tab[i].func, tab[i].escaped); 2164 break; 2165 } 2166 } 2167 2168 vim_regfree(regmatch.regprog); 2169 vim_free(tofree); 2170 2171 return ret; 2172 } 2173 2174 /* 2175 * Expand a list of names. 2176 * 2177 * Generic function for command line completion. It calls a function to 2178 * obtain strings, one by one. The strings are matched against a regexp 2179 * program. Matching strings are copied into an array, which is returned. 2180 * 2181 * Returns OK when no problems encountered, FAIL for error (out of memory). 2182 */ 2183 static int 2184 ExpandGeneric( 2185 expand_T *xp, 2186 regmatch_T *regmatch, 2187 int *num_file, 2188 char_u ***file, 2189 char_u *((*func)(expand_T *, int)), 2190 // returns a string from the list 2191 int escaped) 2192 { 2193 int i; 2194 int count = 0; 2195 int round; 2196 char_u *str; 2197 2198 // do this loop twice: 2199 // round == 0: count the number of matching names 2200 // round == 1: copy the matching names into allocated memory 2201 for (round = 0; round <= 1; ++round) 2202 { 2203 for (i = 0; ; ++i) 2204 { 2205 str = (*func)(xp, i); 2206 if (str == NULL) // end of list 2207 break; 2208 if (*str == NUL) // skip empty strings 2209 continue; 2210 2211 if (vim_regexec(regmatch, str, (colnr_T)0)) 2212 { 2213 if (round) 2214 { 2215 if (escaped) 2216 str = vim_strsave_escaped(str, (char_u *)" \t\\."); 2217 else 2218 str = vim_strsave(str); 2219 if (str == NULL) 2220 { 2221 FreeWild(count, *file); 2222 *num_file = 0; 2223 *file = NULL; 2224 return FAIL; 2225 } 2226 (*file)[count] = str; 2227 # ifdef FEAT_MENU 2228 if (func == get_menu_names && str != NULL) 2229 { 2230 // test for separator added by get_menu_names() 2231 str += STRLEN(str) - 1; 2232 if (*str == '\001') 2233 *str = '.'; 2234 } 2235 # endif 2236 } 2237 ++count; 2238 } 2239 } 2240 if (round == 0) 2241 { 2242 if (count == 0) 2243 return OK; 2244 *file = ALLOC_MULT(char_u *, count); 2245 if (*file == NULL) 2246 { 2247 *num_file = 0; 2248 *file = NULL; 2249 return FAIL; 2250 } 2251 *num_file = count; 2252 count = 0; 2253 } 2254 } 2255 2256 // Sort the results. Keep menu's in the specified order. 2257 if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS) 2258 { 2259 if (xp->xp_context == EXPAND_EXPRESSION 2260 || xp->xp_context == EXPAND_FUNCTIONS 2261 || xp->xp_context == EXPAND_USER_FUNC) 2262 // <SNR> functions should be sorted to the end. 2263 qsort((void *)*file, (size_t)*num_file, sizeof(char_u *), 2264 sort_func_compare); 2265 else 2266 sort_strings(*file, *num_file); 2267 } 2268 2269 #if defined(FEAT_SYN_HL) 2270 // Reset the variables used for special highlight names expansion, so that 2271 // they don't show up when getting normal highlight names by ID. 2272 reset_expand_highlight(); 2273 #endif 2274 return OK; 2275 } 2276 2277 /* 2278 * Complete a shell command. 2279 * Returns FAIL or OK; 2280 */ 2281 static int 2282 expand_shellcmd( 2283 char_u *filepat, // pattern to match with command names 2284 int *num_file, // return: number of matches 2285 char_u ***file, // return: array with matches 2286 int flagsarg) // EW_ flags 2287 { 2288 char_u *pat; 2289 int i; 2290 char_u *path = NULL; 2291 int mustfree = FALSE; 2292 garray_T ga; 2293 char_u *buf; 2294 size_t l; 2295 char_u *s, *e; 2296 int flags = flagsarg; 2297 int ret; 2298 int did_curdir = FALSE; 2299 hashtab_T found_ht; 2300 hashitem_T *hi; 2301 hash_T hash; 2302 2303 buf = alloc(MAXPATHL); 2304 if (buf == NULL) 2305 return FAIL; 2306 2307 // for ":set path=" and ":set tags=" halve backslashes for escaped space 2308 pat = vim_strsave(filepat); 2309 if (pat == NULL) 2310 { 2311 vim_free(buf); 2312 return FAIL; 2313 } 2314 2315 for (i = 0; pat[i]; ++i) 2316 if (pat[i] == '\\' && pat[i + 1] == ' ') 2317 STRMOVE(pat + i, pat + i + 1); 2318 2319 flags |= EW_FILE | EW_EXEC | EW_SHELLCMD; 2320 2321 if (pat[0] == '.' && (vim_ispathsep(pat[1]) 2322 || (pat[1] == '.' && vim_ispathsep(pat[2])))) 2323 path = (char_u *)"."; 2324 else 2325 { 2326 // For an absolute name we don't use $PATH. 2327 if (!mch_isFullName(pat)) 2328 path = vim_getenv((char_u *)"PATH", &mustfree); 2329 if (path == NULL) 2330 path = (char_u *)""; 2331 } 2332 2333 // Go over all directories in $PATH. Expand matches in that directory and 2334 // collect them in "ga". When "." is not in $PATH also expand for the 2335 // current directory, to find "subdir/cmd". 2336 ga_init2(&ga, (int)sizeof(char *), 10); 2337 hash_init(&found_ht); 2338 for (s = path; ; s = e) 2339 { 2340 # if defined(MSWIN) 2341 e = vim_strchr(s, ';'); 2342 # else 2343 e = vim_strchr(s, ':'); 2344 # endif 2345 if (e == NULL) 2346 e = s + STRLEN(s); 2347 2348 if (*s == NUL) 2349 { 2350 if (did_curdir) 2351 break; 2352 // Find directories in the current directory, path is empty. 2353 did_curdir = TRUE; 2354 flags |= EW_DIR; 2355 } 2356 else if (STRNCMP(s, ".", (int)(e - s)) == 0) 2357 { 2358 did_curdir = TRUE; 2359 flags |= EW_DIR; 2360 } 2361 else 2362 // Do not match directories inside a $PATH item. 2363 flags &= ~EW_DIR; 2364 2365 l = e - s; 2366 if (l > MAXPATHL - 5) 2367 break; 2368 vim_strncpy(buf, s, l); 2369 add_pathsep(buf); 2370 l = STRLEN(buf); 2371 vim_strncpy(buf + l, pat, MAXPATHL - 1 - l); 2372 2373 // Expand matches in one directory of $PATH. 2374 ret = expand_wildcards(1, &buf, num_file, file, flags); 2375 if (ret == OK) 2376 { 2377 if (ga_grow(&ga, *num_file) == FAIL) 2378 FreeWild(*num_file, *file); 2379 else 2380 { 2381 for (i = 0; i < *num_file; ++i) 2382 { 2383 char_u *name = (*file)[i]; 2384 2385 if (STRLEN(name) > l) 2386 { 2387 // Check if this name was already found. 2388 hash = hash_hash(name + l); 2389 hi = hash_lookup(&found_ht, name + l, hash); 2390 if (HASHITEM_EMPTY(hi)) 2391 { 2392 // Remove the path that was prepended. 2393 STRMOVE(name, name + l); 2394 ((char_u **)ga.ga_data)[ga.ga_len++] = name; 2395 hash_add_item(&found_ht, hi, name, hash); 2396 name = NULL; 2397 } 2398 } 2399 vim_free(name); 2400 } 2401 vim_free(*file); 2402 } 2403 } 2404 if (*e != NUL) 2405 ++e; 2406 } 2407 *file = ga.ga_data; 2408 *num_file = ga.ga_len; 2409 2410 vim_free(buf); 2411 vim_free(pat); 2412 if (mustfree) 2413 vim_free(path); 2414 hash_clear(&found_ht); 2415 return OK; 2416 } 2417 2418 # if defined(FEAT_EVAL) 2419 /* 2420 * Call "user_expand_func()" to invoke a user defined Vim script function and 2421 * return the result (either a string, a List or NULL). 2422 */ 2423 static void * 2424 call_user_expand_func( 2425 void *(*user_expand_func)(char_u *, int, typval_T *), 2426 expand_T *xp, 2427 int *num_file, 2428 char_u ***file) 2429 { 2430 cmdline_info_T *ccline = get_cmdline_info(); 2431 int keep = 0; 2432 typval_T args[4]; 2433 sctx_T save_current_sctx = current_sctx; 2434 char_u *pat = NULL; 2435 void *ret; 2436 2437 if (xp->xp_arg == NULL || xp->xp_arg[0] == '\0' || xp->xp_line == NULL) 2438 return NULL; 2439 *num_file = 0; 2440 *file = NULL; 2441 2442 if (ccline->cmdbuff != NULL) 2443 { 2444 keep = ccline->cmdbuff[ccline->cmdlen]; 2445 ccline->cmdbuff[ccline->cmdlen] = 0; 2446 } 2447 2448 pat = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len); 2449 2450 args[0].v_type = VAR_STRING; 2451 args[0].vval.v_string = pat; 2452 args[1].v_type = VAR_STRING; 2453 args[1].vval.v_string = xp->xp_line; 2454 args[2].v_type = VAR_NUMBER; 2455 args[2].vval.v_number = xp->xp_col; 2456 args[3].v_type = VAR_UNKNOWN; 2457 2458 current_sctx = xp->xp_script_ctx; 2459 2460 ret = user_expand_func(xp->xp_arg, 3, args); 2461 2462 current_sctx = save_current_sctx; 2463 if (ccline->cmdbuff != NULL) 2464 ccline->cmdbuff[ccline->cmdlen] = keep; 2465 2466 vim_free(pat); 2467 return ret; 2468 } 2469 2470 /* 2471 * Expand names with a function defined by the user. 2472 */ 2473 static int 2474 ExpandUserDefined( 2475 expand_T *xp, 2476 regmatch_T *regmatch, 2477 int *num_file, 2478 char_u ***file) 2479 { 2480 char_u *retstr; 2481 char_u *s; 2482 char_u *e; 2483 int keep; 2484 garray_T ga; 2485 int skip; 2486 2487 retstr = call_user_expand_func(call_func_retstr, xp, num_file, file); 2488 if (retstr == NULL) 2489 return FAIL; 2490 2491 ga_init2(&ga, (int)sizeof(char *), 3); 2492 for (s = retstr; *s != NUL; s = e) 2493 { 2494 e = vim_strchr(s, '\n'); 2495 if (e == NULL) 2496 e = s + STRLEN(s); 2497 keep = *e; 2498 *e = NUL; 2499 2500 skip = xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0; 2501 *e = keep; 2502 2503 if (!skip) 2504 { 2505 if (ga_grow(&ga, 1) == FAIL) 2506 break; 2507 ((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, e - s); 2508 ++ga.ga_len; 2509 } 2510 2511 if (*e != NUL) 2512 ++e; 2513 } 2514 vim_free(retstr); 2515 *file = ga.ga_data; 2516 *num_file = ga.ga_len; 2517 return OK; 2518 } 2519 2520 /* 2521 * Expand names with a list returned by a function defined by the user. 2522 */ 2523 static int 2524 ExpandUserList( 2525 expand_T *xp, 2526 int *num_file, 2527 char_u ***file) 2528 { 2529 list_T *retlist; 2530 listitem_T *li; 2531 garray_T ga; 2532 2533 retlist = call_user_expand_func(call_func_retlist, xp, num_file, file); 2534 if (retlist == NULL) 2535 return FAIL; 2536 2537 ga_init2(&ga, (int)sizeof(char *), 3); 2538 // Loop over the items in the list. 2539 FOR_ALL_LIST_ITEMS(retlist, li) 2540 { 2541 if (li->li_tv.v_type != VAR_STRING || li->li_tv.vval.v_string == NULL) 2542 continue; // Skip non-string items and empty strings 2543 2544 if (ga_grow(&ga, 1) == FAIL) 2545 break; 2546 2547 ((char_u **)ga.ga_data)[ga.ga_len] = 2548 vim_strsave(li->li_tv.vval.v_string); 2549 ++ga.ga_len; 2550 } 2551 list_unref(retlist); 2552 2553 *file = ga.ga_data; 2554 *num_file = ga.ga_len; 2555 return OK; 2556 } 2557 # endif 2558 2559 /* 2560 * Expand "file" for all comma-separated directories in "path". 2561 * Adds the matches to "ga". Caller must init "ga". 2562 */ 2563 void 2564 globpath( 2565 char_u *path, 2566 char_u *file, 2567 garray_T *ga, 2568 int expand_options) 2569 { 2570 expand_T xpc; 2571 char_u *buf; 2572 int i; 2573 int num_p; 2574 char_u **p; 2575 2576 buf = alloc(MAXPATHL); 2577 if (buf == NULL) 2578 return; 2579 2580 ExpandInit(&xpc); 2581 xpc.xp_context = EXPAND_FILES; 2582 2583 // Loop over all entries in {path}. 2584 while (*path != NUL) 2585 { 2586 // Copy one item of the path to buf[] and concatenate the file name. 2587 copy_option_part(&path, buf, MAXPATHL, ","); 2588 if (STRLEN(buf) + STRLEN(file) + 2 < MAXPATHL) 2589 { 2590 # if defined(MSWIN) 2591 // Using the platform's path separator (\) makes vim incorrectly 2592 // treat it as an escape character, use '/' instead. 2593 if (*buf != NUL && !after_pathsep(buf, buf + STRLEN(buf))) 2594 STRCAT(buf, "/"); 2595 # else 2596 add_pathsep(buf); 2597 # endif 2598 STRCAT(buf, file); 2599 if (ExpandFromContext(&xpc, buf, &num_p, &p, 2600 WILD_SILENT|expand_options) != FAIL && num_p > 0) 2601 { 2602 ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options); 2603 2604 if (ga_grow(ga, num_p) == OK) 2605 // take over the pointers and put them in "ga" 2606 for (i = 0; i < num_p; ++i) 2607 { 2608 ((char_u **)ga->ga_data)[ga->ga_len] = p[i]; 2609 ++ga->ga_len; 2610 } 2611 vim_free(p); 2612 } 2613 } 2614 } 2615 2616 vim_free(buf); 2617 } 2618 2619 #ifdef FEAT_WILDMENU 2620 2621 /* 2622 * Translate some keys pressed when 'wildmenu' is used. 2623 */ 2624 int 2625 wildmenu_translate_key( 2626 cmdline_info_T *cclp, 2627 int key, 2628 expand_T *xp, 2629 int did_wild_list) 2630 { 2631 int c = key; 2632 2633 if (did_wild_list && p_wmnu) 2634 { 2635 if (c == K_LEFT) 2636 c = Ctrl_P; 2637 else if (c == K_RIGHT) 2638 c = Ctrl_N; 2639 } 2640 // Hitting CR after "emenu Name.": complete submenu 2641 if (xp->xp_context == EXPAND_MENUNAMES && p_wmnu 2642 && cclp->cmdpos > 1 2643 && cclp->cmdbuff[cclp->cmdpos - 1] == '.' 2644 && cclp->cmdbuff[cclp->cmdpos - 2] != '\\' 2645 && (c == '\n' || c == '\r' || c == K_KENTER)) 2646 c = K_DOWN; 2647 2648 return c; 2649 } 2650 2651 /* 2652 * Delete characters on the command line, from "from" to the current 2653 * position. 2654 */ 2655 static void 2656 cmdline_del(cmdline_info_T *cclp, int from) 2657 { 2658 mch_memmove(cclp->cmdbuff + from, cclp->cmdbuff + cclp->cmdpos, 2659 (size_t)(cclp->cmdlen - cclp->cmdpos + 1)); 2660 cclp->cmdlen -= cclp->cmdpos - from; 2661 cclp->cmdpos = from; 2662 } 2663 2664 /* 2665 * Handle a key pressed when wild menu is displayed 2666 */ 2667 int 2668 wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp) 2669 { 2670 int c = key; 2671 int i; 2672 int j; 2673 2674 if (!p_wmnu) 2675 return c; 2676 2677 // Special translations for 'wildmenu' 2678 if (xp->xp_context == EXPAND_MENUNAMES) 2679 { 2680 // Hitting <Down> after "emenu Name.": complete submenu 2681 if (c == K_DOWN && cclp->cmdpos > 0 2682 && cclp->cmdbuff[cclp->cmdpos - 1] == '.') 2683 c = p_wc; 2684 else if (c == K_UP) 2685 { 2686 // Hitting <Up>: Remove one submenu name in front of the 2687 // cursor 2688 int found = FALSE; 2689 2690 j = (int)(xp->xp_pattern - cclp->cmdbuff); 2691 i = 0; 2692 while (--j > 0) 2693 { 2694 // check for start of menu name 2695 if (cclp->cmdbuff[j] == ' ' 2696 && cclp->cmdbuff[j - 1] != '\\') 2697 { 2698 i = j + 1; 2699 break; 2700 } 2701 // check for start of submenu name 2702 if (cclp->cmdbuff[j] == '.' 2703 && cclp->cmdbuff[j - 1] != '\\') 2704 { 2705 if (found) 2706 { 2707 i = j + 1; 2708 break; 2709 } 2710 else 2711 found = TRUE; 2712 } 2713 } 2714 if (i > 0) 2715 cmdline_del(cclp, i); 2716 c = p_wc; 2717 xp->xp_context = EXPAND_NOTHING; 2718 } 2719 } 2720 if ((xp->xp_context == EXPAND_FILES 2721 || xp->xp_context == EXPAND_DIRECTORIES 2722 || xp->xp_context == EXPAND_SHELLCMD)) 2723 { 2724 char_u upseg[5]; 2725 2726 upseg[0] = PATHSEP; 2727 upseg[1] = '.'; 2728 upseg[2] = '.'; 2729 upseg[3] = PATHSEP; 2730 upseg[4] = NUL; 2731 2732 if (c == K_DOWN 2733 && cclp->cmdpos > 0 2734 && cclp->cmdbuff[cclp->cmdpos - 1] == PATHSEP 2735 && (cclp->cmdpos < 3 2736 || cclp->cmdbuff[cclp->cmdpos - 2] != '.' 2737 || cclp->cmdbuff[cclp->cmdpos - 3] != '.')) 2738 { 2739 // go down a directory 2740 c = p_wc; 2741 } 2742 else if (STRNCMP(xp->xp_pattern, upseg + 1, 3) == 0 && c == K_DOWN) 2743 { 2744 // If in a direct ancestor, strip off one ../ to go down 2745 int found = FALSE; 2746 2747 j = cclp->cmdpos; 2748 i = (int)(xp->xp_pattern - cclp->cmdbuff); 2749 while (--j > i) 2750 { 2751 if (has_mbyte) 2752 j -= (*mb_head_off)(cclp->cmdbuff, cclp->cmdbuff + j); 2753 if (vim_ispathsep(cclp->cmdbuff[j])) 2754 { 2755 found = TRUE; 2756 break; 2757 } 2758 } 2759 if (found 2760 && cclp->cmdbuff[j - 1] == '.' 2761 && cclp->cmdbuff[j - 2] == '.' 2762 && (vim_ispathsep(cclp->cmdbuff[j - 3]) || j == i + 2)) 2763 { 2764 cmdline_del(cclp, j - 2); 2765 c = p_wc; 2766 } 2767 } 2768 else if (c == K_UP) 2769 { 2770 // go up a directory 2771 int found = FALSE; 2772 2773 j = cclp->cmdpos - 1; 2774 i = (int)(xp->xp_pattern - cclp->cmdbuff); 2775 while (--j > i) 2776 { 2777 if (has_mbyte) 2778 j -= (*mb_head_off)(cclp->cmdbuff, cclp->cmdbuff + j); 2779 if (vim_ispathsep(cclp->cmdbuff[j]) 2780 # ifdef BACKSLASH_IN_FILENAME 2781 && vim_strchr((char_u *)" *?[{`$%#", 2782 cclp->cmdbuff[j + 1]) == NULL 2783 # endif 2784 ) 2785 { 2786 if (found) 2787 { 2788 i = j + 1; 2789 break; 2790 } 2791 else 2792 found = TRUE; 2793 } 2794 } 2795 2796 if (!found) 2797 j = i; 2798 else if (STRNCMP(cclp->cmdbuff + j, upseg, 4) == 0) 2799 j += 4; 2800 else if (STRNCMP(cclp->cmdbuff + j, upseg + 1, 3) == 0 2801 && j == i) 2802 j += 3; 2803 else 2804 j = 0; 2805 if (j > 0) 2806 { 2807 // TODO this is only for DOS/UNIX systems - need to put in 2808 // machine-specific stuff here and in upseg init 2809 cmdline_del(cclp, j); 2810 put_on_cmdline(upseg + 1, 3, FALSE); 2811 } 2812 else if (cclp->cmdpos > i) 2813 cmdline_del(cclp, i); 2814 2815 // Now complete in the new directory. Set KeyTyped in case the 2816 // Up key came from a mapping. 2817 c = p_wc; 2818 KeyTyped = TRUE; 2819 } 2820 } 2821 2822 return c; 2823 } 2824 2825 /* 2826 * Free expanded names when finished walking through the matches 2827 */ 2828 void 2829 wildmenu_cleanup(cmdline_info_T *cclp) 2830 { 2831 int skt = KeyTyped; 2832 int old_RedrawingDisabled = RedrawingDisabled; 2833 2834 if (!p_wmnu || wild_menu_showing == 0) 2835 return; 2836 2837 if (cclp->input_fn) 2838 RedrawingDisabled = 0; 2839 2840 if (wild_menu_showing == WM_SCROLLED) 2841 { 2842 // Entered command line, move it up 2843 cmdline_row--; 2844 redrawcmd(); 2845 } 2846 else if (save_p_ls != -1) 2847 { 2848 // restore 'laststatus' and 'winminheight' 2849 p_ls = save_p_ls; 2850 p_wmh = save_p_wmh; 2851 last_status(FALSE); 2852 update_screen(VALID); // redraw the screen NOW 2853 redrawcmd(); 2854 save_p_ls = -1; 2855 } 2856 else 2857 { 2858 win_redraw_last_status(topframe); 2859 redraw_statuslines(); 2860 } 2861 KeyTyped = skt; 2862 wild_menu_showing = 0; 2863 if (cclp->input_fn) 2864 RedrawingDisabled = old_RedrawingDisabled; 2865 } 2866 #endif 2867 2868 #if defined(FEAT_EVAL) || defined(PROTO) 2869 /* 2870 * "getcompletion()" function 2871 */ 2872 void 2873 f_getcompletion(typval_T *argvars, typval_T *rettv) 2874 { 2875 char_u *pat; 2876 char_u *type; 2877 expand_T xpc; 2878 int filtered = FALSE; 2879 int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH 2880 | WILD_NO_BEEP; 2881 2882 if (argvars[1].v_type != VAR_STRING) 2883 { 2884 semsg(_(e_invarg2), "type must be a string"); 2885 return; 2886 } 2887 type = tv_get_string(&argvars[1]); 2888 2889 if (argvars[2].v_type != VAR_UNKNOWN) 2890 filtered = tv_get_bool_chk(&argvars[2], NULL); 2891 2892 if (p_wic) 2893 options |= WILD_ICASE; 2894 2895 // For filtered results, 'wildignore' is used 2896 if (!filtered) 2897 options |= WILD_KEEP_ALL; 2898 2899 ExpandInit(&xpc); 2900 if (STRCMP(type, "cmdline") == 0) 2901 { 2902 set_one_cmd_context(&xpc, tv_get_string(&argvars[0])); 2903 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); 2904 } 2905 else 2906 { 2907 xpc.xp_pattern = tv_get_string(&argvars[0]); 2908 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); 2909 2910 xpc.xp_context = cmdcomplete_str_to_type(type); 2911 if (xpc.xp_context == EXPAND_NOTHING) 2912 { 2913 semsg(_(e_invarg2), type); 2914 return; 2915 } 2916 2917 # if defined(FEAT_MENU) 2918 if (xpc.xp_context == EXPAND_MENUS) 2919 { 2920 set_context_in_menu_cmd(&xpc, (char_u *)"menu", xpc.xp_pattern, FALSE); 2921 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); 2922 } 2923 # endif 2924 # ifdef FEAT_CSCOPE 2925 if (xpc.xp_context == EXPAND_CSCOPE) 2926 { 2927 set_context_in_cscope_cmd(&xpc, xpc.xp_pattern, CMD_cscope); 2928 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); 2929 } 2930 # endif 2931 # ifdef FEAT_SIGNS 2932 if (xpc.xp_context == EXPAND_SIGN) 2933 { 2934 set_context_in_sign_cmd(&xpc, xpc.xp_pattern); 2935 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); 2936 } 2937 # endif 2938 } 2939 2940 pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context); 2941 if ((rettv_list_alloc(rettv) != FAIL) && (pat != NULL)) 2942 { 2943 int i; 2944 2945 ExpandOne(&xpc, pat, NULL, options, WILD_ALL_KEEP); 2946 2947 for (i = 0; i < xpc.xp_numfiles; i++) 2948 list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); 2949 } 2950 vim_free(pat); 2951 ExpandCleanup(&xpc); 2952 } 2953 #endif // FEAT_EVAL 2954