diff --git a/lua/cmp/config/default.lua b/lua/cmp/config/default.lua index 4db1b5d..15634db 100644 --- a/lua/cmp/config/default.lua +++ b/lua/cmp/config/default.lua @@ -58,7 +58,6 @@ return function() return diff end end - return true end) return entries end diff --git a/lua/cmp/matcher.lua b/lua/cmp/matcher.lua index f97be6f..f55afd1 100644 --- a/lua/cmp/matcher.lua +++ b/lua/cmp/matcher.lua @@ -1,4 +1,5 @@ local char = require('cmp.utils.char') +local str = require('cmp.utils.str') local matcher = {} @@ -72,8 +73,9 @@ end ---Match entry ---@param input string ---@param word string +---@param words string[] ---@return number -matcher.match = function(input, word) +matcher.match = function(input, word, words) -- Empty input if #input == 0 then return matcher.PREFIX_FACTOR + matcher.NOT_FUZZY_FACTOR @@ -108,8 +110,22 @@ matcher.match = function(input, word) return 0 end + -- Add prefix bonus + local prefix = false + if matches[1].input_match_start == 1 and matches[1].word_match_start == 1 then + prefix = true + else + for _, w in ipairs(words or {}) do + if str.has_prefix(w, string.sub(input, matches[1].input_match_start, matches[1].input_match_end)) then + prefix = true + break + end + end + end + -- Compute prefix match score - local score = 0 + local score = prefix and matcher.PREFIX_FACTOR or 0 + local boundary_fixer = prefix and matches[1].index - 1 or 0 local idx = 1 for _, m in ipairs(matches) do local s = 0 @@ -119,14 +135,11 @@ matcher.match = function(input, word) end idx = idx + 1 if s > 0 then - score = score + (s * (1 + math.max(0, matcher.WORD_BOUNDALY_ORDER_FACTOR - m.index) / matcher.WORD_BOUNDALY_ORDER_FACTOR)) + score = score + (s * (1 + math.max(0, matcher.WORD_BOUNDALY_ORDER_FACTOR - (m.index - boundary_fixer)) / matcher.WORD_BOUNDALY_ORDER_FACTOR)) score = score + (m.strict_match and 0.1 or 0) end end - -- Add prefix bonus - score = score + ((matches[1].input_match_start == 1 and matches[1].word_match_start == 1) and matcher.PREFIX_FACTOR or 0) - -- Check remaining input as fuzzy if matches[#matches].input_match_end < #input then if matcher.fuzzy(input, word, matches) then diff --git a/lua/cmp/matcher_spec.lua b/lua/cmp/matcher_spec.lua index 6dca9f2..a7aa66b 100644 --- a/lua/cmp/matcher_spec.lua +++ b/lua/cmp/matcher_spec.lua @@ -20,6 +20,7 @@ describe('matcher', function() assert.is.truthy(matcher.match('candlesingle', 'candle#accept#single') >= 1) assert.is.truthy(matcher.match('conso', 'console') > matcher.match('conso', 'ConstantSourceNode')) assert.is.truthy(matcher.match('var_', 'var_dump') >= 1) + assert.is.truthy(matcher.match('my_', 'my_awesome_variable') > matcher.match('my_', 'completion_matching_strategy_list')) end) it('debug', function() diff --git a/lua/cmp/source.lua b/lua/cmp/source.lua index c7b865d..2537e0b 100644 --- a/lua/cmp/source.lua +++ b/lua/cmp/source.lua @@ -112,9 +112,10 @@ source.get_entries = function(self, ctx) if not inputs[o] then inputs[o] = string.sub(ctx.cursor_before_line, o) end - e.score = matcher.match(inputs[o], e:get_filter_text()) - e.exact = inputs[o] == e:get_filter_text() + e.score = matcher.match(inputs[o], e:get_filter_text(), { e:get_word() }) + e.exact = false if e.score >= 1 then + e.exact = vim.tbl_contains({ e:get_filter_text(), e:get_word() }, inputs[o]) table.insert(entries, e) end end