feat: add completion to pre-filtering (#626)
Works by pressing `<C-l>` in insert mode. Supported are all builtins that have prefiltering. Means: - lsp_workspace_symbols - lsp_workspace_diagnostics - lsp_document_symbols - lsp_document_diagnostics
This commit is contained in:
@@ -420,6 +420,49 @@ actions.smart_send_to_qflist = function(prompt_bufnr)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
actions.complete_tag = function(prompt_bufnr)
|
||||||
|
local current_picker = action_state.get_current_picker(prompt_bufnr)
|
||||||
|
local tags = current_picker.sorter.tags
|
||||||
|
local delimiter = current_picker.sorter._delimiter
|
||||||
|
|
||||||
|
if not tags then
|
||||||
|
print('No tag pre-filtering set for this picker')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- format tags to match filter_function
|
||||||
|
local prefilter_tags = {}
|
||||||
|
for tag, _ in pairs(tags) do
|
||||||
|
table.insert(prefilter_tags, string.format('%s%s%s ', delimiter, tag:lower(), delimiter))
|
||||||
|
end
|
||||||
|
|
||||||
|
local line = action_state.get_current_line()
|
||||||
|
local filtered_tags = {}
|
||||||
|
-- retrigger completion with already selected tag anew
|
||||||
|
-- trim and add space since we can match [[:pattern: ]] with or without space at the end
|
||||||
|
if vim.tbl_contains(prefilter_tags, vim.trim(line) .. " ") then
|
||||||
|
filtered_tags = prefilter_tags
|
||||||
|
else
|
||||||
|
-- match tag by substring
|
||||||
|
for _, tag in pairs(prefilter_tags) do
|
||||||
|
local start, _ = tag:find(line)
|
||||||
|
if start then
|
||||||
|
table.insert(filtered_tags, tag)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if vim.tbl_isempty(filtered_tags) then
|
||||||
|
print('No matches found')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- incremental completion by substituting string starting from col - #line byte offset
|
||||||
|
local col = vim.api.nvim_win_get_cursor(0)[2] + 1
|
||||||
|
vim.fn.complete(col - #line, filtered_tags)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Open the quickfix list
|
--- Open the quickfix list
|
||||||
actions.open_qflist = function(_)
|
actions.open_qflist = function(_)
|
||||||
vim.cmd [[copen]]
|
vim.cmd [[copen]]
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ mappings.default_mappings = config.values.default_mappings or {
|
|||||||
["<S-Tab>"] = actions.toggle_selection + actions.move_selection_better,
|
["<S-Tab>"] = actions.toggle_selection + actions.move_selection_better,
|
||||||
["<C-q>"] = actions.send_to_qflist + actions.open_qflist,
|
["<C-q>"] = actions.send_to_qflist + actions.open_qflist,
|
||||||
["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist,
|
["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist,
|
||||||
|
["<C-l>"] = actions.complete_tag
|
||||||
},
|
},
|
||||||
|
|
||||||
n = {
|
n = {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ function Sorter:new(opts)
|
|||||||
|
|
||||||
return setmetatable({
|
return setmetatable({
|
||||||
state = {},
|
state = {},
|
||||||
|
tags = opts.tags,
|
||||||
filter_function = opts.filter_function,
|
filter_function = opts.filter_function,
|
||||||
scoring_function = opts.scoring_function,
|
scoring_function = opts.scoring_function,
|
||||||
highlighter = opts.highlighter,
|
highlighter = opts.highlighter,
|
||||||
@@ -87,6 +88,7 @@ function Sorter:score(prompt, entry)
|
|||||||
|
|
||||||
local filter_score
|
local filter_score
|
||||||
if self.filter_function ~= nil then
|
if self.filter_function ~= nil then
|
||||||
|
if self.tags then self.tags:insert(entry) end
|
||||||
filter_score, prompt = self:filter_function(prompt, entry)
|
filter_score, prompt = self:filter_function(prompt, entry)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -476,7 +478,7 @@ end
|
|||||||
|
|
||||||
local substr_matcher = function(_, prompt, line, _)
|
local substr_matcher = function(_, prompt, line, _)
|
||||||
local display = line:lower()
|
local display = line:lower()
|
||||||
local search_terms = util.max_split(prompt, "%s")
|
local search_terms = util.max_split(prompt:lower(), "%s")
|
||||||
local matched = 0
|
local matched = 0
|
||||||
local total_search_terms = 0
|
local total_search_terms = 0
|
||||||
for _, word in pairs(search_terms) do
|
for _, word in pairs(search_terms) do
|
||||||
@@ -492,10 +494,9 @@ end
|
|||||||
local filter_function = function(opts)
|
local filter_function = function(opts)
|
||||||
local scoring_function = vim.F.if_nil(opts.filter_function, substr_matcher)
|
local scoring_function = vim.F.if_nil(opts.filter_function, substr_matcher)
|
||||||
local tag = vim.F.if_nil(opts.tag, "ordinal")
|
local tag = vim.F.if_nil(opts.tag, "ordinal")
|
||||||
local delimiter = vim.F.if_nil(opts.delimiter, ":")
|
|
||||||
|
|
||||||
return function(_, prompt, entry)
|
return function(_, prompt, entry)
|
||||||
local filter = "^(" .. delimiter .. "(%S+)" .. "[" .. delimiter .. "%s]" .. ")"
|
local filter = "^(" .. opts.delimiter .. "(%S+)" .. "[" .. opts.delimiter .. "%s]" .. ")"
|
||||||
local matched = prompt:match(filter)
|
local matched = prompt:match(filter)
|
||||||
|
|
||||||
if matched == nil then
|
if matched == nil then
|
||||||
@@ -503,13 +504,29 @@ local filter_function = function(opts)
|
|||||||
end
|
end
|
||||||
-- clear prompt of tag
|
-- clear prompt of tag
|
||||||
prompt = prompt:sub(#matched + 1, -1)
|
prompt = prompt:sub(#matched + 1, -1)
|
||||||
local query = vim.trim(matched:gsub(delimiter, ""))
|
local query = vim.trim(matched:gsub(opts.delimiter, ""))
|
||||||
return scoring_function(_, query, entry[tag], _), prompt
|
return scoring_function(_, query, entry[tag], _), prompt
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function create_tag_set(tag)
|
||||||
|
tag = vim.F.if_nil(tag, 'ordinal')
|
||||||
|
local set = {}
|
||||||
|
return setmetatable(set, {
|
||||||
|
__index = {
|
||||||
|
insert = function(set_, entry)
|
||||||
|
local value = entry[tag]
|
||||||
|
if not set_[value] then set_[value] = true end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
sorters.prefilter = function(opts)
|
sorters.prefilter = function(opts)
|
||||||
local sorter = opts.sorter
|
local sorter = opts.sorter
|
||||||
|
opts.delimiter = util.get_default(opts.delimiter, ':')
|
||||||
|
sorter._delimiter = opts.delimiter
|
||||||
|
sorter.tags = create_tag_set(opts.tag)
|
||||||
sorter.filter_function = filter_function(opts)
|
sorter.filter_function = filter_function(opts)
|
||||||
sorter._was_discarded = function() return false end
|
sorter._was_discarded = function() return false end
|
||||||
return sorter
|
return sorter
|
||||||
|
|||||||
Reference in New Issue
Block a user