Mercurial > vim
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, ®match, pat, numMatches, matches); | 2595 ret = ExpandSettings(xp, ®match, pat, numMatches, matches); |
2603 else if (xp->xp_context == EXPAND_MAPPINGS) | 2596 else if (xp->xp_context == EXPAND_MAPPINGS) |
2604 ret = ExpandMappings(pat, ®match, numMatches, matches); | 2597 ret = ExpandMappings(pat, ®match, 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, ®match, matches, numMatches); | 2600 ret = ExpandUserDefined(pat, xp, ®match, matches, numMatches); |
2608 # endif | 2601 # endif |
2609 else | 2602 else |
2610 ret = ExpandOther(pat, xp, ®match, matches, numMatches); | 2603 ret = ExpandOther(pat, xp, ®match, 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. |