Skip to content

Commit 14a014d

Browse files
committed
feat: min score on fuzzy results, avoid trimming valid items
1 parent 013dc02 commit 14a014d

File tree

3 files changed

+71
-59
lines changed

3 files changed

+71
-59
lines changed

lua/blink/cmp/fuzzy/ffi.lua

+52-44
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,22 @@ end
1818

1919

2020

21-
2221
typedef struct {
2322
const int32_t *ptr;
2423
size_t len;
2524
size_t capacity;
2625
} blink_cmp_fuzzy__Vec_int32_t;
2726

28-
typedef struct {
29-
const uint32_t *ptr;
30-
size_t len;
31-
size_t capacity;
32-
} blink_cmp_fuzzy__Vec_uint32_t;
33-
typedef struct {
34-
const int32_t *ptr;
35-
} blink_cmp_fuzzy__Option_int32_t;
3627

37-
typedef struct {
38-
const char * *ptr;
39-
size_t len;
40-
size_t capacity;
41-
} blink_cmp_fuzzy__Vec___string_ptr;
42-
typedef struct {
43-
const blink_cmp_fuzzy__Vec___string_ptr *ptr;
44-
} blink_cmp_fuzzy__Option_Vec___string_ptr;
28+
4529
typedef struct {
4630
const char * *ptr;
4731
} blink_cmp_fuzzy__Option___string_ptr;
4832

33+
typedef struct {
34+
const int32_t *ptr;
35+
} blink_cmp_fuzzy__Option_int32_t;
36+
4937
typedef struct {
5038
const char * label;
5139
const blink_cmp_fuzzy__Option___string_ptr sort_text;
@@ -55,10 +43,24 @@ typedef struct {
5543
const char * source;
5644
} blink_cmp_fuzzy__LspItem;
5745

46+
typedef struct {
47+
const uint32_t *ptr;
48+
size_t len;
49+
size_t capacity;
50+
} blink_cmp_fuzzy__Vec_uint32_t;
51+
typedef struct {
52+
const char * *ptr;
53+
size_t len;
54+
size_t capacity;
55+
} blink_cmp_fuzzy__Vec___string_ptr;
56+
typedef struct {
57+
const blink_cmp_fuzzy__Vec___string_ptr *ptr;
58+
} blink_cmp_fuzzy__Option_Vec___string_ptr;
5859

5960
typedef struct {
6061
const int8_t use_frecency;
6162
const blink_cmp_fuzzy__Option_Vec___string_ptr nearby_words;
63+
const uint16_t min_score;
6264
const size_t max_items;
6365
const blink_cmp_fuzzy__Vec___string_ptr sorts;
6466
} blink_cmp_fuzzy__FuzzyOptions;
@@ -101,21 +103,16 @@ int32_t __gc_get_words(
101103

102104

103105

104-
local __const_c_typename_bool = ffi.typeof("const int8_t[?]")
105-
local __c_function_argument_bool = ffi.typeof("int8_t[?]")
106-
local __c_mut_function_argument_bool = ffi.typeof("int8_t[?]")
106+
local __const_c_typename_size_t = ffi.typeof("const size_t[?]")
107+
local __c_function_argument_size_t = ffi.typeof("size_t[?]")
108+
local __c_mut_function_argument_size_t = ffi.typeof("size_t[?]")
107109

108110

109111
local __const_c_typename_int32_t = ffi.typeof("const int32_t[?]")
110112
local __c_function_argument_int32_t = ffi.typeof("int32_t[?]")
111113
local __c_mut_function_argument_int32_t = ffi.typeof("int32_t[?]")
112114

113115

114-
local __const_c_typename_size_t = ffi.typeof("const size_t[?]")
115-
local __c_function_argument_size_t = ffi.typeof("size_t[?]")
116-
local __c_mut_function_argument_size_t = ffi.typeof("size_t[?]")
117-
118-
119116
local __typename_Vec_int32_t = ffi.metatype("blink_cmp_fuzzy__Vec_int32_t", {})
120117
local __const_c_typename_Vec_int32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_int32_t[?]")
121118
local __c_function_argument_Vec_int32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_int32_t*[?]")
@@ -127,10 +124,25 @@ local __c_function_argument_uint32_t = ffi.typeof("uint32_t[?]")
127124
local __c_mut_function_argument_uint32_t = ffi.typeof("uint32_t[?]")
128125

129126

130-
local __typename_Vec_uint32_t = ffi.metatype("blink_cmp_fuzzy__Vec_uint32_t", {})
131-
local __const_c_typename_Vec_uint32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_uint32_t[?]")
132-
local __c_function_argument_Vec_uint32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_uint32_t*[?]")
133-
local __c_mut_function_argument_Vec_uint32_t = ffi.typeof("blink_cmp_fuzzy__Vec_uint32_t*[?]")
127+
local __const_c_typename_uint16_t = ffi.typeof("const uint16_t[?]")
128+
local __c_function_argument_uint16_t = ffi.typeof("uint16_t[?]")
129+
local __c_mut_function_argument_uint16_t = ffi.typeof("uint16_t[?]")
130+
131+
132+
local __const_c_typename___string_ptr = ffi.typeof("const char *[?]")
133+
local __c_function_argument___string_ptr = ffi.typeof("const char *[?]")
134+
local __c_mut_function_argument___string_ptr = ffi.typeof("char *[?]")
135+
136+
137+
local __typename_Option___string_ptr = ffi.metatype("blink_cmp_fuzzy__Option___string_ptr", {})
138+
local __const_c_typename_Option___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option___string_ptr[?]")
139+
local __c_function_argument_Option___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option___string_ptr*[?]")
140+
local __c_mut_function_argument_Option___string_ptr = ffi.typeof("blink_cmp_fuzzy__Option___string_ptr*[?]")
141+
142+
143+
local __const_c_typename_bool = ffi.typeof("const int8_t[?]")
144+
local __c_function_argument_bool = ffi.typeof("int8_t[?]")
145+
local __c_mut_function_argument_bool = ffi.typeof("int8_t[?]")
134146

135147

136148
local __typename_Option_int32_t = ffi.metatype("blink_cmp_fuzzy__Option_int32_t", {})
@@ -139,9 +151,16 @@ local __c_function_argument_Option_int32_t = ffi.typeof("const blink_cmp_fuzzy__
139151
local __c_mut_function_argument_Option_int32_t = ffi.typeof("blink_cmp_fuzzy__Option_int32_t*[?]")
140152

141153

142-
local __const_c_typename___string_ptr = ffi.typeof("const char *[?]")
143-
local __c_function_argument___string_ptr = ffi.typeof("const char *[?]")
144-
local __c_mut_function_argument___string_ptr = ffi.typeof("char *[?]")
154+
local __typename_LspItem = ffi.metatype("blink_cmp_fuzzy__LspItem", {})
155+
local __const_c_typename_LspItem = ffi.typeof("const blink_cmp_fuzzy__LspItem[?]")
156+
local __c_function_argument_LspItem = ffi.typeof("const blink_cmp_fuzzy__LspItem*[?]")
157+
local __c_mut_function_argument_LspItem = ffi.typeof("blink_cmp_fuzzy__LspItem*[?]")
158+
159+
160+
local __typename_Vec_uint32_t = ffi.metatype("blink_cmp_fuzzy__Vec_uint32_t", {})
161+
local __const_c_typename_Vec_uint32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_uint32_t[?]")
162+
local __c_function_argument_Vec_uint32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_uint32_t*[?]")
163+
local __c_mut_function_argument_Vec_uint32_t = ffi.typeof("blink_cmp_fuzzy__Vec_uint32_t*[?]")
145164

146165

147166
local __typename_Vec___string_ptr = ffi.metatype("blink_cmp_fuzzy__Vec___string_ptr", {})
@@ -156,18 +175,6 @@ local __c_function_argument_Option_Vec___string_ptr = ffi.typeof("const blink_cm
156175
local __c_mut_function_argument_Option_Vec___string_ptr = ffi.typeof("blink_cmp_fuzzy__Option_Vec___string_ptr*[?]")
157176

158177

159-
local __typename_Option___string_ptr = ffi.metatype("blink_cmp_fuzzy__Option___string_ptr", {})
160-
local __const_c_typename_Option___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option___string_ptr[?]")
161-
local __c_function_argument_Option___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option___string_ptr*[?]")
162-
local __c_mut_function_argument_Option___string_ptr = ffi.typeof("blink_cmp_fuzzy__Option___string_ptr*[?]")
163-
164-
165-
local __typename_LspItem = ffi.metatype("blink_cmp_fuzzy__LspItem", {})
166-
local __const_c_typename_LspItem = ffi.typeof("const blink_cmp_fuzzy__LspItem[?]")
167-
local __c_function_argument_LspItem = ffi.typeof("const blink_cmp_fuzzy__LspItem*[?]")
168-
local __c_mut_function_argument_LspItem = ffi.typeof("blink_cmp_fuzzy__LspItem*[?]")
169-
170-
171178
local __typename_FuzzyOptions = ffi.metatype("blink_cmp_fuzzy__FuzzyOptions", {})
172179
local __const_c_typename_FuzzyOptions = ffi.typeof("const blink_cmp_fuzzy__FuzzyOptions[?]")
173180
local __c_function_argument_FuzzyOptions = ffi.typeof("const blink_cmp_fuzzy__FuzzyOptions*[?]")
@@ -348,6 +355,7 @@ end
348355
end
349356
end
350357
)(value.nearby_words),
358+
(function(value) return value end)(value.min_score),
351359
(function(value) return value end)(value.max_items),
352360
(
353361
function(value)

lua/blink/cmp/fuzzy/fuzzy.rs

+14-15
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub struct MatchedLspItem {
2828
pub struct FuzzyOptions {
2929
use_frecency: bool,
3030
nearby_words: Option<Vec<String>>,
31+
min_score: u16,
3132
max_items: usize,
3233
sorts: Vec<String>,
3334
}
@@ -46,7 +47,7 @@ pub fn fuzzy(
4647
.map(|s| s.label.as_str())
4748
.collect::<Vec<_>>();
4849
let options = frizbee::Options {
49-
min_score: 0,
50+
min_score: opts.min_score,
5051
stable_sort: false,
5152
..Default::default()
5253
};
@@ -57,38 +58,36 @@ pub fn fuzzy(
5758
.iter()
5859
.map(|mtch| {
5960
(mtch.score as i32)
60-
+ frecency.get_score(&haystack[mtch.index]) as i32
61+
+ frecency.get_score(&haystack[mtch.index_in_haystack]) as i32
6162
+ nearby_words
62-
.get(&haystack[mtch.index].label)
63+
.get(&haystack[mtch.index_in_haystack].label)
6364
.map(|_| 2)
6465
.unwrap_or(0)
65-
+ haystack[mtch.index].score_offset.unwrap_or(0)
66+
+ haystack[mtch.index_in_haystack].score_offset.unwrap_or(0)
6667
})
6768
.collect::<Vec<_>>();
6869
matches.sort_by_cached_key(|mtch| Reverse(match_scores[mtch.index]));
6970

70-
// Grab the top N matches
71-
let mut match_indices = matches
72-
.iter()
73-
.map(|mtch| mtch.index)
74-
.take(opts.max_items)
75-
.collect::<Vec<_>>();
76-
7771
// Sort matches by sort criteria
7872
for sort in opts.sorts.iter() {
7973
match sort.as_str() {
8074
"kind" => {
81-
match_indices.sort_by_key(|idx| haystack[*idx].kind);
75+
matches.sort_by_key(|mtch| haystack[mtch.index_in_haystack].kind);
8276
}
8377
"score" => {
84-
match_indices.sort_by_key(|idx| Reverse(match_scores[*idx]));
78+
matches.sort_by_key(|mtch| Reverse(mtch.score));
8579
}
8680
"label" => {
87-
match_indices.sort_by_key(|idx| haystack[*idx].label.clone());
81+
matches.sort_by_key(|mtch| haystack[mtch.index_in_haystack].label.clone());
8882
}
8983
_ => {}
9084
}
9185
}
9286

93-
match_indices
87+
// Grab the top N matches and return the indices
88+
matches
89+
.iter()
90+
.map(|mtch| mtch.index_in_haystack)
91+
.take(opts.max_items)
92+
.collect::<Vec<_>>()
9493
}

lua/blink/cmp/fuzzy/init.lua

+5
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,17 @@ function fuzzy.filter_items(needle, items)
4242
local filtered_items = {}
4343
local matched_indices =
4444
fuzzy.rust.fuzzy(needle, haystack_labels, haystack_kinds, haystack_score_offsets, haystack_sources, {
45+
-- each matching char is worth 4 points and it receives a bonus for capitalization, delimiter and prefix
46+
-- so this should generally be good
47+
-- TODO: make this configurable
48+
min_score = 4 * needle:len(),
4549
max_items = config.max_items,
4650
use_frecency = config.use_frecency,
4751
use_proximity = config.use_proximity,
4852
sorts = config.sorts,
4953
nearby_words = nearby_words,
5054
})
55+
5156
for _, idx in ipairs(matched_indices) do
5257
table.insert(filtered_items, items[idx + 1])
5358
end

0 commit comments

Comments
 (0)