feat: lsp diagnostics and prefiltering by entry attribute (#543)
prefiltering for lsp_document_symbols and lsp_workspace_symbols. example: type `:var:` to show all vars
This commit is contained in:
@@ -18,6 +18,7 @@ globals = {
|
||||
"TelescopeCachedTails",
|
||||
"TelescopeCachedNgrams",
|
||||
"_TelescopeConfigurationValues",
|
||||
"__TelescopeKeymapStore",
|
||||
}
|
||||
|
||||
-- Global objects defined by the C code
|
||||
|
||||
@@ -409,6 +409,7 @@ Built-in functions. Ready to be bound to any key you like. :smile:
|
||||
| `builtin.lsp_workspace_symbols` | Searches in LSP all workspace symbols. |
|
||||
| `builtin.lsp_code_actions` | Lists LSP action to be trigged on enter. |
|
||||
| `builtin.lsp_range_code_actions` | Lists LSP range code action to be trigged on enter. |
|
||||
| `builtin.lsp_diagnostics` | Lists LSP Diagnostics in the current document. |
|
||||
| .................................. | Your next awesome picker function here :D |
|
||||
|
||||
### Git Pickers
|
||||
|
||||
@@ -252,16 +252,16 @@ previewers.Previewer() *previewers.Previewer()*
|
||||
|
||||
|
||||
|
||||
previewers.buffer_previewer_maker({opts}, {bufnr}, {filepath})*previewers.buffer_previewer_maker()*
|
||||
previewers.buffer_previewer_maker({filepath}, {bufnr}, {opts})*previewers.buffer_previewer_maker()*
|
||||
A universal way of reading a file into a buffer previewer. It handles async
|
||||
reading, cache, highlighting, displaying directories and provides a
|
||||
callback which can be used, to jump to a line in the buffer.
|
||||
|
||||
|
||||
Parameters: ~
|
||||
{opts} (table) keys: `use_ft_detect`, `bufname` and `callback`
|
||||
{bufnr} (number) Where the content will be written
|
||||
{filepath} (string) String to the filepath, will be expanded
|
||||
{bufnr} (number) Where the content will be written
|
||||
{opts} (table) keys: `use_ft_detect`, `bufname` and `callback`
|
||||
|
||||
|
||||
previewers.cat() *previewers.cat()*
|
||||
|
||||
@@ -64,6 +64,7 @@ builtin.spell_suggest = require('telescope.builtin.internal').spell_suggest
|
||||
builtin.lsp_references = require('telescope.builtin.lsp').references
|
||||
builtin.lsp_document_symbols = require('telescope.builtin.lsp').document_symbols
|
||||
builtin.lsp_code_actions = require('telescope.builtin.lsp').code_actions
|
||||
builtin.lsp_diagnostics = require('telescope.builtin.lsp').diagnostics
|
||||
builtin.lsp_range_code_actions = require('telescope.builtin.lsp').range_code_actions
|
||||
builtin.lsp_workspace_symbols = require('telescope.builtin.lsp').workspace_symbols
|
||||
|
||||
|
||||
@@ -64,7 +64,10 @@ lsp.document_symbols = function(opts)
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts)
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
sorter = conf.prefilter_sorter{
|
||||
tag = "symbol_type",
|
||||
sorter = conf.generic_sorter(opts)
|
||||
}
|
||||
}):find()
|
||||
end
|
||||
|
||||
@@ -180,7 +183,32 @@ lsp.workspace_symbols = function(opts)
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts)
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
sorter = conf.prefilter_sorter{
|
||||
tag = "symbol_type",
|
||||
sorter = conf.generic_sorter(opts)
|
||||
}
|
||||
}):find()
|
||||
end
|
||||
|
||||
lsp.diagnostics = function(opts)
|
||||
local locations = utils.diagnostics_to_tbl(opts)
|
||||
|
||||
if vim.tbl_isempty(locations) then
|
||||
print('No diagnostics found')
|
||||
return
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = 'LSP Diagnostics',
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_diagnostics(opts)
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.prefilter_sorter{
|
||||
tag = "type",
|
||||
sorter = conf.generic_sorter(opts)
|
||||
}
|
||||
}):find()
|
||||
end
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ function config.set_defaults(defaults)
|
||||
set("default_mappings", nil)
|
||||
|
||||
set("generic_sorter", sorters.get_generic_fuzzy_sorter)
|
||||
set("prefilter_sorter", sorters.prefilter)
|
||||
set("file_sorter", sorters.get_fuzzy_file)
|
||||
|
||||
set("file_ignore_patterns", nil)
|
||||
|
||||
@@ -27,6 +27,13 @@ local lsp_type_highlight = {
|
||||
["Variable"] = "TelescopeResultsVariable",
|
||||
}
|
||||
|
||||
local lsp_type_diagnostic = {
|
||||
[1] = "Error",
|
||||
[2] = "Warning",
|
||||
[3] = "Information",
|
||||
[4] = "Hint"
|
||||
}
|
||||
|
||||
local make_entry = {}
|
||||
|
||||
do
|
||||
@@ -847,6 +854,77 @@ function make_entry.gen_from_ctags(opts)
|
||||
end
|
||||
end
|
||||
|
||||
function make_entry.gen_from_lsp_diagnostics(opts)
|
||||
opts = opts or {}
|
||||
opts.tail_path = utils.get_default(opts.tail_path, true)
|
||||
|
||||
local signs = {}
|
||||
for _, v in pairs(lsp_type_diagnostic) do
|
||||
signs[v] = vim.trim(vim.fn.sign_getdefined("LspDiagnosticsSign" .. v)[1].text)
|
||||
end
|
||||
-- expose line width for longer msg if opts.hide_filename
|
||||
local line_width = utils.get_default(opts.line_width, 48)
|
||||
local displayer = entry_display.create {
|
||||
separator = "▏",
|
||||
items = {
|
||||
{ width = 11 },
|
||||
{ width = line_width },
|
||||
{ remaining = true }
|
||||
}
|
||||
}
|
||||
|
||||
local make_display = function(entry)
|
||||
local filename
|
||||
if not opts.hide_filename then
|
||||
filename = entry.filename
|
||||
if opts.tail_path then
|
||||
filename = utils.path_tail(filename)
|
||||
elseif opts.shorten_path then
|
||||
filename = utils.path_shorten(filename)
|
||||
end
|
||||
end
|
||||
|
||||
-- add styling of entries
|
||||
local pos = string.format("%3d:%2d", entry.lnum, entry.col)
|
||||
local line_info = {
|
||||
string.format("%s %s", signs[entry.type], pos),
|
||||
string.format("LspDiagnosticsDefault%s", entry.type)
|
||||
}
|
||||
-- remove line break to avoid display issues
|
||||
local text = string.format("%-" .. line_width .."s", entry.text:gsub(".* | ", ""):gsub("[\n]", ""))
|
||||
|
||||
return displayer {
|
||||
line_info,
|
||||
text,
|
||||
filename,
|
||||
}
|
||||
end
|
||||
|
||||
return function(entry)
|
||||
local filename = entry.filename or vim.api.nvim_buf_get_name(entry.bufnr)
|
||||
|
||||
return {
|
||||
valid = true,
|
||||
|
||||
value = entry,
|
||||
ordinal = (
|
||||
not opts.ignore_filename and filename
|
||||
or ''
|
||||
) .. ' ' .. entry.text,
|
||||
display = make_display,
|
||||
bufnr = entry.bufnr,
|
||||
filename = filename,
|
||||
type = entry.type,
|
||||
lnum = entry.lnum,
|
||||
col = entry.col,
|
||||
text = entry.text,
|
||||
start = entry.start,
|
||||
finish = entry.finish,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function make_entry.gen_from_autocommands(_)
|
||||
local displayer = entry_display.create {
|
||||
separator = "▏",
|
||||
|
||||
@@ -39,6 +39,7 @@ function Sorter:new(opts)
|
||||
|
||||
return setmetatable({
|
||||
state = {},
|
||||
filter_function = opts.filter_function,
|
||||
scoring_function = opts.scoring_function,
|
||||
highlighter = opts.highlighter,
|
||||
discard = opts.discard,
|
||||
@@ -84,7 +85,13 @@ function Sorter:score(prompt, entry)
|
||||
return FILTERED
|
||||
end
|
||||
|
||||
local score = self:scoring_function(prompt or "", ordinal, entry)
|
||||
local filter_score
|
||||
if self.filter_function ~= nil then
|
||||
filter_score, prompt = self:filter_function(prompt, entry)
|
||||
end
|
||||
|
||||
local score = (filter_score == FILTERED and FILTERED or
|
||||
self:scoring_function(prompt or "", ordinal, entry))
|
||||
|
||||
if score == FILTERED then
|
||||
self:_mark_discarded(prompt, ordinal)
|
||||
@@ -467,4 +474,45 @@ sorters.get_substr_matcher = function()
|
||||
}
|
||||
end
|
||||
|
||||
local substr_matcher = function(_, prompt, line, _)
|
||||
local display = line:lower()
|
||||
local search_terms = util.max_split(prompt, "%s")
|
||||
local matched = 0
|
||||
local total_search_terms = 0
|
||||
for _, word in pairs(search_terms) do
|
||||
total_search_terms = total_search_terms + 1
|
||||
if display:find(word, 1, true) then
|
||||
matched = matched + 1
|
||||
end
|
||||
end
|
||||
|
||||
return matched == total_search_terms and 0 or FILTERED
|
||||
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 matched = prompt:match(filter)
|
||||
|
||||
if matched == nil then
|
||||
return 0, prompt
|
||||
end
|
||||
-- clear prompt of tag
|
||||
prompt = prompt:sub(#matched + 1, -1)
|
||||
local query = vim.trim(matched:gsub(delimiter, ""))
|
||||
return scoring_function(_, query, entry[tag], _), prompt
|
||||
end
|
||||
end
|
||||
|
||||
sorters.prefilter = function(opts)
|
||||
local sorter = opts.sorter
|
||||
sorter.filter_function = filter_function(opts)
|
||||
sorter._was_discarded = function() return false end
|
||||
return sorter
|
||||
end
|
||||
|
||||
return sorters
|
||||
|
||||
@@ -82,6 +82,41 @@ utils.quickfix_items_to_entries = function(locations)
|
||||
return results
|
||||
end
|
||||
|
||||
utils.diagnostics_to_tbl = function(opts)
|
||||
opts = opts or {}
|
||||
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local filename = vim.api.nvim_buf_get_name(bufnr)
|
||||
local buffer_diags = vim.lsp.diagnostic.get(bufnr, opts.client_id)
|
||||
|
||||
local items = {}
|
||||
local lsp_type_diagnostic = {[1] = "Error", [2] = "Warning", [3] = "Information", [4] = "Hint"}
|
||||
local insert_diag = function(diag)
|
||||
local start = diag.range['start']
|
||||
local finish = diag.range['end']
|
||||
local row = start.line
|
||||
local col = start.character
|
||||
|
||||
local line = (vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false) or {""})[1]
|
||||
|
||||
table.insert(items, {
|
||||
bufnr = bufnr,
|
||||
filename = filename,
|
||||
lnum = row + 1,
|
||||
col = col + 1,
|
||||
start = start,
|
||||
finish = finish,
|
||||
text = vim.trim(line .. " | " .. diag.message),
|
||||
type = lsp_type_diagnostic[diag.severity] or lsp_type_diagnostic[1]
|
||||
})
|
||||
end
|
||||
|
||||
for _, diag in ipairs(buffer_diags) do insert_diag(diag) end
|
||||
|
||||
table.sort(items, function(a, b) return a.lnum < b.lnum end)
|
||||
return items
|
||||
end
|
||||
|
||||
-- TODO: Figure out how to do this... could include in plenary :)
|
||||
-- NOTE: Don't use this yet. It will segfault sometimes.
|
||||
--
|
||||
|
||||
Reference in New Issue
Block a user