mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
vim-patch:8.2.4765: function matchfuzzy() sorts too many items
Problem: Function matchfuzzy() sorts too many items.
Solution: Only put matches in the array. (Yegappan Lakshmanan,
closes vim/vim#10208)
047a7019b2
This commit is contained in:
@@ -5093,34 +5093,28 @@ static int fuzzy_match_item_compare(const void *const s1, const void *const s2)
|
|||||||
/// for each item or use 'item_cb' Funcref function to get the string.
|
/// for each item or use 'item_cb' Funcref function to get the string.
|
||||||
/// If 'retmatchpos' is true, then return a list of positions where 'str'
|
/// If 'retmatchpos' is true, then return a list of positions where 'str'
|
||||||
/// matches for each item.
|
/// matches for each item.
|
||||||
static void fuzzy_match_in_list(list_T *const items, char_u *const str, const bool matchseq,
|
static void fuzzy_match_in_list(list_T *const l, char_u *const str, const bool matchseq,
|
||||||
const char_u *const key, Callback *const item_cb,
|
const char_u *const key, Callback *const item_cb,
|
||||||
const bool retmatchpos, list_T *const fmatchlist,
|
const bool retmatchpos, list_T *const fmatchlist,
|
||||||
const long max_matches)
|
const long max_matches)
|
||||||
FUNC_ATTR_NONNULL_ARG(2, 5, 7)
|
FUNC_ATTR_NONNULL_ARG(2, 5, 7)
|
||||||
{
|
{
|
||||||
const long len = tv_list_len(items);
|
long len = tv_list_len(l);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (max_matches > 0 && len > max_matches) {
|
||||||
|
len = max_matches;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(vim): when using a limit use that instead of "len"
|
fuzzyItem_T *const items = xcalloc(len, sizeof(fuzzyItem_T));
|
||||||
fuzzyItem_T *const ptrs = xcalloc(len, sizeof(fuzzyItem_T));
|
long match_count = 0;
|
||||||
long i = 0;
|
|
||||||
long found_match = 0;
|
|
||||||
uint32_t matches[MAX_FUZZY_MATCHES];
|
uint32_t matches[MAX_FUZZY_MATCHES];
|
||||||
|
|
||||||
// For all the string items in items, get the fuzzy matching score
|
// For all the string items in items, get the fuzzy matching score
|
||||||
TV_LIST_ITER(items, li, {
|
TV_LIST_ITER(l, li, {
|
||||||
ptrs[i].idx = i;
|
if (max_matches > 0 && match_count >= max_matches) {
|
||||||
ptrs[i].item = li;
|
break;
|
||||||
ptrs[i].score = SCORE_NONE;
|
|
||||||
|
|
||||||
// TODO(vim): instead of putting all items in ptrs[] should only add
|
|
||||||
// matching items there.
|
|
||||||
if (max_matches > 0 && found_match >= max_matches) {
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char_u *itemstr = NULL;
|
char_u *itemstr = NULL;
|
||||||
@@ -5153,31 +5147,33 @@ static void fuzzy_match_in_list(list_T *const items, char_u *const str, const bo
|
|||||||
|
|
||||||
int score;
|
int score;
|
||||||
if (itemstr != NULL && fuzzy_match(itemstr, str, matchseq, &score, matches,
|
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
|
// Copy the list of matching positions in itemstr to a list, if
|
||||||
// 'retmatchpos' is set.
|
// 'retmatchpos' is set.
|
||||||
if (retmatchpos) {
|
if (retmatchpos) {
|
||||||
ptrs[i].lmatchpos = tv_list_alloc(kListLenMayKnow);
|
items[match_count].lmatchpos = tv_list_alloc(kListLenMayKnow);
|
||||||
int j = 0;
|
int j = 0;
|
||||||
const char_u *p = str;
|
const char_u *p = str;
|
||||||
while (*p != NUL) {
|
while (*p != NUL) {
|
||||||
if (!ascii_iswhite(utf_ptr2char(p))) {
|
if (!ascii_iswhite(utf_ptr2char(p))) {
|
||||||
tv_list_append_number(ptrs[i].lmatchpos, matches[j]);
|
tv_list_append_number(items[match_count].lmatchpos, matches[j]);
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
MB_PTR_ADV(p);
|
MB_PTR_ADV(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptrs[i].score = score;
|
match_count++;
|
||||||
found_match++;
|
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
tv_clear(&rettv);
|
tv_clear(&rettv);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (found_match > 0) {
|
if (match_count > 0) {
|
||||||
// Sort the list by the descending order of the match score
|
// Sort the list by the descending order of the match score
|
||||||
qsort(ptrs, len, sizeof(fuzzyItem_T), fuzzy_match_item_compare);
|
qsort(items, match_count, sizeof(fuzzyItem_T), fuzzy_match_item_compare);
|
||||||
|
|
||||||
// For matchfuzzy(), return a list of matched strings.
|
// For matchfuzzy(), return a list of matched strings.
|
||||||
// ['str1', 'str2', 'str3']
|
// ['str1', 'str2', 'str3']
|
||||||
@@ -5186,48 +5182,49 @@ static void fuzzy_match_in_list(list_T *const items, char_u *const str, const bo
|
|||||||
// is a list of lists where each list item is a list of matched
|
// is a list of lists where each list item is a list of matched
|
||||||
// character positions. The third item is a list of matching scores.
|
// character positions. The third item is a list of matching scores.
|
||||||
// [['str1', 'str2', 'str3'], [[1, 3], [1, 3], [1, 3]]]
|
// [['str1', 'str2', 'str3'], [[1, 3], [1, 3], [1, 3]]]
|
||||||
list_T *l;
|
list_T *retlist;
|
||||||
if (retmatchpos) {
|
if (retmatchpos) {
|
||||||
const listitem_T *const li = tv_list_find(fmatchlist, 0);
|
const listitem_T *const li = tv_list_find(fmatchlist, 0);
|
||||||
assert(li != NULL && TV_LIST_ITEM_TV(li)->vval.v_list != NULL);
|
assert(li != NULL && TV_LIST_ITEM_TV(li)->vval.v_list != NULL);
|
||||||
l = TV_LIST_ITEM_TV(li)->vval.v_list;
|
retlist = TV_LIST_ITEM_TV(li)->vval.v_list;
|
||||||
} else {
|
} else {
|
||||||
l = fmatchlist;
|
retlist = fmatchlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the matching strings with a valid score to the return list
|
// Copy the matching strings with a valid score to the return list
|
||||||
for (i = 0; i < len; i++) {
|
for (long i = 0; i < match_count; i++) {
|
||||||
if (ptrs[i].score == SCORE_NONE) {
|
if (items[i].score == SCORE_NONE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tv_list_append_tv(l, TV_LIST_ITEM_TV(ptrs[i].item));
|
tv_list_append_tv(retlist, TV_LIST_ITEM_TV(items[i].item));
|
||||||
}
|
}
|
||||||
|
|
||||||
// next copy the list of matching positions
|
// next copy the list of matching positions
|
||||||
if (retmatchpos) {
|
if (retmatchpos) {
|
||||||
const listitem_T *li = tv_list_find(fmatchlist, -2);
|
const listitem_T *li = tv_list_find(fmatchlist, -2);
|
||||||
assert(li != NULL && TV_LIST_ITEM_TV(li)->vval.v_list != NULL);
|
assert(li != NULL && TV_LIST_ITEM_TV(li)->vval.v_list != NULL);
|
||||||
l = TV_LIST_ITEM_TV(li)->vval.v_list;
|
retlist = TV_LIST_ITEM_TV(li)->vval.v_list;
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
if (ptrs[i].score == SCORE_NONE) {
|
for (long i = 0; i < match_count; i++) {
|
||||||
|
if (items[i].score == SCORE_NONE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tv_list_append_list(l, ptrs[i].lmatchpos);
|
tv_list_append_list(retlist, items[i].lmatchpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy the matching scores
|
// copy the matching scores
|
||||||
li = tv_list_find(fmatchlist, -1);
|
li = tv_list_find(fmatchlist, -1);
|
||||||
assert(li != NULL && TV_LIST_ITEM_TV(li)->vval.v_list != NULL);
|
assert(li != NULL && TV_LIST_ITEM_TV(li)->vval.v_list != NULL);
|
||||||
l = TV_LIST_ITEM_TV(li)->vval.v_list;
|
retlist = TV_LIST_ITEM_TV(li)->vval.v_list;
|
||||||
for (i = 0; i < len; i++) {
|
for (long i = 0; i < match_count; i++) {
|
||||||
if (ptrs[i].score == SCORE_NONE) {
|
if (items[i].score == SCORE_NONE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tv_list_append_number(l, ptrs[i].score);
|
tv_list_append_number(retlist, items[i].score);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xfree(ptrs);
|
xfree(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do fuzzy matching. Returns the list of matched strings in 'rettv'.
|
/// Do fuzzy matching. Returns the list of matched strings in 'rettv'.
|
||||||
|
Reference in New Issue
Block a user