blob: c347c1aba8f794fa59655e6d6efd252832dd289a [file] [log] [blame]
Bram Moolenaar66b51422019-08-18 21:44:12 +02001/* 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
16static int cmd_showtail; // Only show path tail in lists ?
17
18static void set_expand_context(expand_T *xp);
19static int ExpandFromContext(expand_T *xp, char_u *, int *, char_u ***, int);
20static int expand_showtail(expand_T *xp);
21#ifdef FEAT_CMDL_COMPL
22static int expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int flagsarg);
23static int ExpandRTDir(char_u *pat, int flags, int *num_file, char_u ***file, char *dirname[]);
24static int ExpandPackAddDir(char_u *pat, int *num_file, char_u ***file);
25# if defined(FEAT_EVAL)
26static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file);
27static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file);
28# endif
29#endif
30
31#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
32 static int
33sort_func_compare(const void *s1, const void *s2)
34{
35 char_u *p1 = *(char_u **)s1;
36 char_u *p2 = *(char_u **)s2;
37
38 if (*p1 != '<' && *p2 == '<') return -1;
39 if (*p1 == '<' && *p2 != '<') return 1;
40 return STRCMP(p1, p2);
41}
42#endif
43
44 static void
45ExpandEscape(
46 expand_T *xp,
47 char_u *str,
48 int numfiles,
49 char_u **files,
50 int options)
51{
52 int i;
53 char_u *p;
54
55 // May change home directory back to "~"
56 if (options & WILD_HOME_REPLACE)
57 tilde_replace(str, numfiles, files);
58
59 if (options & WILD_ESCAPE)
60 {
61 if (xp->xp_context == EXPAND_FILES
62 || xp->xp_context == EXPAND_FILES_IN_PATH
63 || xp->xp_context == EXPAND_SHELLCMD
64 || xp->xp_context == EXPAND_BUFFERS
65 || xp->xp_context == EXPAND_DIRECTORIES)
66 {
67 // Insert a backslash into a file name before a space, \, %, #
68 // and wildmatch characters, except '~'.
69 for (i = 0; i < numfiles; ++i)
70 {
71 // for ":set path=" we need to escape spaces twice
72 if (xp->xp_backslash == XP_BS_THREE)
73 {
74 p = vim_strsave_escaped(files[i], (char_u *)" ");
75 if (p != NULL)
76 {
77 vim_free(files[i]);
78 files[i] = p;
79#if defined(BACKSLASH_IN_FILENAME)
80 p = vim_strsave_escaped(files[i], (char_u *)" ");
81 if (p != NULL)
82 {
83 vim_free(files[i]);
84 files[i] = p;
85 }
86#endif
87 }
88 }
89#ifdef BACKSLASH_IN_FILENAME
90 p = vim_strsave_fnameescape(files[i], FALSE);
91#else
92 p = vim_strsave_fnameescape(files[i], xp->xp_shell);
93#endif
94 if (p != NULL)
95 {
96 vim_free(files[i]);
97 files[i] = p;
98 }
99
100 // If 'str' starts with "\~", replace "~" at start of
101 // files[i] with "\~".
102 if (str[0] == '\\' && str[1] == '~' && files[i][0] == '~')
103 escape_fname(&files[i]);
104 }
105 xp->xp_backslash = XP_BS_NONE;
106
107 // If the first file starts with a '+' escape it. Otherwise it
108 // could be seen as "+cmd".
109 if (*files[0] == '+')
110 escape_fname(&files[0]);
111 }
112 else if (xp->xp_context == EXPAND_TAGS)
113 {
114 // Insert a backslash before characters in a tag name that
115 // would terminate the ":tag" command.
116 for (i = 0; i < numfiles; ++i)
117 {
118 p = vim_strsave_escaped(files[i], (char_u *)"\\|\"");
119 if (p != NULL)
120 {
121 vim_free(files[i]);
122 files[i] = p;
123 }
124 }
125 }
126 }
127}
128
129/*
130 * Return FAIL if this is not an appropriate context in which to do
131 * completion of anything, return OK if it is (even if there are no matches).
132 * For the caller, this means that the character is just passed through like a
133 * normal character (instead of being expanded). This allows :s/^I^D etc.
134 */
135 int
136nextwild(
137 expand_T *xp,
138 int type,
139 int options, // extra options for ExpandOne()
140 int escape) // if TRUE, escape the returned matches
141{
142 cmdline_info_T *ccline = get_cmdline_info();
143 int i, j;
144 char_u *p1;
145 char_u *p2;
146 int difflen;
147 int v;
148
149 if (xp->xp_numfiles == -1)
150 {
151 set_expand_context(xp);
152 cmd_showtail = expand_showtail(xp);
153 }
154
155 if (xp->xp_context == EXPAND_UNSUCCESSFUL)
156 {
157 beep_flush();
158 return OK; // Something illegal on command line
159 }
160 if (xp->xp_context == EXPAND_NOTHING)
161 {
162 // Caller can use the character as a normal char instead
163 return FAIL;
164 }
165
166 msg_puts("..."); // show that we are busy
167 out_flush();
168
169 i = (int)(xp->xp_pattern - ccline->cmdbuff);
170 xp->xp_pattern_len = ccline->cmdpos - i;
171
172 if (type == WILD_NEXT || type == WILD_PREV)
173 {
174 // Get next/previous match for a previous expanded pattern.
175 p2 = ExpandOne(xp, NULL, NULL, 0, type);
176 }
177 else
178 {
179 // Translate string into pattern and expand it.
180 if ((p1 = addstar(xp->xp_pattern, xp->xp_pattern_len,
181 xp->xp_context)) == NULL)
182 p2 = NULL;
183 else
184 {
185 int use_options = options |
186 WILD_HOME_REPLACE|WILD_ADD_SLASH|WILD_SILENT;
187 if (escape)
188 use_options |= WILD_ESCAPE;
189
190 if (p_wic)
191 use_options += WILD_ICASE;
192 p2 = ExpandOne(xp, p1,
193 vim_strnsave(&ccline->cmdbuff[i], xp->xp_pattern_len),
194 use_options, type);
195 vim_free(p1);
196 // longest match: make sure it is not shorter, happens with :help
197 if (p2 != NULL && type == WILD_LONGEST)
198 {
199 for (j = 0; j < xp->xp_pattern_len; ++j)
200 if (ccline->cmdbuff[i + j] == '*'
201 || ccline->cmdbuff[i + j] == '?')
202 break;
203 if ((int)STRLEN(p2) < j)
204 VIM_CLEAR(p2);
205 }
206 }
207 }
208
209 if (p2 != NULL && !got_int)
210 {
211 difflen = (int)STRLEN(p2) - xp->xp_pattern_len;
212 if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen)
213 {
214 v = realloc_cmdbuff(ccline->cmdlen + difflen + 4);
215 xp->xp_pattern = ccline->cmdbuff + i;
216 }
217 else
218 v = OK;
219 if (v == OK)
220 {
221 mch_memmove(&ccline->cmdbuff[ccline->cmdpos + difflen],
222 &ccline->cmdbuff[ccline->cmdpos],
223 (size_t)(ccline->cmdlen - ccline->cmdpos + 1));
224 mch_memmove(&ccline->cmdbuff[i], p2, STRLEN(p2));
225 ccline->cmdlen += difflen;
226 ccline->cmdpos += difflen;
227 }
228 }
229 vim_free(p2);
230
231 redrawcmd();
232 cursorcmd();
233
234 // When expanding a ":map" command and no matches are found, assume that
235 // the key is supposed to be inserted literally
236 if (xp->xp_context == EXPAND_MAPPINGS && p2 == NULL)
237 return FAIL;
238
239 if (xp->xp_numfiles <= 0 && p2 == NULL)
240 beep_flush();
241 else if (xp->xp_numfiles == 1)
242 // free expanded pattern
243 (void)ExpandOne(xp, NULL, NULL, 0, WILD_FREE);
244
245 return OK;
246}
247
248/*
249 * Do wildcard expansion on the string 'str'.
250 * Chars that should not be expanded must be preceded with a backslash.
251 * Return a pointer to allocated memory containing the new string.
252 * Return NULL for failure.
253 *
254 * "orig" is the originally expanded string, copied to allocated memory. It
255 * should either be kept in orig_save or freed. When "mode" is WILD_NEXT or
256 * WILD_PREV "orig" should be NULL.
257 *
258 * Results are cached in xp->xp_files and xp->xp_numfiles, except when "mode"
259 * is WILD_EXPAND_FREE or WILD_ALL.
260 *
261 * mode = WILD_FREE: just free previously expanded matches
262 * mode = WILD_EXPAND_FREE: normal expansion, do not keep matches
263 * mode = WILD_EXPAND_KEEP: normal expansion, keep matches
264 * mode = WILD_NEXT: use next match in multiple match, wrap to first
265 * mode = WILD_PREV: use previous match in multiple match, wrap to first
266 * mode = WILD_ALL: return all matches concatenated
267 * mode = WILD_LONGEST: return longest matched part
268 * mode = WILD_ALL_KEEP: get all matches, keep matches
269 *
270 * options = WILD_LIST_NOTFOUND: list entries without a match
271 * options = WILD_HOME_REPLACE: do home_replace() for buffer names
272 * options = WILD_USE_NL: Use '\n' for WILD_ALL
273 * options = WILD_NO_BEEP: Don't beep for multiple matches
274 * options = WILD_ADD_SLASH: add a slash after directory names
275 * options = WILD_KEEP_ALL: don't remove 'wildignore' entries
276 * options = WILD_SILENT: don't print warning messages
277 * options = WILD_ESCAPE: put backslash before special chars
278 * options = WILD_ICASE: ignore case for files
279 *
280 * The variables xp->xp_context and xp->xp_backslash must have been set!
281 */
282 char_u *
283ExpandOne(
284 expand_T *xp,
285 char_u *str,
286 char_u *orig, // allocated copy of original of expanded string
287 int options,
288 int mode)
289{
290 char_u *ss = NULL;
291 static int findex;
292 static char_u *orig_save = NULL; // kept value of orig
293 int orig_saved = FALSE;
294 int i;
295 long_u len;
296 int non_suf_match; // number without matching suffix
297
298 // first handle the case of using an old match
299 if (mode == WILD_NEXT || mode == WILD_PREV)
300 {
301 if (xp->xp_numfiles > 0)
302 {
303 if (mode == WILD_PREV)
304 {
305 if (findex == -1)
306 findex = xp->xp_numfiles;
307 --findex;
308 }
309 else // mode == WILD_NEXT
310 ++findex;
311
312 // When wrapping around, return the original string, set findex to
313 // -1.
314 if (findex < 0)
315 {
316 if (orig_save == NULL)
317 findex = xp->xp_numfiles - 1;
318 else
319 findex = -1;
320 }
321 if (findex >= xp->xp_numfiles)
322 {
323 if (orig_save == NULL)
324 findex = 0;
325 else
326 findex = -1;
327 }
328#ifdef FEAT_WILDMENU
329 if (p_wmnu)
330 win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files,
331 findex, cmd_showtail);
332#endif
333 if (findex == -1)
334 return vim_strsave(orig_save);
335 return vim_strsave(xp->xp_files[findex]);
336 }
337 else
338 return NULL;
339 }
340
341 // free old names
342 if (xp->xp_numfiles != -1 && mode != WILD_ALL && mode != WILD_LONGEST)
343 {
344 FreeWild(xp->xp_numfiles, xp->xp_files);
345 xp->xp_numfiles = -1;
346 VIM_CLEAR(orig_save);
347 }
348 findex = 0;
349
350 if (mode == WILD_FREE) // only release file name
351 return NULL;
352
353 if (xp->xp_numfiles == -1)
354 {
355 vim_free(orig_save);
356 orig_save = orig;
357 orig_saved = TRUE;
358
359 // Do the expansion.
360 if (ExpandFromContext(xp, str, &xp->xp_numfiles, &xp->xp_files,
361 options) == FAIL)
362 {
363#ifdef FNAME_ILLEGAL
364 // Illegal file name has been silently skipped. But when there
365 // are wildcards, the real problem is that there was no match,
366 // causing the pattern to be added, which has illegal characters.
367 if (!(options & WILD_SILENT) && (options & WILD_LIST_NOTFOUND))
368 semsg(_(e_nomatch2), str);
369#endif
370 }
371 else if (xp->xp_numfiles == 0)
372 {
373 if (!(options & WILD_SILENT))
374 semsg(_(e_nomatch2), str);
375 }
376 else
377 {
378 // Escape the matches for use on the command line.
379 ExpandEscape(xp, str, xp->xp_numfiles, xp->xp_files, options);
380
381 // Check for matching suffixes in file names.
382 if (mode != WILD_ALL && mode != WILD_ALL_KEEP
383 && mode != WILD_LONGEST)
384 {
385 if (xp->xp_numfiles)
386 non_suf_match = xp->xp_numfiles;
387 else
388 non_suf_match = 1;
389 if ((xp->xp_context == EXPAND_FILES
390 || xp->xp_context == EXPAND_DIRECTORIES)
391 && xp->xp_numfiles > 1)
392 {
393 // More than one match; check suffix.
394 // The files will have been sorted on matching suffix in
395 // expand_wildcards, only need to check the first two.
396 non_suf_match = 0;
397 for (i = 0; i < 2; ++i)
398 if (match_suffix(xp->xp_files[i]))
399 ++non_suf_match;
400 }
401 if (non_suf_match != 1)
402 {
403 // Can we ever get here unless it's while expanding
404 // interactively? If not, we can get rid of this all
405 // together. Don't really want to wait for this message
406 // (and possibly have to hit return to continue!).
407 if (!(options & WILD_SILENT))
408 emsg(_(e_toomany));
409 else if (!(options & WILD_NO_BEEP))
410 beep_flush();
411 }
412 if (!(non_suf_match != 1 && mode == WILD_EXPAND_FREE))
413 ss = vim_strsave(xp->xp_files[0]);
414 }
415 }
416 }
417
418 // Find longest common part
419 if (mode == WILD_LONGEST && xp->xp_numfiles > 0)
420 {
421 int mb_len = 1;
422 int c0, ci;
423
424 for (len = 0; xp->xp_files[0][len]; len += mb_len)
425 {
426 if (has_mbyte)
427 {
428 mb_len = (*mb_ptr2len)(&xp->xp_files[0][len]);
429 c0 =(* mb_ptr2char)(&xp->xp_files[0][len]);
430 }
431 else
432 c0 = xp->xp_files[0][len];
433 for (i = 1; i < xp->xp_numfiles; ++i)
434 {
435 if (has_mbyte)
436 ci =(* mb_ptr2char)(&xp->xp_files[i][len]);
437 else
438 ci = xp->xp_files[i][len];
439 if (p_fic && (xp->xp_context == EXPAND_DIRECTORIES
440 || xp->xp_context == EXPAND_FILES
441 || xp->xp_context == EXPAND_SHELLCMD
442 || xp->xp_context == EXPAND_BUFFERS))
443 {
444 if (MB_TOLOWER(c0) != MB_TOLOWER(ci))
445 break;
446 }
447 else if (c0 != ci)
448 break;
449 }
450 if (i < xp->xp_numfiles)
451 {
452 if (!(options & WILD_NO_BEEP))
453 vim_beep(BO_WILD);
454 break;
455 }
456 }
457
458 ss = alloc(len + 1);
459 if (ss)
460 vim_strncpy(ss, xp->xp_files[0], (size_t)len);
461 findex = -1; // next p_wc gets first one
462 }
463
464 // Concatenate all matching names
465 if (mode == WILD_ALL && xp->xp_numfiles > 0)
466 {
467 len = 0;
468 for (i = 0; i < xp->xp_numfiles; ++i)
469 len += (long_u)STRLEN(xp->xp_files[i]) + 1;
470 ss = alloc(len);
471 if (ss != NULL)
472 {
473 *ss = NUL;
474 for (i = 0; i < xp->xp_numfiles; ++i)
475 {
476 STRCAT(ss, xp->xp_files[i]);
477 if (i != xp->xp_numfiles - 1)
478 STRCAT(ss, (options & WILD_USE_NL) ? "\n" : " ");
479 }
480 }
481 }
482
483 if (mode == WILD_EXPAND_FREE || mode == WILD_ALL)
484 ExpandCleanup(xp);
485
486 // Free "orig" if it wasn't stored in "orig_save".
487 if (!orig_saved)
488 vim_free(orig);
489
490 return ss;
491}
492
493/*
494 * Prepare an expand structure for use.
495 */
496 void
497ExpandInit(expand_T *xp)
498{
499 xp->xp_pattern = NULL;
500 xp->xp_pattern_len = 0;
501 xp->xp_backslash = XP_BS_NONE;
502#ifndef BACKSLASH_IN_FILENAME
503 xp->xp_shell = FALSE;
504#endif
505 xp->xp_numfiles = -1;
506 xp->xp_files = NULL;
507#if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
508 xp->xp_arg = NULL;
509#endif
510 xp->xp_line = NULL;
511}
512
513/*
514 * Cleanup an expand structure after use.
515 */
516 void
517ExpandCleanup(expand_T *xp)
518{
519 if (xp->xp_numfiles >= 0)
520 {
521 FreeWild(xp->xp_numfiles, xp->xp_files);
522 xp->xp_numfiles = -1;
523 }
524}
525
526/*
527 * Show all matches for completion on the command line.
528 * Returns EXPAND_NOTHING when the character that triggered expansion should
529 * be inserted like a normal character.
530 */
531 int
532showmatches(expand_T *xp, int wildmenu UNUSED)
533{
534 cmdline_info_T *ccline = get_cmdline_info();
535#define L_SHOWFILE(m) (showtail ? sm_gettail(files_found[m]) : files_found[m])
536 int num_files;
537 char_u **files_found;
538 int i, j, k;
539 int maxlen;
540 int lines;
541 int columns;
542 char_u *p;
543 int lastlen;
544 int attr;
545 int showtail;
546
547 if (xp->xp_numfiles == -1)
548 {
549 set_expand_context(xp);
550 i = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos,
551 &num_files, &files_found);
552 showtail = expand_showtail(xp);
553 if (i != EXPAND_OK)
554 return i;
555
556 }
557 else
558 {
559 num_files = xp->xp_numfiles;
560 files_found = xp->xp_files;
561 showtail = cmd_showtail;
562 }
563
564#ifdef FEAT_WILDMENU
565 if (!wildmenu)
566 {
567#endif
568 msg_didany = FALSE; // lines_left will be set
569 msg_start(); // prepare for paging
570 msg_putchar('\n');
571 out_flush();
572 cmdline_row = msg_row;
573 msg_didany = FALSE; // lines_left will be set again
574 msg_start(); // prepare for paging
575#ifdef FEAT_WILDMENU
576 }
577#endif
578
579 if (got_int)
580 got_int = FALSE; // only int. the completion, not the cmd line
581#ifdef FEAT_WILDMENU
582 else if (wildmenu)
583 win_redr_status_matches(xp, num_files, files_found, -1, showtail);
584#endif
585 else
586 {
587 // find the length of the longest file name
588 maxlen = 0;
589 for (i = 0; i < num_files; ++i)
590 {
591 if (!showtail && (xp->xp_context == EXPAND_FILES
592 || xp->xp_context == EXPAND_SHELLCMD
593 || xp->xp_context == EXPAND_BUFFERS))
594 {
595 home_replace(NULL, files_found[i], NameBuff, MAXPATHL, TRUE);
596 j = vim_strsize(NameBuff);
597 }
598 else
599 j = vim_strsize(L_SHOWFILE(i));
600 if (j > maxlen)
601 maxlen = j;
602 }
603
604 if (xp->xp_context == EXPAND_TAGS_LISTFILES)
605 lines = num_files;
606 else
607 {
608 // compute the number of columns and lines for the listing
609 maxlen += 2; // two spaces between file names
610 columns = ((int)Columns + 2) / maxlen;
611 if (columns < 1)
612 columns = 1;
613 lines = (num_files + columns - 1) / columns;
614 }
615
616 attr = HL_ATTR(HLF_D); // find out highlighting for directories
617
618 if (xp->xp_context == EXPAND_TAGS_LISTFILES)
619 {
620 msg_puts_attr(_("tagname"), HL_ATTR(HLF_T));
621 msg_clr_eos();
622 msg_advance(maxlen - 3);
623 msg_puts_attr(_(" kind file\n"), HL_ATTR(HLF_T));
624 }
625
626 // list the files line by line
627 for (i = 0; i < lines; ++i)
628 {
629 lastlen = 999;
630 for (k = i; k < num_files; k += lines)
631 {
632 if (xp->xp_context == EXPAND_TAGS_LISTFILES)
633 {
634 msg_outtrans_attr(files_found[k], HL_ATTR(HLF_D));
635 p = files_found[k] + STRLEN(files_found[k]) + 1;
636 msg_advance(maxlen + 1);
637 msg_puts((char *)p);
638 msg_advance(maxlen + 3);
639 msg_outtrans_long_attr(p + 2, HL_ATTR(HLF_D));
640 break;
641 }
642 for (j = maxlen - lastlen; --j >= 0; )
643 msg_putchar(' ');
644 if (xp->xp_context == EXPAND_FILES
645 || xp->xp_context == EXPAND_SHELLCMD
646 || xp->xp_context == EXPAND_BUFFERS)
647 {
648 // highlight directories
649 if (xp->xp_numfiles != -1)
650 {
651 char_u *halved_slash;
652 char_u *exp_path;
653
654 // Expansion was done before and special characters
655 // were escaped, need to halve backslashes. Also
656 // $HOME has been replaced with ~/.
657 exp_path = expand_env_save_opt(files_found[k], TRUE);
658 halved_slash = backslash_halve_save(
659 exp_path != NULL ? exp_path : files_found[k]);
660 j = mch_isdir(halved_slash != NULL ? halved_slash
661 : files_found[k]);
662 vim_free(exp_path);
663 vim_free(halved_slash);
664 }
665 else
666 // Expansion was done here, file names are literal.
667 j = mch_isdir(files_found[k]);
668 if (showtail)
669 p = L_SHOWFILE(k);
670 else
671 {
672 home_replace(NULL, files_found[k], NameBuff, MAXPATHL,
673 TRUE);
674 p = NameBuff;
675 }
676 }
677 else
678 {
679 j = FALSE;
680 p = L_SHOWFILE(k);
681 }
682 lastlen = msg_outtrans_attr(p, j ? attr : 0);
683 }
684 if (msg_col > 0) // when not wrapped around
685 {
686 msg_clr_eos();
687 msg_putchar('\n');
688 }
689 out_flush(); // show one line at a time
690 if (got_int)
691 {
692 got_int = FALSE;
693 break;
694 }
695 }
696
697 // we redraw the command below the lines that we have just listed
698 // This is a bit tricky, but it saves a lot of screen updating.
699 cmdline_row = msg_row; // will put it back later
700 }
701
702 if (xp->xp_numfiles == -1)
703 FreeWild(num_files, files_found);
704
705 return EXPAND_OK;
706}
707
708/*
709 * Private gettail for showmatches() (and win_redr_status_matches()):
710 * Find tail of file name path, but ignore trailing "/".
711 */
712 char_u *
713sm_gettail(char_u *s)
714{
715 char_u *p;
716 char_u *t = s;
717 int had_sep = FALSE;
718
719 for (p = s; *p != NUL; )
720 {
721 if (vim_ispathsep(*p)
722#ifdef BACKSLASH_IN_FILENAME
723 && !rem_backslash(p)
724#endif
725 )
726 had_sep = TRUE;
727 else if (had_sep)
728 {
729 t = p;
730 had_sep = FALSE;
731 }
732 MB_PTR_ADV(p);
733 }
734 return t;
735}
736
737/*
738 * Return TRUE if we only need to show the tail of completion matches.
739 * When not completing file names or there is a wildcard in the path FALSE is
740 * returned.
741 */
742 static int
743expand_showtail(expand_T *xp)
744{
745 char_u *s;
746 char_u *end;
747
748 // When not completing file names a "/" may mean something different.
749 if (xp->xp_context != EXPAND_FILES
750 && xp->xp_context != EXPAND_SHELLCMD
751 && xp->xp_context != EXPAND_DIRECTORIES)
752 return FALSE;
753
754 end = gettail(xp->xp_pattern);
755 if (end == xp->xp_pattern) // there is no path separator
756 return FALSE;
757
758 for (s = xp->xp_pattern; s < end; s++)
759 {
760 // Skip escaped wildcards. Only when the backslash is not a path
761 // separator, on DOS the '*' "path\*\file" must not be skipped.
762 if (rem_backslash(s))
763 ++s;
764 else if (vim_strchr((char_u *)"*?[", *s) != NULL)
765 return FALSE;
766 }
767 return TRUE;
768}
769
770/*
771 * Prepare a string for expansion.
772 * When expanding file names: The string will be used with expand_wildcards().
773 * Copy "fname[len]" into allocated memory and add a '*' at the end.
774 * When expanding other names: The string will be used with regcomp(). Copy
775 * the name into allocated memory and prepend "^".
776 */
777 char_u *
778addstar(
779 char_u *fname,
780 int len,
781 int context) // EXPAND_FILES etc.
782{
783 char_u *retval;
784 int i, j;
785 int new_len;
786 char_u *tail;
787 int ends_in_star;
788
789 if (context != EXPAND_FILES
790 && context != EXPAND_FILES_IN_PATH
791 && context != EXPAND_SHELLCMD
792 && context != EXPAND_DIRECTORIES)
793 {
794 // Matching will be done internally (on something other than files).
795 // So we convert the file-matching-type wildcards into our kind for
796 // use with vim_regcomp(). First work out how long it will be:
797
798 // For help tags the translation is done in find_help_tags().
799 // For a tag pattern starting with "/" no translation is needed.
800 if (context == EXPAND_HELP
801 || context == EXPAND_COLORS
802 || context == EXPAND_COMPILER
803 || context == EXPAND_OWNSYNTAX
804 || context == EXPAND_FILETYPE
805 || context == EXPAND_PACKADD
806 || ((context == EXPAND_TAGS_LISTFILES
807 || context == EXPAND_TAGS)
808 && fname[0] == '/'))
809 retval = vim_strnsave(fname, len);
810 else
811 {
812 new_len = len + 2; // +2 for '^' at start, NUL at end
813 for (i = 0; i < len; i++)
814 {
815 if (fname[i] == '*' || fname[i] == '~')
816 new_len++; // '*' needs to be replaced by ".*"
817 // '~' needs to be replaced by "\~"
818
819 // Buffer names are like file names. "." should be literal
820 if (context == EXPAND_BUFFERS && fname[i] == '.')
821 new_len++; // "." becomes "\."
822
823 // Custom expansion takes care of special things, match
824 // backslashes literally (perhaps also for other types?)
825 if ((context == EXPAND_USER_DEFINED
826 || context == EXPAND_USER_LIST) && fname[i] == '\\')
827 new_len++; // '\' becomes "\\"
828 }
829 retval = alloc(new_len);
830 if (retval != NULL)
831 {
832 retval[0] = '^';
833 j = 1;
834 for (i = 0; i < len; i++, j++)
835 {
836 // Skip backslash. But why? At least keep it for custom
837 // expansion.
838 if (context != EXPAND_USER_DEFINED
839 && context != EXPAND_USER_LIST
840 && fname[i] == '\\'
841 && ++i == len)
842 break;
843
844 switch (fname[i])
845 {
846 case '*': retval[j++] = '.';
847 break;
848 case '~': retval[j++] = '\\';
849 break;
850 case '?': retval[j] = '.';
851 continue;
852 case '.': if (context == EXPAND_BUFFERS)
853 retval[j++] = '\\';
854 break;
855 case '\\': if (context == EXPAND_USER_DEFINED
856 || context == EXPAND_USER_LIST)
857 retval[j++] = '\\';
858 break;
859 }
860 retval[j] = fname[i];
861 }
862 retval[j] = NUL;
863 }
864 }
865 }
866 else
867 {
868 retval = alloc(len + 4);
869 if (retval != NULL)
870 {
871 vim_strncpy(retval, fname, len);
872
873 // Don't add a star to *, ~, ~user, $var or `cmd`.
874 // * would become **, which walks the whole tree.
875 // ~ would be at the start of the file name, but not the tail.
876 // $ could be anywhere in the tail.
877 // ` could be anywhere in the file name.
878 // When the name ends in '$' don't add a star, remove the '$'.
879 tail = gettail(retval);
880 ends_in_star = (len > 0 && retval[len - 1] == '*');
881#ifndef BACKSLASH_IN_FILENAME
882 for (i = len - 2; i >= 0; --i)
883 {
884 if (retval[i] != '\\')
885 break;
886 ends_in_star = !ends_in_star;
887 }
888#endif
889 if ((*retval != '~' || tail != retval)
890 && !ends_in_star
891 && vim_strchr(tail, '$') == NULL
892 && vim_strchr(retval, '`') == NULL)
893 retval[len++] = '*';
894 else if (len > 0 && retval[len - 1] == '$')
895 --len;
896 retval[len] = NUL;
897 }
898 }
899 return retval;
900}
901
902/*
903 * Must parse the command line so far to work out what context we are in.
904 * Completion can then be done based on that context.
905 * This routine sets the variables:
906 * xp->xp_pattern The start of the pattern to be expanded within
907 * the command line (ends at the cursor).
908 * xp->xp_context The type of thing to expand. Will be one of:
909 *
910 * EXPAND_UNSUCCESSFUL Used sometimes when there is something illegal on
911 * the command line, like an unknown command. Caller
912 * should beep.
913 * EXPAND_NOTHING Unrecognised context for completion, use char like
914 * a normal char, rather than for completion. eg
915 * :s/^I/
916 * EXPAND_COMMANDS Cursor is still touching the command, so complete
917 * it.
918 * EXPAND_BUFFERS Complete file names for :buf and :sbuf commands.
919 * EXPAND_FILES After command with EX_XFILE set, or after setting
920 * with P_EXPAND set. eg :e ^I, :w>>^I
921 * EXPAND_DIRECTORIES In some cases this is used instead of the latter
922 * when we know only directories are of interest. eg
923 * :set dir=^I
924 * EXPAND_SHELLCMD After ":!cmd", ":r !cmd" or ":w !cmd".
925 * EXPAND_SETTINGS Complete variable names. eg :set d^I
926 * EXPAND_BOOL_SETTINGS Complete boolean variables only, eg :set no^I
927 * EXPAND_TAGS Complete tags from the files in p_tags. eg :ta a^I
928 * EXPAND_TAGS_LISTFILES As above, but list filenames on ^D, after :tselect
929 * EXPAND_HELP Complete tags from the file 'helpfile'/tags
930 * EXPAND_EVENTS Complete event names
931 * EXPAND_SYNTAX Complete :syntax command arguments
932 * EXPAND_HIGHLIGHT Complete highlight (syntax) group names
933 * EXPAND_AUGROUP Complete autocommand group names
934 * EXPAND_USER_VARS Complete user defined variable names, eg :unlet a^I
935 * EXPAND_MAPPINGS Complete mapping and abbreviation names,
936 * eg :unmap a^I , :cunab x^I
937 * EXPAND_FUNCTIONS Complete internal or user defined function names,
938 * eg :call sub^I
939 * EXPAND_USER_FUNC Complete user defined function names, eg :delf F^I
940 * EXPAND_EXPRESSION Complete internal or user defined function/variable
941 * names in expressions, eg :while s^I
942 * EXPAND_ENV_VARS Complete environment variable names
943 * EXPAND_USER Complete user names
944 */
945 static void
946set_expand_context(expand_T *xp)
947{
948 cmdline_info_T *ccline = get_cmdline_info();
949
950 // only expansion for ':', '>' and '=' command-lines
951 if (ccline->cmdfirstc != ':'
952#ifdef FEAT_EVAL
953 && ccline->cmdfirstc != '>' && ccline->cmdfirstc != '='
954 && !ccline->input_fn
955#endif
956 )
957 {
958 xp->xp_context = EXPAND_NOTHING;
959 return;
960 }
961 set_cmd_context(xp, ccline->cmdbuff, ccline->cmdlen, ccline->cmdpos, TRUE);
962}
963
964 void
965set_cmd_context(
966 expand_T *xp,
967 char_u *str, // start of command line
968 int len, // length of command line (excl. NUL)
969 int col, // position of cursor
970 int use_ccline UNUSED) // use ccline for info
971{
972#ifdef FEAT_EVAL
973 cmdline_info_T *ccline = get_cmdline_info();
974#endif
975 int old_char = NUL;
976 char_u *nextcomm;
977
978 // Avoid a UMR warning from Purify, only save the character if it has been
979 // written before.
980 if (col < len)
981 old_char = str[col];
982 str[col] = NUL;
983 nextcomm = str;
984
985#ifdef FEAT_EVAL
986 if (use_ccline && ccline->cmdfirstc == '=')
987 {
988# ifdef FEAT_CMDL_COMPL
989 // pass CMD_SIZE because there is no real command
990 set_context_for_expression(xp, str, CMD_SIZE);
991# endif
992 }
993 else if (use_ccline && ccline->input_fn)
994 {
995 xp->xp_context = ccline->xp_context;
996 xp->xp_pattern = ccline->cmdbuff;
997# if defined(FEAT_CMDL_COMPL)
998 xp->xp_arg = ccline->xp_arg;
999# endif
1000 }
1001 else
1002#endif
1003 while (nextcomm != NULL)
1004 nextcomm = set_one_cmd_context(xp, nextcomm);
1005
1006 // Store the string here so that call_user_expand_func() can get to them
1007 // easily.
1008 xp->xp_line = str;
1009 xp->xp_col = col;
1010
1011 str[col] = old_char;
1012}
1013
1014/*
1015 * Expand the command line "str" from context "xp".
1016 * "xp" must have been set by set_cmd_context().
1017 * xp->xp_pattern points into "str", to where the text that is to be expanded
1018 * starts.
1019 * Returns EXPAND_UNSUCCESSFUL when there is something illegal before the
1020 * cursor.
1021 * Returns EXPAND_NOTHING when there is nothing to expand, might insert the
1022 * key that triggered expansion literally.
1023 * Returns EXPAND_OK otherwise.
1024 */
1025 int
1026expand_cmdline(
1027 expand_T *xp,
1028 char_u *str, // start of command line
1029 int col, // position of cursor
1030 int *matchcount, // return: nr of matches
1031 char_u ***matches) // return: array of pointers to matches
1032{
1033 char_u *file_str = NULL;
1034 int options = WILD_ADD_SLASH|WILD_SILENT;
1035
1036 if (xp->xp_context == EXPAND_UNSUCCESSFUL)
1037 {
1038 beep_flush();
1039 return EXPAND_UNSUCCESSFUL; // Something illegal on command line
1040 }
1041 if (xp->xp_context == EXPAND_NOTHING)
1042 {
1043 // Caller can use the character as a normal char instead
1044 return EXPAND_NOTHING;
1045 }
1046
1047 // add star to file name, or convert to regexp if not exp. files.
1048 xp->xp_pattern_len = (int)(str + col - xp->xp_pattern);
1049 file_str = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
1050 if (file_str == NULL)
1051 return EXPAND_UNSUCCESSFUL;
1052
1053 if (p_wic)
1054 options += WILD_ICASE;
1055
1056 // find all files that match the description
1057 if (ExpandFromContext(xp, file_str, matchcount, matches, options) == FAIL)
1058 {
1059 *matchcount = 0;
1060 *matches = NULL;
1061 }
1062 vim_free(file_str);
1063
1064 return EXPAND_OK;
1065}
1066
1067#ifdef FEAT_MULTI_LANG
1068/*
1069 * Cleanup matches for help tags:
1070 * Remove "@ab" if the top of 'helplang' is "ab" and the language of the first
1071 * tag matches it. Otherwise remove "@en" if "en" is the only language.
1072 */
1073 static void
1074cleanup_help_tags(int num_file, char_u **file)
1075{
1076 int i, j;
1077 int len;
1078 char_u buf[4];
1079 char_u *p = buf;
1080
1081 if (p_hlg[0] != NUL && (p_hlg[0] != 'e' || p_hlg[1] != 'n'))
1082 {
1083 *p++ = '@';
1084 *p++ = p_hlg[0];
1085 *p++ = p_hlg[1];
1086 }
1087 *p = NUL;
1088
1089 for (i = 0; i < num_file; ++i)
1090 {
1091 len = (int)STRLEN(file[i]) - 3;
1092 if (len <= 0)
1093 continue;
1094 if (STRCMP(file[i] + len, "@en") == 0)
1095 {
1096 // Sorting on priority means the same item in another language may
1097 // be anywhere. Search all items for a match up to the "@en".
1098 for (j = 0; j < num_file; ++j)
1099 if (j != i && (int)STRLEN(file[j]) == len + 3
1100 && STRNCMP(file[i], file[j], len + 1) == 0)
1101 break;
1102 if (j == num_file)
1103 // item only exists with @en, remove it
1104 file[i][len] = NUL;
1105 }
1106 }
1107
1108 if (*buf != NUL)
1109 for (i = 0; i < num_file; ++i)
1110 {
1111 len = (int)STRLEN(file[i]) - 3;
1112 if (len <= 0)
1113 continue;
1114 if (STRCMP(file[i] + len, buf) == 0)
1115 {
1116 // remove the default language
1117 file[i][len] = NUL;
1118 }
1119 }
1120}
1121#endif
1122
1123/*
1124 * Do the expansion based on xp->xp_context and "pat".
1125 */
1126 static int
1127ExpandFromContext(
1128 expand_T *xp,
1129 char_u *pat,
1130 int *num_file,
1131 char_u ***file,
1132 int options) // WILD_ flags
1133{
1134#ifdef FEAT_CMDL_COMPL
1135 regmatch_T regmatch;
1136#endif
1137 int ret;
1138 int flags;
1139
1140 flags = EW_DIR; // include directories
1141 if (options & WILD_LIST_NOTFOUND)
1142 flags |= EW_NOTFOUND;
1143 if (options & WILD_ADD_SLASH)
1144 flags |= EW_ADDSLASH;
1145 if (options & WILD_KEEP_ALL)
1146 flags |= EW_KEEPALL;
1147 if (options & WILD_SILENT)
1148 flags |= EW_SILENT;
1149 if (options & WILD_ALLLINKS)
1150 flags |= EW_ALLLINKS;
1151
1152 if (xp->xp_context == EXPAND_FILES
1153 || xp->xp_context == EXPAND_DIRECTORIES
1154 || xp->xp_context == EXPAND_FILES_IN_PATH)
1155 {
1156 // Expand file or directory names.
1157 int free_pat = FALSE;
1158 int i;
1159
1160 // for ":set path=" and ":set tags=" halve backslashes for escaped
1161 // space
1162 if (xp->xp_backslash != XP_BS_NONE)
1163 {
1164 free_pat = TRUE;
1165 pat = vim_strsave(pat);
1166 for (i = 0; pat[i]; ++i)
1167 if (pat[i] == '\\')
1168 {
1169 if (xp->xp_backslash == XP_BS_THREE
1170 && pat[i + 1] == '\\'
1171 && pat[i + 2] == '\\'
1172 && pat[i + 3] == ' ')
1173 STRMOVE(pat + i, pat + i + 3);
1174 if (xp->xp_backslash == XP_BS_ONE
1175 && pat[i + 1] == ' ')
1176 STRMOVE(pat + i, pat + i + 1);
1177 }
1178 }
1179
1180 if (xp->xp_context == EXPAND_FILES)
1181 flags |= EW_FILE;
1182 else if (xp->xp_context == EXPAND_FILES_IN_PATH)
1183 flags |= (EW_FILE | EW_PATH);
1184 else
1185 flags = (flags | EW_DIR) & ~EW_FILE;
1186 if (options & WILD_ICASE)
1187 flags |= EW_ICASE;
1188
1189 // Expand wildcards, supporting %:h and the like.
1190 ret = expand_wildcards_eval(&pat, num_file, file, flags);
1191 if (free_pat)
1192 vim_free(pat);
1193#ifdef BACKSLASH_IN_FILENAME
1194 if (p_csl[0] != NUL && (options & WILD_IGNORE_COMPLETESLASH) == 0)
1195 {
1196 int i;
1197
1198 for (i = 0; i < *num_file; ++i)
1199 {
1200 char_u *ptr = (*file)[i];
1201
1202 while (*ptr != NUL)
1203 {
1204 if (p_csl[0] == 's' && *ptr == '\\')
1205 *ptr = '/';
1206 else if (p_csl[0] == 'b' && *ptr == '/')
1207 *ptr = '\\';
1208 ptr += (*mb_ptr2len)(ptr);
1209 }
1210 }
1211 }
1212#endif
1213 return ret;
1214 }
1215
1216 *file = (char_u **)"";
1217 *num_file = 0;
1218 if (xp->xp_context == EXPAND_HELP)
1219 {
1220 // With an empty argument we would get all the help tags, which is
1221 // very slow. Get matches for "help" instead.
1222 if (find_help_tags(*pat == NUL ? (char_u *)"help" : pat,
1223 num_file, file, FALSE) == OK)
1224 {
1225#ifdef FEAT_MULTI_LANG
1226 cleanup_help_tags(*num_file, *file);
1227#endif
1228 return OK;
1229 }
1230 return FAIL;
1231 }
1232
1233#ifndef FEAT_CMDL_COMPL
1234 return FAIL;
1235#else
1236 if (xp->xp_context == EXPAND_SHELLCMD)
1237 return expand_shellcmd(pat, num_file, file, flags);
1238 if (xp->xp_context == EXPAND_OLD_SETTING)
1239 return ExpandOldSetting(num_file, file);
1240 if (xp->xp_context == EXPAND_BUFFERS)
1241 return ExpandBufnames(pat, num_file, file, options);
1242 if (xp->xp_context == EXPAND_TAGS
1243 || xp->xp_context == EXPAND_TAGS_LISTFILES)
1244 return expand_tags(xp->xp_context == EXPAND_TAGS, pat, num_file, file);
1245 if (xp->xp_context == EXPAND_COLORS)
1246 {
1247 char *directories[] = {"colors", NULL};
1248 return ExpandRTDir(pat, DIP_START + DIP_OPT, num_file, file,
1249 directories);
1250 }
1251 if (xp->xp_context == EXPAND_COMPILER)
1252 {
1253 char *directories[] = {"compiler", NULL};
1254 return ExpandRTDir(pat, 0, num_file, file, directories);
1255 }
1256 if (xp->xp_context == EXPAND_OWNSYNTAX)
1257 {
1258 char *directories[] = {"syntax", NULL};
1259 return ExpandRTDir(pat, 0, num_file, file, directories);
1260 }
1261 if (xp->xp_context == EXPAND_FILETYPE)
1262 {
1263 char *directories[] = {"syntax", "indent", "ftplugin", NULL};
1264 return ExpandRTDir(pat, 0, num_file, file, directories);
1265 }
1266# if defined(FEAT_EVAL)
1267 if (xp->xp_context == EXPAND_USER_LIST)
1268 return ExpandUserList(xp, num_file, file);
1269# endif
1270 if (xp->xp_context == EXPAND_PACKADD)
1271 return ExpandPackAddDir(pat, num_file, file);
1272
1273 regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
1274 if (regmatch.regprog == NULL)
1275 return FAIL;
1276
1277 // set ignore-case according to p_ic, p_scs and pat
1278 regmatch.rm_ic = ignorecase(pat);
1279
1280 if (xp->xp_context == EXPAND_SETTINGS
1281 || xp->xp_context == EXPAND_BOOL_SETTINGS)
1282 ret = ExpandSettings(xp, &regmatch, num_file, file);
1283 else if (xp->xp_context == EXPAND_MAPPINGS)
1284 ret = ExpandMappings(&regmatch, num_file, file);
1285# if defined(FEAT_EVAL)
1286 else if (xp->xp_context == EXPAND_USER_DEFINED)
1287 ret = ExpandUserDefined(xp, &regmatch, num_file, file);
1288# endif
1289 else
1290 {
1291 static struct expgen
1292 {
1293 int context;
1294 char_u *((*func)(expand_T *, int));
1295 int ic;
1296 int escaped;
1297 } tab[] =
1298 {
1299 {EXPAND_COMMANDS, get_command_name, FALSE, TRUE},
1300 {EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE},
1301 {EXPAND_MAPCLEAR, get_mapclear_arg, TRUE, TRUE},
1302 {EXPAND_MESSAGES, get_messages_arg, TRUE, TRUE},
1303 {EXPAND_HISTORY, get_history_arg, TRUE, TRUE},
1304 {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE},
1305 {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE},
1306 {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE},
1307 {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE},
1308 {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE},
1309# ifdef FEAT_EVAL
1310 {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE},
1311 {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE},
1312 {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE},
1313 {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE},
1314# endif
1315# ifdef FEAT_MENU
1316 {EXPAND_MENUS, get_menu_name, FALSE, TRUE},
1317 {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE},
1318# endif
1319# ifdef FEAT_SYN_HL
1320 {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE},
1321# endif
1322# ifdef FEAT_PROFILE
1323 {EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE},
1324# endif
1325 {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE},
1326 {EXPAND_EVENTS, get_event_name, TRUE, TRUE},
1327 {EXPAND_AUGROUP, get_augroup_name, TRUE, TRUE},
1328# ifdef FEAT_CSCOPE
1329 {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE},
1330# endif
1331# ifdef FEAT_SIGNS
1332 {EXPAND_SIGN, get_sign_name, TRUE, TRUE},
1333# endif
1334# ifdef FEAT_PROFILE
1335 {EXPAND_PROFILE, get_profile_name, TRUE, TRUE},
1336# endif
1337# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
1338 {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE},
1339 {EXPAND_LOCALES, get_locales, TRUE, FALSE},
1340# endif
1341 {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE},
1342 {EXPAND_USER, get_users, TRUE, FALSE},
1343 {EXPAND_ARGLIST, get_arglist_name, TRUE, FALSE},
1344 };
1345 int i;
1346
1347 // Find a context in the table and call the ExpandGeneric() with the
1348 // right function to do the expansion.
1349 ret = FAIL;
1350 for (i = 0; i < (int)(sizeof(tab) / sizeof(struct expgen)); ++i)
1351 if (xp->xp_context == tab[i].context)
1352 {
1353 if (tab[i].ic)
1354 regmatch.rm_ic = TRUE;
1355 ret = ExpandGeneric(xp, &regmatch, num_file, file,
1356 tab[i].func, tab[i].escaped);
1357 break;
1358 }
1359 }
1360
1361 vim_regfree(regmatch.regprog);
1362
1363 return ret;
1364#endif // FEAT_CMDL_COMPL
1365}
1366
1367#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
1368/*
1369 * Expand a list of names.
1370 *
1371 * Generic function for command line completion. It calls a function to
1372 * obtain strings, one by one. The strings are matched against a regexp
1373 * program. Matching strings are copied into an array, which is returned.
1374 *
1375 * Returns OK when no problems encountered, FAIL for error (out of memory).
1376 */
1377 int
1378ExpandGeneric(
1379 expand_T *xp,
1380 regmatch_T *regmatch,
1381 int *num_file,
1382 char_u ***file,
1383 char_u *((*func)(expand_T *, int)),
1384 // returns a string from the list
1385 int escaped)
1386{
1387 int i;
1388 int count = 0;
1389 int round;
1390 char_u *str;
1391
1392 // do this loop twice:
1393 // round == 0: count the number of matching names
1394 // round == 1: copy the matching names into allocated memory
1395 for (round = 0; round <= 1; ++round)
1396 {
1397 for (i = 0; ; ++i)
1398 {
1399 str = (*func)(xp, i);
1400 if (str == NULL) // end of list
1401 break;
1402 if (*str == NUL) // skip empty strings
1403 continue;
1404
1405 if (vim_regexec(regmatch, str, (colnr_T)0))
1406 {
1407 if (round)
1408 {
1409 if (escaped)
1410 str = vim_strsave_escaped(str, (char_u *)" \t\\.");
1411 else
1412 str = vim_strsave(str);
1413 (*file)[count] = str;
1414# ifdef FEAT_MENU
1415 if (func == get_menu_names && str != NULL)
1416 {
1417 // test for separator added by get_menu_names()
1418 str += STRLEN(str) - 1;
1419 if (*str == '\001')
1420 *str = '.';
1421 }
1422# endif
1423 }
1424 ++count;
1425 }
1426 }
1427 if (round == 0)
1428 {
1429 if (count == 0)
1430 return OK;
1431 *num_file = count;
1432 *file = ALLOC_MULT(char_u *, count);
1433 if (*file == NULL)
1434 {
1435 *file = (char_u **)"";
1436 return FAIL;
1437 }
1438 count = 0;
1439 }
1440 }
1441
1442 // Sort the results. Keep menu's in the specified order.
1443 if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS)
1444 {
1445 if (xp->xp_context == EXPAND_EXPRESSION
1446 || xp->xp_context == EXPAND_FUNCTIONS
1447 || xp->xp_context == EXPAND_USER_FUNC)
1448 // <SNR> functions should be sorted to the end.
1449 qsort((void *)*file, (size_t)*num_file, sizeof(char_u *),
1450 sort_func_compare);
1451 else
1452 sort_strings(*file, *num_file);
1453 }
1454
1455# ifdef FEAT_CMDL_COMPL
1456 // Reset the variables used for special highlight names expansion, so that
1457 // they don't show up when getting normal highlight names by ID.
1458 reset_expand_highlight();
1459# endif
1460
1461 return OK;
1462}
1463
1464/*
1465 * Complete a shell command.
1466 * Returns FAIL or OK;
1467 */
1468 static int
1469expand_shellcmd(
1470 char_u *filepat, // pattern to match with command names
1471 int *num_file, // return: number of matches
1472 char_u ***file, // return: array with matches
1473 int flagsarg) // EW_ flags
1474{
1475 char_u *pat;
1476 int i;
1477 char_u *path = NULL;
1478 int mustfree = FALSE;
1479 garray_T ga;
1480 char_u *buf = alloc(MAXPATHL);
1481 size_t l;
1482 char_u *s, *e;
1483 int flags = flagsarg;
1484 int ret;
1485 int did_curdir = FALSE;
1486 hashtab_T found_ht;
1487 hashitem_T *hi;
1488 hash_T hash;
1489
1490 if (buf == NULL)
1491 return FAIL;
1492
1493 // for ":set path=" and ":set tags=" halve backslashes for escaped
1494 // space
1495 pat = vim_strsave(filepat);
1496 for (i = 0; pat[i]; ++i)
1497 if (pat[i] == '\\' && pat[i + 1] == ' ')
1498 STRMOVE(pat + i, pat + i + 1);
1499
1500 flags |= EW_FILE | EW_EXEC | EW_SHELLCMD;
1501
1502 if (pat[0] == '.' && (vim_ispathsep(pat[1])
1503 || (pat[1] == '.' && vim_ispathsep(pat[2]))))
1504 path = (char_u *)".";
1505 else
1506 {
1507 // For an absolute name we don't use $PATH.
1508 if (!mch_isFullName(pat))
1509 path = vim_getenv((char_u *)"PATH", &mustfree);
1510 if (path == NULL)
1511 path = (char_u *)"";
1512 }
1513
1514 // Go over all directories in $PATH. Expand matches in that directory and
1515 // collect them in "ga". When "." is not in $PATH also expand for the
1516 // current directory, to find "subdir/cmd".
1517 ga_init2(&ga, (int)sizeof(char *), 10);
1518 hash_init(&found_ht);
1519 for (s = path; ; s = e)
1520 {
1521# if defined(MSWIN)
1522 e = vim_strchr(s, ';');
1523# else
1524 e = vim_strchr(s, ':');
1525# endif
1526 if (e == NULL)
1527 e = s + STRLEN(s);
1528
1529 if (*s == NUL)
1530 {
1531 if (did_curdir)
1532 break;
1533 // Find directories in the current directory, path is empty.
1534 did_curdir = TRUE;
1535 flags |= EW_DIR;
1536 }
1537 else if (STRNCMP(s, ".", (int)(e - s)) == 0)
1538 {
1539 did_curdir = TRUE;
1540 flags |= EW_DIR;
1541 }
1542 else
1543 // Do not match directories inside a $PATH item.
1544 flags &= ~EW_DIR;
1545
1546 l = e - s;
1547 if (l > MAXPATHL - 5)
1548 break;
1549 vim_strncpy(buf, s, l);
1550 add_pathsep(buf);
1551 l = STRLEN(buf);
1552 vim_strncpy(buf + l, pat, MAXPATHL - 1 - l);
1553
1554 // Expand matches in one directory of $PATH.
1555 ret = expand_wildcards(1, &buf, num_file, file, flags);
1556 if (ret == OK)
1557 {
1558 if (ga_grow(&ga, *num_file) == FAIL)
1559 FreeWild(*num_file, *file);
1560 else
1561 {
1562 for (i = 0; i < *num_file; ++i)
1563 {
1564 char_u *name = (*file)[i];
1565
1566 if (STRLEN(name) > l)
1567 {
1568 // Check if this name was already found.
1569 hash = hash_hash(name + l);
1570 hi = hash_lookup(&found_ht, name + l, hash);
1571 if (HASHITEM_EMPTY(hi))
1572 {
1573 // Remove the path that was prepended.
1574 STRMOVE(name, name + l);
1575 ((char_u **)ga.ga_data)[ga.ga_len++] = name;
1576 hash_add_item(&found_ht, hi, name, hash);
1577 name = NULL;
1578 }
1579 }
1580 vim_free(name);
1581 }
1582 vim_free(*file);
1583 }
1584 }
1585 if (*e != NUL)
1586 ++e;
1587 }
1588 *file = ga.ga_data;
1589 *num_file = ga.ga_len;
1590
1591 vim_free(buf);
1592 vim_free(pat);
1593 if (mustfree)
1594 vim_free(path);
1595 hash_clear(&found_ht);
1596 return OK;
1597}
1598
1599# if defined(FEAT_EVAL)
1600/*
1601 * Call "user_expand_func()" to invoke a user defined Vim script function and
1602 * return the result (either a string or a List).
1603 */
1604 static void *
1605call_user_expand_func(
1606 void *(*user_expand_func)(char_u *, int, typval_T *),
1607 expand_T *xp,
1608 int *num_file,
1609 char_u ***file)
1610{
1611 cmdline_info_T *ccline = get_cmdline_info();
1612 int keep = 0;
1613 typval_T args[4];
1614 sctx_T save_current_sctx = current_sctx;
1615 char_u *pat = NULL;
1616 void *ret;
1617
1618 if (xp->xp_arg == NULL || xp->xp_arg[0] == '\0' || xp->xp_line == NULL)
1619 return NULL;
1620 *num_file = 0;
1621 *file = NULL;
1622
1623 if (ccline->cmdbuff != NULL)
1624 {
1625 keep = ccline->cmdbuff[ccline->cmdlen];
1626 ccline->cmdbuff[ccline->cmdlen] = 0;
1627 }
1628
1629 pat = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len);
1630
1631 args[0].v_type = VAR_STRING;
1632 args[0].vval.v_string = pat;
1633 args[1].v_type = VAR_STRING;
1634 args[1].vval.v_string = xp->xp_line;
1635 args[2].v_type = VAR_NUMBER;
1636 args[2].vval.v_number = xp->xp_col;
1637 args[3].v_type = VAR_UNKNOWN;
1638
1639 current_sctx = xp->xp_script_ctx;
1640
1641 ret = user_expand_func(xp->xp_arg, 3, args);
1642
1643 current_sctx = save_current_sctx;
1644 if (ccline->cmdbuff != NULL)
1645 ccline->cmdbuff[ccline->cmdlen] = keep;
1646
1647 vim_free(pat);
1648 return ret;
1649}
1650
1651/*
1652 * Expand names with a function defined by the user.
1653 */
1654 static int
1655ExpandUserDefined(
1656 expand_T *xp,
1657 regmatch_T *regmatch,
1658 int *num_file,
1659 char_u ***file)
1660{
1661 char_u *retstr;
1662 char_u *s;
1663 char_u *e;
1664 int keep;
1665 garray_T ga;
1666 int skip;
1667
1668 retstr = call_user_expand_func(call_func_retstr, xp, num_file, file);
1669 if (retstr == NULL)
1670 return FAIL;
1671
1672 ga_init2(&ga, (int)sizeof(char *), 3);
1673 for (s = retstr; *s != NUL; s = e)
1674 {
1675 e = vim_strchr(s, '\n');
1676 if (e == NULL)
1677 e = s + STRLEN(s);
1678 keep = *e;
1679 *e = NUL;
1680
1681 skip = xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0;
1682 *e = keep;
1683
1684 if (!skip)
1685 {
1686 if (ga_grow(&ga, 1) == FAIL)
1687 break;
1688 ((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, (int)(e - s));
1689 ++ga.ga_len;
1690 }
1691
1692 if (*e != NUL)
1693 ++e;
1694 }
1695 vim_free(retstr);
1696 *file = ga.ga_data;
1697 *num_file = ga.ga_len;
1698 return OK;
1699}
1700
1701/*
1702 * Expand names with a list returned by a function defined by the user.
1703 */
1704 static int
1705ExpandUserList(
1706 expand_T *xp,
1707 int *num_file,
1708 char_u ***file)
1709{
1710 list_T *retlist;
1711 listitem_T *li;
1712 garray_T ga;
1713
1714 retlist = call_user_expand_func(call_func_retlist, xp, num_file, file);
1715 if (retlist == NULL)
1716 return FAIL;
1717
1718 ga_init2(&ga, (int)sizeof(char *), 3);
1719 // Loop over the items in the list.
1720 for (li = retlist->lv_first; li != NULL; li = li->li_next)
1721 {
1722 if (li->li_tv.v_type != VAR_STRING || li->li_tv.vval.v_string == NULL)
1723 continue; // Skip non-string items and empty strings
1724
1725 if (ga_grow(&ga, 1) == FAIL)
1726 break;
1727
1728 ((char_u **)ga.ga_data)[ga.ga_len] =
1729 vim_strsave(li->li_tv.vval.v_string);
1730 ++ga.ga_len;
1731 }
1732 list_unref(retlist);
1733
1734 *file = ga.ga_data;
1735 *num_file = ga.ga_len;
1736 return OK;
1737}
1738# endif
1739
1740/*
1741 * Expand color scheme, compiler or filetype names.
1742 * Search from 'runtimepath':
1743 * 'runtimepath'/{dirnames}/{pat}.vim
1744 * When "flags" has DIP_START: search also from 'start' of 'packpath':
1745 * 'packpath'/pack/ * /start/ * /{dirnames}/{pat}.vim
1746 * When "flags" has DIP_OPT: search also from 'opt' of 'packpath':
1747 * 'packpath'/pack/ * /opt/ * /{dirnames}/{pat}.vim
1748 * "dirnames" is an array with one or more directory names.
1749 */
1750 static int
1751ExpandRTDir(
1752 char_u *pat,
1753 int flags,
1754 int *num_file,
1755 char_u ***file,
1756 char *dirnames[])
1757{
1758 char_u *s;
1759 char_u *e;
1760 char_u *match;
1761 garray_T ga;
1762 int i;
1763 int pat_len;
1764
1765 *num_file = 0;
1766 *file = NULL;
1767 pat_len = (int)STRLEN(pat);
1768 ga_init2(&ga, (int)sizeof(char *), 10);
1769
1770 for (i = 0; dirnames[i] != NULL; ++i)
1771 {
1772 s = alloc(STRLEN(dirnames[i]) + pat_len + 7);
1773 if (s == NULL)
1774 {
1775 ga_clear_strings(&ga);
1776 return FAIL;
1777 }
1778 sprintf((char *)s, "%s/%s*.vim", dirnames[i], pat);
1779 globpath(p_rtp, s, &ga, 0);
1780 vim_free(s);
1781 }
1782
1783 if (flags & DIP_START) {
1784 for (i = 0; dirnames[i] != NULL; ++i)
1785 {
1786 s = alloc(STRLEN(dirnames[i]) + pat_len + 22);
1787 if (s == NULL)
1788 {
1789 ga_clear_strings(&ga);
1790 return FAIL;
1791 }
1792 sprintf((char *)s, "pack/*/start/*/%s/%s*.vim", dirnames[i], pat);
1793 globpath(p_pp, s, &ga, 0);
1794 vim_free(s);
1795 }
1796 }
1797
1798 if (flags & DIP_OPT) {
1799 for (i = 0; dirnames[i] != NULL; ++i)
1800 {
1801 s = alloc(STRLEN(dirnames[i]) + pat_len + 20);
1802 if (s == NULL)
1803 {
1804 ga_clear_strings(&ga);
1805 return FAIL;
1806 }
1807 sprintf((char *)s, "pack/*/opt/*/%s/%s*.vim", dirnames[i], pat);
1808 globpath(p_pp, s, &ga, 0);
1809 vim_free(s);
1810 }
1811 }
1812
1813 for (i = 0; i < ga.ga_len; ++i)
1814 {
1815 match = ((char_u **)ga.ga_data)[i];
1816 s = match;
1817 e = s + STRLEN(s);
1818 if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0)
1819 {
1820 e -= 4;
1821 for (s = e; s > match; MB_PTR_BACK(match, s))
1822 if (s < match || vim_ispathsep(*s))
1823 break;
1824 ++s;
1825 *e = NUL;
1826 mch_memmove(match, s, e - s + 1);
1827 }
1828 }
1829
1830 if (ga.ga_len == 0)
1831 return FAIL;
1832
1833 // Sort and remove duplicates which can happen when specifying multiple
1834 // directories in dirnames.
1835 remove_duplicates(&ga);
1836
1837 *file = ga.ga_data;
1838 *num_file = ga.ga_len;
1839 return OK;
1840}
1841
1842/*
1843 * Expand loadplugin names:
1844 * 'packpath'/pack/ * /opt/{pat}
1845 */
1846 static int
1847ExpandPackAddDir(
1848 char_u *pat,
1849 int *num_file,
1850 char_u ***file)
1851{
1852 char_u *s;
1853 char_u *e;
1854 char_u *match;
1855 garray_T ga;
1856 int i;
1857 int pat_len;
1858
1859 *num_file = 0;
1860 *file = NULL;
1861 pat_len = (int)STRLEN(pat);
1862 ga_init2(&ga, (int)sizeof(char *), 10);
1863
1864 s = alloc(pat_len + 26);
1865 if (s == NULL)
1866 {
1867 ga_clear_strings(&ga);
1868 return FAIL;
1869 }
1870 sprintf((char *)s, "pack/*/opt/%s*", pat);
1871 globpath(p_pp, s, &ga, 0);
1872 vim_free(s);
1873
1874 for (i = 0; i < ga.ga_len; ++i)
1875 {
1876 match = ((char_u **)ga.ga_data)[i];
1877 s = gettail(match);
1878 e = s + STRLEN(s);
1879 mch_memmove(match, s, e - s + 1);
1880 }
1881
1882 if (ga.ga_len == 0)
1883 return FAIL;
1884
1885 // Sort and remove duplicates which can happen when specifying multiple
1886 // directories in dirnames.
1887 remove_duplicates(&ga);
1888
1889 *file = ga.ga_data;
1890 *num_file = ga.ga_len;
1891 return OK;
1892}
1893#endif
1894
1895#if defined(FEAT_CMDL_COMPL) || defined(FEAT_EVAL) || defined(PROTO)
1896/*
1897 * Expand "file" for all comma-separated directories in "path".
1898 * Adds the matches to "ga". Caller must init "ga".
1899 */
1900 void
1901globpath(
1902 char_u *path,
1903 char_u *file,
1904 garray_T *ga,
1905 int expand_options)
1906{
1907 expand_T xpc;
1908 char_u *buf;
1909 int i;
1910 int num_p;
1911 char_u **p;
1912
1913 buf = alloc(MAXPATHL);
1914 if (buf == NULL)
1915 return;
1916
1917 ExpandInit(&xpc);
1918 xpc.xp_context = EXPAND_FILES;
1919
1920 // Loop over all entries in {path}.
1921 while (*path != NUL)
1922 {
1923 // Copy one item of the path to buf[] and concatenate the file name.
1924 copy_option_part(&path, buf, MAXPATHL, ",");
1925 if (STRLEN(buf) + STRLEN(file) + 2 < MAXPATHL)
1926 {
1927# if defined(MSWIN)
1928 // Using the platform's path separator (\) makes vim incorrectly
1929 // treat it as an escape character, use '/' instead.
1930 if (*buf != NUL && !after_pathsep(buf, buf + STRLEN(buf)))
1931 STRCAT(buf, "/");
1932# else
1933 add_pathsep(buf);
1934# endif
1935 STRCAT(buf, file);
1936 if (ExpandFromContext(&xpc, buf, &num_p, &p,
1937 WILD_SILENT|expand_options) != FAIL && num_p > 0)
1938 {
1939 ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options);
1940
1941 if (ga_grow(ga, num_p) == OK)
1942 {
1943 for (i = 0; i < num_p; ++i)
1944 {
1945 ((char_u **)ga->ga_data)[ga->ga_len] =
1946 vim_strnsave(p[i], (int)STRLEN(p[i]));
1947 ++ga->ga_len;
1948 }
1949 }
1950
1951 FreeWild(num_p, p);
1952 }
1953 }
1954 }
1955
1956 vim_free(buf);
1957}
1958#endif
1959
1960#if defined(FEAT_CMDL_COMPL) | defined(PROTO)
1961/*
1962 * "getcompletion()" function
1963 */
1964 void
1965f_getcompletion(typval_T *argvars, typval_T *rettv)
1966{
1967 char_u *pat;
1968 expand_T xpc;
1969 int filtered = FALSE;
1970 int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH
1971 | WILD_NO_BEEP;
1972
1973 if (argvars[2].v_type != VAR_UNKNOWN)
1974 filtered = tv_get_number_chk(&argvars[2], NULL);
1975
1976 if (p_wic)
1977 options |= WILD_ICASE;
1978
1979 // For filtered results, 'wildignore' is used
1980 if (!filtered)
1981 options |= WILD_KEEP_ALL;
1982
1983 ExpandInit(&xpc);
1984 xpc.xp_pattern = tv_get_string(&argvars[0]);
1985 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern);
1986 xpc.xp_context = cmdcomplete_str_to_type(tv_get_string(&argvars[1]));
1987 if (xpc.xp_context == EXPAND_NOTHING)
1988 {
1989 if (argvars[1].v_type == VAR_STRING)
1990 semsg(_(e_invarg2), argvars[1].vval.v_string);
1991 else
1992 emsg(_(e_invarg));
1993 return;
1994 }
1995
1996# if defined(FEAT_MENU)
1997 if (xpc.xp_context == EXPAND_MENUS)
1998 {
1999 set_context_in_menu_cmd(&xpc, (char_u *)"menu", xpc.xp_pattern, FALSE);
2000 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern);
2001 }
2002# endif
2003# ifdef FEAT_CSCOPE
2004 if (xpc.xp_context == EXPAND_CSCOPE)
2005 {
2006 set_context_in_cscope_cmd(&xpc, xpc.xp_pattern, CMD_cscope);
2007 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern);
2008 }
2009# endif
2010# ifdef FEAT_SIGNS
2011 if (xpc.xp_context == EXPAND_SIGN)
2012 {
2013 set_context_in_sign_cmd(&xpc, xpc.xp_pattern);
2014 xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern);
2015 }
2016# endif
2017
2018 pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context);
2019 if ((rettv_list_alloc(rettv) != FAIL) && (pat != NULL))
2020 {
2021 int i;
2022
2023 ExpandOne(&xpc, pat, NULL, options, WILD_ALL_KEEP);
2024
2025 for (i = 0; i < xpc.xp_numfiles; i++)
2026 list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1);
2027 }
2028 vim_free(pat);
2029 ExpandCleanup(&xpc);
2030}
2031#endif // FEAT_CMDL_COMPL