Skip to content

Commit 049c0ee

Browse files
phanenibhagwan
authored andcommitted
fix(symbols): fuzzy match as fallback
1 parent bd69cba commit 049c0ee

File tree

1 file changed

+52
-8
lines changed

1 file changed

+52
-8
lines changed

lua/fzf-lua/providers/lsp.lua

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,56 @@ local function symbols_to_items(opts, symbols, bufnr, child_prefix)
232232
return _symbols_to_items(symbols, {}, bufnr or 0, "")
233233
end
234234

235+
---@param text string
236+
---@param query string
237+
---@param hl_func fun(s: string): string
238+
---@return string
239+
local function fuzzy_highlight(text, query, hl_func)
240+
if not query or #query == 0 then
241+
return text
242+
end
243+
244+
local s, e
245+
if query:find("%u") then -- exact match
246+
s, e = text:find(query, 1, true)
247+
end
248+
if not s then -- case-insensitive match
249+
s, e = text:lower():find(query:lower(), 1, true)
250+
end
251+
if s and e then
252+
return text:sub(1, s - 1)
253+
.. hl_func(text:sub(s, e))
254+
.. text:sub(e + 1)
255+
end
256+
257+
-- fuzzy match: highlight only matched chars
258+
local text_lower = text:lower()
259+
local query_lower = query:lower()
260+
local match_indices = {}
261+
local ti, qi = 1, 1
262+
while ti <= #text and qi <= #query do
263+
if text_lower:sub(ti, ti) == query_lower:sub(qi, qi) then
264+
match_indices[#match_indices + 1] = ti
265+
qi = qi + 1
266+
end
267+
ti = ti + 1
268+
end
269+
if #match_indices ~= #query then
270+
return text
271+
end
272+
local buf = {}
273+
local mi = 1
274+
for i = 1, #text do
275+
if mi <= #match_indices and i == match_indices[mi] then
276+
buf[#buf + 1] = hl_func(text:sub(i, i))
277+
mi = mi + 1
278+
else
279+
buf[#buf + 1] = text:sub(i, i)
280+
end
281+
end
282+
return table.concat(buf)
283+
end
284+
235285
local function symbol_handler(opts, cb, _, result, ctx, _)
236286
result = utils.tbl_islist(result) and result or { result }
237287
local items
@@ -250,15 +300,9 @@ local function symbol_handler(opts, cb, _, result, ctx, _)
250300
(not opts._regex_filter_fn or opts._regex_filter_fn(entry, utils.CTX())) then
251301
local mbicon_align = 0
252302
if opts.is_live and type(opts.query) == "string" and #opts.query > 0 then
253-
-- highlight exact matches with `live_workspace_symbols` (#1028)
303+
-- highlight exact or fuzzy matches with `live_workspace_symbols` (#1028)
254304
local sym, text = entry.text:match("^(.+%])(.*)$")
255-
local s, e = text:lower():find(opts.query:lower(), 1, true)
256-
if s and e then
257-
text = text:sub(1, s - 1)
258-
.. utils.ansi_codes[opts.hls.live_sym](text:sub(s, e))
259-
.. text:sub(e + 1)
260-
end
261-
entry.text = sym .. text
305+
entry.text = sym .. fuzzy_highlight(text, opts.query, utils.ansi_codes[opts.hls.live_sym])
262306
end
263307
if M._sym2style then
264308
local kind = entry.text:match("%[(.-)%]")

0 commit comments

Comments
 (0)