feat: detect upper case letters with get_substr_matcher (#2950)

* feat: detect upper case letters by substr matcher

* test: add tests for get_substr_matcher
This commit is contained in:
JINNOUCHI Yasushi
2024-03-20 14:24:31 +09:00
committed by GitHub
parent 3b8399c273
commit f06eeb79e1
2 changed files with 111 additions and 19 deletions

View File

@@ -511,9 +511,10 @@ sorters.get_levenshtein_sorter = function()
} }
end end
local substr_highlighter = function(_, prompt, display) local substr_highlighter = function(make_display)
return function(_, prompt, display)
local highlights = {} local highlights = {}
display = display:lower() display = make_display(prompt, display)
local search_terms = util.max_split(prompt, "%s") local search_terms = util.max_split(prompt, "%s")
local hl_start, hl_end local hl_start, hl_end
@@ -526,29 +527,36 @@ local substr_highlighter = function(_, prompt, display)
end end
return highlights return highlights
end
end end
sorters.get_substr_matcher = function() sorters.get_substr_matcher = function()
local make_display = vim.o.smartcase
and function(prompt, display)
local has_upper_case = not not prompt:match "%u"
return has_upper_case and display or display:lower()
end
or function(_, display)
return display:lower()
end
return Sorter:new { return Sorter:new {
highlighter = substr_highlighter, highlighter = substr_highlighter(make_display),
scoring_function = function(_, prompt, _, entry) scoring_function = function(_, prompt, _, entry)
if #prompt == 0 then if #prompt == 0 then
return 1 return 1
end end
local display = entry.ordinal:lower() local display = make_display(prompt, entry.ordinal)
local search_terms = util.max_split(prompt, "%s") local search_terms = util.max_split(prompt, "%s")
local matched = 0
local total_search_terms = 0
for _, word in pairs(search_terms) do for _, word in pairs(search_terms) do
total_search_terms = total_search_terms + 1 if not display:find(word, 1, true) then
if display:find(word, 1, true) then return -1
matched = matched + 1
end end
end end
return matched == total_search_terms and entry.index or -1 return entry.index
end, end,
} }
end end

View File

@@ -0,0 +1,84 @@
local sorters = require "telescope.sorters"
describe("get_substr_matcher", function()
local function with_smartcase(smartcase, case)
local original = vim.o.smartcase
vim.o.smartcase = smartcase
describe("scoring_function", function()
it(case.msg, function()
local matcher = sorters.get_substr_matcher()
assert.are.same(case.expected_score, matcher.scoring_function(_, case.prompt, _, case.entry))
end)
end)
describe("highlighter", function()
it("returns valid highlights", function()
local matcher = sorters.get_substr_matcher()
local highlights = matcher.highlighter(_, case.prompt, case.entry.ordinal)
table.sort(highlights, function(a, b)
return a.start < b.start
end)
assert.are.same(case.expected_highlights, highlights)
end)
end)
vim.o.smartcase = original
end
describe("when smartcase=OFF", function()
for _, case in ipairs {
{
msg = "doesn't match",
prompt = "abc def",
entry = { index = 3, ordinal = "abc d" },
expected_score = -1,
expected_highlights = { { start = 1, finish = 3 } },
},
{
msg = "matches with lower case letters only",
prompt = "abc def",
entry = { index = 3, ordinal = "abc def ghi" },
expected_score = 3,
expected_highlights = { { start = 1, finish = 3 }, { start = 5, finish = 7 } },
},
{
msg = "doesn't match with upper case letters",
prompt = "ABC def",
entry = { index = 3, ordinal = "ABC def ghi" },
expected_score = -1,
expected_highlights = { { start = 5, finish = 7 } },
},
} do
with_smartcase(false, case)
end
end)
describe("when smartcase=OFF", function()
for _, case in ipairs {
{
msg = "doesn't match",
prompt = "abc def",
entry = { index = 3, ordinal = "abc d" },
expected_score = -1,
expected_highlights = { { start = 1, finish = 3 } },
},
{
msg = "matches with lower case letters only",
prompt = "abc def",
entry = { index = 3, ordinal = "abc def ghi" },
expected_score = 3,
expected_highlights = { { start = 1, finish = 3 }, { start = 5, finish = 7 } },
},
{
msg = "matches with upper case letters",
prompt = "ABC def",
entry = { index = 3, ordinal = "ABC def ghi" },
expected_score = 3,
expected_highlights = { { start = 1, finish = 3 }, { start = 5, finish = 7 } },
},
} do
with_smartcase(true, case)
end
end)
end)