comparison src/cmdexpand.c @ 27914:9a997de62da2 v8.2.4482

patch 8.2.4482: no fuzzy cmdline completion for user defined completion Commit: https://github.com/vim/vim/commit/afd4ae35d66b2e7732eceb5ad9f6b4ece6b7c64c Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Sun Feb 27 21:03:21 2022 +0000 patch 8.2.4482: no fuzzy cmdline completion for user defined completion Problem: No fuzzy cmdline completion for user defined completion. Solution: Add fuzzy completion for user defined completion. (Yegappan Lakshmanan, closes #9858)
author Bram Moolenaar <Bram@vim.org>
date Sun, 27 Feb 2022 22:15:04 +0100
parents be9e6e0b1591
children 6efa2f193c94
comparison
equal deleted inserted replaced
27913:38695d6adf31 27914:9a997de62da2
14 #include "vim.h" 14 #include "vim.h"
15 15
16 static int cmd_showtail; // Only show path tail in lists ? 16 static int cmd_showtail; // Only show path tail in lists ?
17 17
18 static void set_expand_context(expand_T *xp); 18 static void set_expand_context(expand_T *xp);
19 static int ExpandGeneric(expand_T *xp, regmatch_T *regmatch, 19 static int ExpandGeneric(char_u *pat, expand_T *xp, regmatch_T *regmatch,
20 char_u ***matches, int *numMatches, 20 char_u ***matches, int *numMatches,
21 char_u *((*func)(expand_T *, int)), int escaped, 21 char_u *((*func)(expand_T *, int)), int escaped);
22 char_u *fuzzystr);
23 static int ExpandFromContext(expand_T *xp, char_u *, char_u ***, int *, int); 22 static int ExpandFromContext(expand_T *xp, char_u *, char_u ***, int *, int);
24 static int expand_showtail(expand_T *xp); 23 static int expand_showtail(expand_T *xp);
25 static int expand_shellcmd(char_u *filepat, char_u ***matches, int *numMatches, int flagsarg); 24 static int expand_shellcmd(char_u *filepat, char_u ***matches, int *numMatches, int flagsarg);
26 #if defined(FEAT_EVAL) 25 #if defined(FEAT_EVAL)
27 static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, char_u ***matches, int *numMatches); 26 static int ExpandUserDefined(char_u *pat, expand_T *xp, regmatch_T *regmatch, char_u ***matches, int *numMatches);
28 static int ExpandUserList(expand_T *xp, char_u ***matches, int *numMatches); 27 static int ExpandUserList(expand_T *xp, char_u ***matches, int *numMatches);
29 #endif 28 #endif
30 29
31 #ifdef FEAT_WILDMENU 30 #ifdef FEAT_WILDMENU
32 // "compl_match_array" points the currently displayed list of entries in the 31 // "compl_match_array" points the currently displayed list of entries in the
60 && xp->xp_context != EXPAND_OWNSYNTAX 59 && xp->xp_context != EXPAND_OWNSYNTAX
61 && xp->xp_context != EXPAND_PACKADD 60 && xp->xp_context != EXPAND_PACKADD
62 && xp->xp_context != EXPAND_SHELLCMD 61 && xp->xp_context != EXPAND_SHELLCMD
63 && xp->xp_context != EXPAND_TAGS 62 && xp->xp_context != EXPAND_TAGS
64 && xp->xp_context != EXPAND_TAGS_LISTFILES 63 && xp->xp_context != EXPAND_TAGS_LISTFILES
65 && xp->xp_context != EXPAND_USER_DEFINED
66 && xp->xp_context != EXPAND_USER_LIST); 64 && xp->xp_context != EXPAND_USER_LIST);
67 } 65 }
68 66
69 /* 67 /*
70 * Returns TRUE if fuzzy completion for cmdline completion is enabled and 68 * Returns TRUE if fuzzy completion for cmdline completion is enabled and
71 * 'fuzzystr' is not empty. 69 * 'fuzzystr' is not empty. If search pattern is empty, then don't use fuzzy
70 * matching.
72 */ 71 */
73 int 72 int
74 cmdline_fuzzy_complete(char_u *fuzzystr) 73 cmdline_fuzzy_complete(char_u *fuzzystr)
75 { 74 {
76 return vim_strchr(p_wop, WOP_FUZZY) != NULL && *fuzzystr != NUL; 75 return vim_strchr(p_wop, WOP_FUZZY) != NULL && *fuzzystr != NUL;
2442 // right function to do the expansion. 2441 // right function to do the expansion.
2443 for (i = 0; i < (int)ARRAY_LENGTH(tab); ++i) 2442 for (i = 0; i < (int)ARRAY_LENGTH(tab); ++i)
2444 { 2443 {
2445 if (xp->xp_context == tab[i].context) 2444 if (xp->xp_context == tab[i].context)
2446 { 2445 {
2447 // Use fuzzy matching if 'wildoptions' has 'fuzzy'.
2448 // If no search pattern is supplied, then don't use fuzzy
2449 // matching and return all the found items.
2450 int fuzzy = cmdline_fuzzy_complete(pat);
2451
2452 if (tab[i].ic) 2446 if (tab[i].ic)
2453 rmp->rm_ic = TRUE; 2447 rmp->rm_ic = TRUE;
2454 ret = ExpandGeneric(xp, rmp, matches, numMatches, 2448 ret = ExpandGeneric(pat, xp, rmp, matches, numMatches,
2455 tab[i].func, tab[i].escaped, 2449 tab[i].func, tab[i].escaped);
2456 fuzzy ? pat : NULL);
2457 break; 2450 break;
2458 } 2451 }
2459 } 2452 }
2460 2453
2461 return ret; 2454 return ret;
2602 ret = ExpandSettings(xp, &regmatch, pat, numMatches, matches); 2595 ret = ExpandSettings(xp, &regmatch, pat, numMatches, matches);
2603 else if (xp->xp_context == EXPAND_MAPPINGS) 2596 else if (xp->xp_context == EXPAND_MAPPINGS)
2604 ret = ExpandMappings(pat, &regmatch, numMatches, matches); 2597 ret = ExpandMappings(pat, &regmatch, numMatches, matches);
2605 # if defined(FEAT_EVAL) 2598 # if defined(FEAT_EVAL)
2606 else if (xp->xp_context == EXPAND_USER_DEFINED) 2599 else if (xp->xp_context == EXPAND_USER_DEFINED)
2607 ret = ExpandUserDefined(xp, &regmatch, matches, numMatches); 2600 ret = ExpandUserDefined(pat, xp, &regmatch, matches, numMatches);
2608 # endif 2601 # endif
2609 else 2602 else
2610 ret = ExpandOther(pat, xp, &regmatch, matches, numMatches); 2603 ret = ExpandOther(pat, xp, &regmatch, matches, numMatches);
2611 2604
2612 if (!fuzzy) 2605 if (!fuzzy)
2628 * 2621 *
2629 * Returns OK when no problems encountered, FAIL for error (out of memory). 2622 * Returns OK when no problems encountered, FAIL for error (out of memory).
2630 */ 2623 */
2631 static int 2624 static int
2632 ExpandGeneric( 2625 ExpandGeneric(
2626 char_u *pat,
2633 expand_T *xp, 2627 expand_T *xp,
2634 regmatch_T *regmatch, 2628 regmatch_T *regmatch,
2635 char_u ***matches, 2629 char_u ***matches,
2636 int *numMatches, 2630 int *numMatches,
2637 char_u *((*func)(expand_T *, int)), 2631 char_u *((*func)(expand_T *, int)),
2638 // returns a string from the list 2632 // returns a string from the list
2639 int escaped, 2633 int escaped)
2640 char_u *fuzzystr)
2641 { 2634 {
2642 int i; 2635 int i;
2643 int count = 0; 2636 int count = 0;
2644 int round; 2637 int round;
2645 char_u *str; 2638 char_u *str;
2646 fuzmatch_str_T *fuzmatch = NULL; 2639 fuzmatch_str_T *fuzmatch = NULL;
2647 int score = 0; 2640 int score = 0;
2648 int fuzzy = (fuzzystr != NULL); 2641 int fuzzy;
2649 int funcsort = FALSE; 2642 int funcsort = FALSE;
2650 int match; 2643 int match;
2644
2645 fuzzy = cmdline_fuzzy_complete(pat);
2651 2646
2652 // do this loop twice: 2647 // do this loop twice:
2653 // round == 0: count the number of matching names 2648 // round == 0: count the number of matching names
2654 // round == 1: copy the matching names into allocated memory 2649 // round == 1: copy the matching names into allocated memory
2655 for (round = 0; round <= 1; ++round) 2650 for (round = 0; round <= 1; ++round)
2664 2659
2665 if (!fuzzy) 2660 if (!fuzzy)
2666 match = vim_regexec(regmatch, str, (colnr_T)0); 2661 match = vim_regexec(regmatch, str, (colnr_T)0);
2667 else 2662 else
2668 { 2663 {
2669 score = fuzzy_match_str(str, fuzzystr); 2664 score = fuzzy_match_str(str, pat);
2670 match = (score != 0); 2665 match = (score != 0);
2671 } 2666 }
2672 2667
2673 if (!match) 2668 if (!match)
2674 continue; 2669 continue;
2974 vim_free(pat); 2969 vim_free(pat);
2975 return ret; 2970 return ret;
2976 } 2971 }
2977 2972
2978 /* 2973 /*
2979 * Expand names with a function defined by the user. 2974 * Expand names with a function defined by the user (EXPAND_USER_DEFINED and
2975 * EXPAND_USER_LIST).
2980 */ 2976 */
2981 static int 2977 static int
2982 ExpandUserDefined( 2978 ExpandUserDefined(
2979 char_u *pat,
2983 expand_T *xp, 2980 expand_T *xp,
2984 regmatch_T *regmatch, 2981 regmatch_T *regmatch,
2985 char_u ***matches, 2982 char_u ***matches,
2986 int *numMatches) 2983 int *numMatches)
2987 { 2984 {
2988 char_u *retstr; 2985 char_u *retstr;
2989 char_u *s; 2986 char_u *s;
2990 char_u *e; 2987 char_u *e;
2991 int keep; 2988 int keep;
2992 garray_T ga; 2989 garray_T ga;
2993 int skip; 2990 int fuzzy;
2991 int match;
2992 int score;
2993 int count = 0;
2994
2995 fuzzy = cmdline_fuzzy_complete(pat);
2994 2996
2995 *matches = NULL; 2997 *matches = NULL;
2996 *numMatches = 0; 2998 *numMatches = 0;
2997 retstr = call_user_expand_func(call_func_retstr, xp); 2999 retstr = call_user_expand_func(call_func_retstr, xp);
2998 if (retstr == NULL) 3000 if (retstr == NULL)
2999 return FAIL; 3001 return FAIL;
3000 3002
3001 ga_init2(&ga, sizeof(char *), 3); 3003 if (!fuzzy)
3004 ga_init2(&ga, sizeof(char *), 3);
3005 else
3006 ga_init2(&ga, sizeof(fuzmatch_str_T), 3);
3007
3002 for (s = retstr; *s != NUL; s = e) 3008 for (s = retstr; *s != NUL; s = e)
3003 { 3009 {
3004 e = vim_strchr(s, '\n'); 3010 e = vim_strchr(s, '\n');
3005 if (e == NULL) 3011 if (e == NULL)
3006 e = s + STRLEN(s); 3012 e = s + STRLEN(s);
3007 keep = *e; 3013 keep = *e;
3008 *e = NUL; 3014 *e = NUL;
3009 3015
3010 skip = xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0; 3016 if (xp->xp_pattern[0] || fuzzy)
3017 {
3018 if (!fuzzy)
3019 match = vim_regexec(regmatch, s, (colnr_T)0);
3020 else
3021 {
3022 score = fuzzy_match_str(s, pat);
3023 match = (score != 0);
3024 }
3025 }
3026 else
3027 match = TRUE; // match everything
3028
3011 *e = keep; 3029 *e = keep;
3012 3030
3013 if (!skip) 3031 if (match)
3014 { 3032 {
3015 if (ga_grow(&ga, 1) == FAIL) 3033 if (ga_grow(&ga, 1) == FAIL)
3016 break; 3034 break;
3017 ((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, e - s); 3035 if (!fuzzy)
3036 ((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, e - s);
3037 else
3038 {
3039 fuzmatch_str_T *fuzmatch =
3040 &((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
3041 fuzmatch->idx = count;
3042 fuzmatch->str = vim_strnsave(s, e - s);
3043 fuzmatch->score = score;
3044 }
3018 ++ga.ga_len; 3045 ++ga.ga_len;
3046 count++;
3019 } 3047 }
3020 3048
3021 if (*e != NUL) 3049 if (*e != NUL)
3022 ++e; 3050 ++e;
3023 } 3051 }
3024 vim_free(retstr); 3052 vim_free(retstr);
3025 *matches = ga.ga_data; 3053
3026 *numMatches = ga.ga_len; 3054 if (!fuzzy)
3055 {
3056 *matches = ga.ga_data;
3057 *numMatches = ga.ga_len;
3058 }
3059 else
3060 {
3061 if (fuzzymatches_to_strmatches(ga.ga_data, matches, count,
3062 FALSE) == FAIL)
3063 return FAIL;
3064 *numMatches = count;
3065 }
3027 return OK; 3066 return OK;
3028 } 3067 }
3029 3068
3030 /* 3069 /*
3031 * Expand names with a list returned by a function defined by the user. 3070 * Expand names with a list returned by a function defined by the user.