Skip to content

Commit

Permalink
perf: delay fuzzy match on displayed vim item
Browse files Browse the repository at this point in the history
`entry.get_vim_item` is a very heavy call, especially when user do
complex stuff on item formatting. Delay its call to window displaying to
let `performance.max_view_entries` applied to it.
  • Loading branch information
yioneko committed Jul 11, 2024
1 parent cdbb74e commit ef88411
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 10 deletions.
46 changes: 38 additions & 8 deletions lua/cmp/entry.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ local matcher = require('cmp.matcher')
---@field public offset integer
---@field public word string
---@field public filter_text string
---@field private match_view_args_ret {input:string, word:string, option:cmp.MatchingConfig, matches:table[]}
local entry = {}

---Create new entry
Expand Down Expand Up @@ -391,7 +392,17 @@ entry.match = function(self, input, matching_config)
-- https://www.lua.org/pil/11.6.html
-- do not use '..' to allocate multiple strings
local cache_key = string.format('%s:%d:%d:%d:%d:%d:%d', input, self.resolved_completion_item and 1 or 0, matching_config.disallow_fuzzy_matching and 1 or 0, matching_config.disallow_partial_matching and 1 or 0, matching_config.disallow_prefix_unmatching and 1 or 0, matching_config.disallow_partial_fuzzy_matching and 1 or 0, matching_config.disallow_symbol_nonprefix_matching and 1 or 0)
return self.match_cache:ensure(cache_key, entry._match, self, input, matching_config)
local matched = self.match_cache:get(cache_key)
if matched then
if self.match_view_args_ret then
self.match_view_args_ret.input = input
self.match_view_args_ret.matches = matched.matches
end
return matched
end
matched = self:_match(input, matching_config)
self.match_cache:set(cache_key, matched)
return matched
end

---@package
Expand All @@ -409,7 +420,7 @@ entry._match = function(self, input, matching_config)
},
}

local score, matches, filter_text, _
local score, matches, filter_text
local checked = {} ---@type table<string, boolean>

filter_text = self.filter_text
Expand Down Expand Up @@ -438,17 +449,36 @@ entry._match = function(self, input, matching_config)

-- Fix highlight if filterText is not the same to vim_item.abbr.
if score > 0 then
local vim_item = self:get_vim_item(self.source_offset)
filter_text = vim_item.abbr or vim_item.word
if not checked[filter_text] then
local diff = self.source_offset - self.offset
_, matches = matcher.match(input:sub(1 + diff), filter_text, option)
end
self.match_view_args_ret = {
input = input,
word = filter_text,
option = option,
matches = matches,
}
end

return { score = score, matches = matches }
end

---@param view string
entry.get_view_matches = function(self, view)
local args_ret = self.match_view_args_ret
if args_ret then
if args_ret.word == view then
return args_ret.matches
end
local input = args_ret.input
local diff = self.source_offset - self.offset
if diff > 0 then
input = input:sub(1 + diff)
end
local _, matches = matcher.match(input, view, args_ret.option)
args_ret.word = view
args_ret.matches = matches
return matches
end
end

---@deprecated use entry.completion_item instead
entry.get_completion_item = function(self)
return self.completion_item
Expand Down
2 changes: 1 addition & 1 deletion lua/cmp/view/custom_entries_view.lua
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ custom_entries_view.new = function()
o = o + v[field].bytes + (self.column_width[field] - v[field].width) + 1
end

for _, m in ipairs(e.matches or {}) do
for _, m in ipairs(e:get_view_matches(v.abbr.text) or {}) do
vim.api.nvim_buf_set_extmark(buf, custom_entries_view.ns, i, a + m.word_match_start - 1, {
end_line = i,
end_col = a + m.word_match_end,
Expand Down
2 changes: 1 addition & 1 deletion lua/cmp/view/wildmenu_entries_view.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ wildmenu_entries_view.new = function()
})
end

for _, m in ipairs(e.matches or {}) do
for _, m in ipairs(e:get_view_matches(view.abbr.text) or {}) do
vim.api.nvim_buf_set_extmark(buf, wildmenu_entries_view.ns, 0, self.offsets[i] + m.word_match_start - 1, {
end_line = 0,
end_col = self.offsets[i] + m.word_match_end,
Expand Down

0 comments on commit ef88411

Please sign in to comment.