diff options
author | Yegappan Lakshmanan <yegappan@yahoo.com> | 2022-04-16 20:42:40 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-04-16 20:42:40 +0100 |
commit | 047a7019b293918343998ccbdfabd48c771f5eef (patch) | |
tree | 85d098afb20c2f40b01bb25c31fa593ae5c9081a | |
parent | d2edee5cf3bd1eb69d88a12bcab33fc4228e83c0 (diff) | |
download | vim-git-047a7019b293918343998ccbdfabd48c771f5eef.tar.gz |
patch 8.2.4765: function matchfuzzy() sorts too many itemsv8.2.4765
Problem: Function matchfuzzy() sorts too many items.
Solution: Only put matches in the array. (Yegappan Lakshmanan,
closes #10208)
-rw-r--r-- | src/search.c | 85 | ||||
-rw-r--r-- | src/version.c | 2 |
2 files changed, 42 insertions, 45 deletions
diff --git a/src/search.c b/src/search.c index 42b66671c..3165ba2ce 100644 --- a/src/search.c +++ b/src/search.c @@ -4642,7 +4642,7 @@ fuzzy_match_item_compare(const void *s1, const void *s2) */ static void fuzzy_match_in_list( - list_T *items, + list_T *l, char_u *str, int matchseq, char_u *key, @@ -4652,46 +4652,38 @@ fuzzy_match_in_list( long max_matches) { long len; - fuzzyItem_T *ptrs; + fuzzyItem_T *items; listitem_T *li; long i = 0; - long found_match = 0; + long match_count = 0; int_u matches[MAX_FUZZY_MATCHES]; - len = list_len(items); + len = list_len(l); if (len == 0) return; + if (max_matches > 0 && len > max_matches) + len = max_matches; - // TODO: when using a limit use that instead of "len" - ptrs = ALLOC_CLEAR_MULT(fuzzyItem_T, len); - if (ptrs == NULL) + items = ALLOC_CLEAR_MULT(fuzzyItem_T, len); + if (items == NULL) return; // For all the string items in items, get the fuzzy matching score - FOR_ALL_LIST_ITEMS(items, li) + FOR_ALL_LIST_ITEMS(l, li) { int score; char_u *itemstr; typval_T rettv; - ptrs[i].idx = i; - ptrs[i].item = li; - ptrs[i].score = SCORE_NONE; - - // TODO: instead of putting all items in ptrs[] should only add - // matching items there. - if (max_matches > 0 && found_match >= max_matches) - { - i++; - continue; - } + if (max_matches > 0 && match_count >= max_matches) + break; itemstr = NULL; rettv.v_type = VAR_UNKNOWN; if (li->li_tv.v_type == VAR_STRING) // list of strings itemstr = li->li_tv.vval.v_string; else if (li->li_tv.v_type == VAR_DICT - && (key != NULL || item_cb->cb_name != NULL)) + && (key != NULL || item_cb->cb_name != NULL)) { // For a dict, either use the specified key to lookup the string or // use the specified callback function to get the string. @@ -4717,8 +4709,12 @@ fuzzy_match_in_list( if (itemstr != NULL && fuzzy_match(itemstr, str, matchseq, &score, matches, - sizeof(matches) / sizeof(matches[0]))) + MAX_FUZZY_MATCHES)) { + items[match_count].idx = match_count; + items[match_count].item = li; + items[match_count].score = score; + // Copy the list of matching positions in itemstr to a list, if // 'retmatchpos' is set. if (retmatchpos) @@ -4726,8 +4722,8 @@ fuzzy_match_in_list( int j = 0; char_u *p; - ptrs[i].lmatchpos = list_alloc(); - if (ptrs[i].lmatchpos == NULL) + items[match_count].lmatchpos = list_alloc(); + if (items[match_count].lmatchpos == NULL) goto done; p = str; @@ -4735,7 +4731,7 @@ fuzzy_match_in_list( { if (!VIM_ISWHITE(PTR2CHAR(p))) { - if (list_append_number(ptrs[i].lmatchpos, + if (list_append_number(items[match_count].lmatchpos, matches[j]) == FAIL) goto done; j++; @@ -4746,19 +4742,17 @@ fuzzy_match_in_list( ++p; } } - ptrs[i].score = score; - ++found_match; + ++match_count; } - ++i; clear_tv(&rettv); } - if (found_match > 0) + if (match_count > 0) { - list_T *l; + list_T *retlist; // Sort the list by the descending order of the match score - qsort((void *)ptrs, (size_t)len, sizeof(fuzzyItem_T), + qsort((void *)items, (size_t)match_count, sizeof(fuzzyItem_T), fuzzy_match_item_compare); // For matchfuzzy(), return a list of matched strings. @@ -4773,17 +4767,17 @@ fuzzy_match_in_list( li = list_find(fmatchlist, 0); if (li == NULL || li->li_tv.vval.v_list == NULL) goto done; - l = li->li_tv.vval.v_list; + retlist = li->li_tv.vval.v_list; } else - l = fmatchlist; + retlist = fmatchlist; // Copy the matching strings with a valid score to the return list - for (i = 0; i < len; i++) + for (i = 0; i < match_count; i++) { - if (ptrs[i].score == SCORE_NONE) + if (items[i].score == SCORE_NONE) break; - list_append_tv(l, &ptrs[i].item->li_tv); + list_append_tv(retlist, &items[i].item->li_tv); } // next copy the list of matching positions @@ -4792,14 +4786,15 @@ fuzzy_match_in_list( li = list_find(fmatchlist, -2); if (li == NULL || li->li_tv.vval.v_list == NULL) goto done; - l = li->li_tv.vval.v_list; + retlist = li->li_tv.vval.v_list; - for (i = 0; i < len; i++) + for (i = 0; i < match_count; i++) { - if (ptrs[i].score == SCORE_NONE) + if (items[i].score == SCORE_NONE) break; - if (ptrs[i].lmatchpos != NULL - && list_append_list(l, ptrs[i].lmatchpos) == FAIL) + if (items[i].lmatchpos != NULL + && list_append_list(retlist, items[i].lmatchpos) + == FAIL) goto done; } @@ -4807,19 +4802,19 @@ fuzzy_match_in_list( li = list_find(fmatchlist, -1); if (li == NULL || li->li_tv.vval.v_list == NULL) goto done; - l = li->li_tv.vval.v_list; - for (i = 0; i < len; i++) + retlist = li->li_tv.vval.v_list; + for (i = 0; i < match_count; i++) { - if (ptrs[i].score == SCORE_NONE) + if (items[i].score == SCORE_NONE) break; - if (list_append_number(l, ptrs[i].score) == FAIL) + if (list_append_number(retlist, items[i].score) == FAIL) goto done; } } } done: - vim_free(ptrs); + vim_free(items); } /* diff --git a/src/version.c b/src/version.c index ad301a838..d4410d05c 100644 --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4765, +/**/ 4764, /**/ 4763, |