From 14a014dce49e658f5eed32853c9241d7869bc5dd Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Thu, 29 Aug 2024 16:04:57 -0400 Subject: [PATCH] feat: min score on fuzzy results, avoid trimming valid items --- lua/blink/cmp/fuzzy/ffi.lua | 96 +++++++++++++++++++----------------- lua/blink/cmp/fuzzy/fuzzy.rs | 29 ++++++----- lua/blink/cmp/fuzzy/init.lua | 5 ++ 3 files changed, 71 insertions(+), 59 deletions(-) diff --git a/lua/blink/cmp/fuzzy/ffi.lua b/lua/blink/cmp/fuzzy/ffi.lua index c50dbb54..f5ad2f90 100644 --- a/lua/blink/cmp/fuzzy/ffi.lua +++ b/lua/blink/cmp/fuzzy/ffi.lua @@ -18,34 +18,22 @@ end - typedef struct { const int32_t *ptr; size_t len; size_t capacity; } blink_cmp_fuzzy__Vec_int32_t; -typedef struct { - const uint32_t *ptr; - size_t len; - size_t capacity; -} blink_cmp_fuzzy__Vec_uint32_t; -typedef struct { - const int32_t *ptr; -} blink_cmp_fuzzy__Option_int32_t; -typedef struct { - const char * *ptr; - size_t len; - size_t capacity; -} blink_cmp_fuzzy__Vec___string_ptr; -typedef struct { - const blink_cmp_fuzzy__Vec___string_ptr *ptr; -} blink_cmp_fuzzy__Option_Vec___string_ptr; + typedef struct { const char * *ptr; } blink_cmp_fuzzy__Option___string_ptr; +typedef struct { + const int32_t *ptr; +} blink_cmp_fuzzy__Option_int32_t; + typedef struct { const char * label; const blink_cmp_fuzzy__Option___string_ptr sort_text; @@ -55,10 +43,24 @@ typedef struct { const char * source; } blink_cmp_fuzzy__LspItem; +typedef struct { + const uint32_t *ptr; + size_t len; + size_t capacity; +} blink_cmp_fuzzy__Vec_uint32_t; +typedef struct { + const char * *ptr; + size_t len; + size_t capacity; +} blink_cmp_fuzzy__Vec___string_ptr; +typedef struct { + const blink_cmp_fuzzy__Vec___string_ptr *ptr; +} blink_cmp_fuzzy__Option_Vec___string_ptr; typedef struct { const int8_t use_frecency; const blink_cmp_fuzzy__Option_Vec___string_ptr nearby_words; + const uint16_t min_score; const size_t max_items; const blink_cmp_fuzzy__Vec___string_ptr sorts; } blink_cmp_fuzzy__FuzzyOptions; @@ -101,9 +103,9 @@ int32_t __gc_get_words( -local __const_c_typename_bool = ffi.typeof("const int8_t[?]") -local __c_function_argument_bool = ffi.typeof("int8_t[?]") -local __c_mut_function_argument_bool = ffi.typeof("int8_t[?]") +local __const_c_typename_size_t = ffi.typeof("const size_t[?]") +local __c_function_argument_size_t = ffi.typeof("size_t[?]") +local __c_mut_function_argument_size_t = ffi.typeof("size_t[?]") local __const_c_typename_int32_t = ffi.typeof("const int32_t[?]") @@ -111,11 +113,6 @@ local __c_function_argument_int32_t = ffi.typeof("int32_t[?]") local __c_mut_function_argument_int32_t = ffi.typeof("int32_t[?]") -local __const_c_typename_size_t = ffi.typeof("const size_t[?]") -local __c_function_argument_size_t = ffi.typeof("size_t[?]") -local __c_mut_function_argument_size_t = ffi.typeof("size_t[?]") - - local __typename_Vec_int32_t = ffi.metatype("blink_cmp_fuzzy__Vec_int32_t", {}) local __const_c_typename_Vec_int32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_int32_t[?]") 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[?]") local __c_mut_function_argument_uint32_t = ffi.typeof("uint32_t[?]") -local __typename_Vec_uint32_t = ffi.metatype("blink_cmp_fuzzy__Vec_uint32_t", {}) -local __const_c_typename_Vec_uint32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_uint32_t[?]") -local __c_function_argument_Vec_uint32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_uint32_t*[?]") -local __c_mut_function_argument_Vec_uint32_t = ffi.typeof("blink_cmp_fuzzy__Vec_uint32_t*[?]") +local __const_c_typename_uint16_t = ffi.typeof("const uint16_t[?]") +local __c_function_argument_uint16_t = ffi.typeof("uint16_t[?]") +local __c_mut_function_argument_uint16_t = ffi.typeof("uint16_t[?]") + + +local __const_c_typename___string_ptr = ffi.typeof("const char *[?]") +local __c_function_argument___string_ptr = ffi.typeof("const char *[?]") +local __c_mut_function_argument___string_ptr = ffi.typeof("char *[?]") + + +local __typename_Option___string_ptr = ffi.metatype("blink_cmp_fuzzy__Option___string_ptr", {}) +local __const_c_typename_Option___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option___string_ptr[?]") +local __c_function_argument_Option___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option___string_ptr*[?]") +local __c_mut_function_argument_Option___string_ptr = ffi.typeof("blink_cmp_fuzzy__Option___string_ptr*[?]") + + +local __const_c_typename_bool = ffi.typeof("const int8_t[?]") +local __c_function_argument_bool = ffi.typeof("int8_t[?]") +local __c_mut_function_argument_bool = ffi.typeof("int8_t[?]") 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__ local __c_mut_function_argument_Option_int32_t = ffi.typeof("blink_cmp_fuzzy__Option_int32_t*[?]") -local __const_c_typename___string_ptr = ffi.typeof("const char *[?]") -local __c_function_argument___string_ptr = ffi.typeof("const char *[?]") -local __c_mut_function_argument___string_ptr = ffi.typeof("char *[?]") +local __typename_LspItem = ffi.metatype("blink_cmp_fuzzy__LspItem", {}) +local __const_c_typename_LspItem = ffi.typeof("const blink_cmp_fuzzy__LspItem[?]") +local __c_function_argument_LspItem = ffi.typeof("const blink_cmp_fuzzy__LspItem*[?]") +local __c_mut_function_argument_LspItem = ffi.typeof("blink_cmp_fuzzy__LspItem*[?]") + + +local __typename_Vec_uint32_t = ffi.metatype("blink_cmp_fuzzy__Vec_uint32_t", {}) +local __const_c_typename_Vec_uint32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_uint32_t[?]") +local __c_function_argument_Vec_uint32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_uint32_t*[?]") +local __c_mut_function_argument_Vec_uint32_t = ffi.typeof("blink_cmp_fuzzy__Vec_uint32_t*[?]") 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 local __c_mut_function_argument_Option_Vec___string_ptr = ffi.typeof("blink_cmp_fuzzy__Option_Vec___string_ptr*[?]") -local __typename_Option___string_ptr = ffi.metatype("blink_cmp_fuzzy__Option___string_ptr", {}) -local __const_c_typename_Option___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option___string_ptr[?]") -local __c_function_argument_Option___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option___string_ptr*[?]") -local __c_mut_function_argument_Option___string_ptr = ffi.typeof("blink_cmp_fuzzy__Option___string_ptr*[?]") - - -local __typename_LspItem = ffi.metatype("blink_cmp_fuzzy__LspItem", {}) -local __const_c_typename_LspItem = ffi.typeof("const blink_cmp_fuzzy__LspItem[?]") -local __c_function_argument_LspItem = ffi.typeof("const blink_cmp_fuzzy__LspItem*[?]") -local __c_mut_function_argument_LspItem = ffi.typeof("blink_cmp_fuzzy__LspItem*[?]") - - local __typename_FuzzyOptions = ffi.metatype("blink_cmp_fuzzy__FuzzyOptions", {}) local __const_c_typename_FuzzyOptions = ffi.typeof("const blink_cmp_fuzzy__FuzzyOptions[?]") local __c_function_argument_FuzzyOptions = ffi.typeof("const blink_cmp_fuzzy__FuzzyOptions*[?]") @@ -348,6 +355,7 @@ end end end )(value.nearby_words), + (function(value) return value end)(value.min_score), (function(value) return value end)(value.max_items), ( function(value) diff --git a/lua/blink/cmp/fuzzy/fuzzy.rs b/lua/blink/cmp/fuzzy/fuzzy.rs index ea8ec854..5704ed50 100644 --- a/lua/blink/cmp/fuzzy/fuzzy.rs +++ b/lua/blink/cmp/fuzzy/fuzzy.rs @@ -28,6 +28,7 @@ pub struct MatchedLspItem { pub struct FuzzyOptions { use_frecency: bool, nearby_words: Option>, + min_score: u16, max_items: usize, sorts: Vec, } @@ -46,7 +47,7 @@ pub fn fuzzy( .map(|s| s.label.as_str()) .collect::>(); let options = frizbee::Options { - min_score: 0, + min_score: opts.min_score, stable_sort: false, ..Default::default() }; @@ -57,38 +58,36 @@ pub fn fuzzy( .iter() .map(|mtch| { (mtch.score as i32) - + frecency.get_score(&haystack[mtch.index]) as i32 + + frecency.get_score(&haystack[mtch.index_in_haystack]) as i32 + nearby_words - .get(&haystack[mtch.index].label) + .get(&haystack[mtch.index_in_haystack].label) .map(|_| 2) .unwrap_or(0) - + haystack[mtch.index].score_offset.unwrap_or(0) + + haystack[mtch.index_in_haystack].score_offset.unwrap_or(0) }) .collect::>(); matches.sort_by_cached_key(|mtch| Reverse(match_scores[mtch.index])); - // Grab the top N matches - let mut match_indices = matches - .iter() - .map(|mtch| mtch.index) - .take(opts.max_items) - .collect::>(); - // Sort matches by sort criteria for sort in opts.sorts.iter() { match sort.as_str() { "kind" => { - match_indices.sort_by_key(|idx| haystack[*idx].kind); + matches.sort_by_key(|mtch| haystack[mtch.index_in_haystack].kind); } "score" => { - match_indices.sort_by_key(|idx| Reverse(match_scores[*idx])); + matches.sort_by_key(|mtch| Reverse(mtch.score)); } "label" => { - match_indices.sort_by_key(|idx| haystack[*idx].label.clone()); + matches.sort_by_key(|mtch| haystack[mtch.index_in_haystack].label.clone()); } _ => {} } } - match_indices + // Grab the top N matches and return the indices + matches + .iter() + .map(|mtch| mtch.index_in_haystack) + .take(opts.max_items) + .collect::>() } diff --git a/lua/blink/cmp/fuzzy/init.lua b/lua/blink/cmp/fuzzy/init.lua index 4bc6c101..d9828220 100644 --- a/lua/blink/cmp/fuzzy/init.lua +++ b/lua/blink/cmp/fuzzy/init.lua @@ -42,12 +42,17 @@ function fuzzy.filter_items(needle, items) local filtered_items = {} local matched_indices = fuzzy.rust.fuzzy(needle, haystack_labels, haystack_kinds, haystack_score_offsets, haystack_sources, { + -- each matching char is worth 4 points and it receives a bonus for capitalization, delimiter and prefix + -- so this should generally be good + -- TODO: make this configurable + min_score = 4 * needle:len(), max_items = config.max_items, use_frecency = config.use_frecency, use_proximity = config.use_proximity, sorts = config.sorts, nearby_words = nearby_words, }) + for _, idx in ipairs(matched_indices) do table.insert(filtered_items, items[idx + 1]) end