diff options
| author | fdschmidt93 <39233597+fdschmidt93@users.noreply.github.com> | 2021-03-09 21:04:21 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-09 21:04:21 +0100 |
| commit | 559bf36e73dc827cff7edd7b726c7a0d73493829 (patch) | |
| tree | 385cda8c343eee0e90437bf9a62c0363a1df8b4c /lua/telescope | |
| parent | ff428c91879d7d5ffa22d950cd53b5eeff3553dc (diff) | |
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
Diffstat (limited to 'lua/telescope')
| -rw-r--r-- | lua/telescope/actions/init.lua | 43 | ||||
| -rw-r--r-- | lua/telescope/mappings.lua | 1 | ||||
| -rw-r--r-- | lua/telescope/sorters.lua | 25 |
3 files changed, 65 insertions, 4 deletions
diff --git a/lua/telescope/actions/init.lua b/lua/telescope/actions/init.lua index d0bd27c..5741554 100644 --- a/lua/telescope/actions/init.lua +++ b/lua/telescope/actions/init.lua @@ -420,6 +420,49 @@ actions.smart_send_to_qflist = function(prompt_bufnr) 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 actions.open_qflist = function(_) vim.cmd [[copen]] diff --git a/lua/telescope/mappings.lua b/lua/telescope/mappings.lua index 40a52f3..d6ebe04 100644 --- a/lua/telescope/mappings.lua +++ b/lua/telescope/mappings.lua @@ -28,6 +28,7 @@ mappings.default_mappings = config.values.default_mappings or { ["<S-Tab>"] = actions.toggle_selection + actions.move_selection_better, ["<C-q>"] = actions.send_to_qflist + actions.open_qflist, ["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist, + ["<C-l>"] = actions.complete_tag }, n = { diff --git a/lua/telescope/sorters.lua b/lua/telescope/sorters.lua index 6ae404d..5ac7086 100644 --- a/lua/telescope/sorters.lua +++ b/lua/telescope/sorters.lua @@ -39,6 +39,7 @@ function Sorter:new(opts) return setmetatable({ state = {}, + tags = opts.tags, filter_function = opts.filter_function, scoring_function = opts.scoring_function, highlighter = opts.highlighter, @@ -87,6 +88,7 @@ function Sorter:score(prompt, entry) local filter_score if self.filter_function ~= nil then + if self.tags then self.tags:insert(entry) end filter_score, prompt = self:filter_function(prompt, entry) end @@ -476,7 +478,7 @@ end local substr_matcher = function(_, prompt, line, _) 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 total_search_terms = 0 for _, word in pairs(search_terms) do @@ -492,10 +494,9 @@ end local filter_function = function(opts) local scoring_function = vim.F.if_nil(opts.filter_function, substr_matcher) local tag = vim.F.if_nil(opts.tag, "ordinal") - local delimiter = vim.F.if_nil(opts.delimiter, ":") return function(_, prompt, entry) - local filter = "^(" .. delimiter .. "(%S+)" .. "[" .. delimiter .. "%s]" .. ")" + local filter = "^(" .. opts.delimiter .. "(%S+)" .. "[" .. opts.delimiter .. "%s]" .. ")" local matched = prompt:match(filter) if matched == nil then @@ -503,13 +504,29 @@ local filter_function = function(opts) end -- clear prompt of tag 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 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) 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._was_discarded = function() return false end return sorter |
