From 1407ac3400971bcdbcf8b8026ff6957edfada1a3 Mon Sep 17 00:00:00 2001 From: fdschmidt93 <39233597+fdschmidt93@users.noreply.github.com> Date: Thu, 10 Jun 2021 17:13:34 +0200 Subject: [PATCH] feat: improved configuration and sorting of lsp_{document,workspace}_diagnostics (#867) --- doc/telescope.txt | 40 ++++++++++++++++++-- lua/telescope/builtin/init.lua | 14 +++++++ lua/telescope/make_entry.lua | 22 +++++------ lua/telescope/utils.lua | 67 ++++++++++++++++++++++++++++++++-- 4 files changed, 122 insertions(+), 21 deletions(-) diff --git a/doc/telescope.txt b/doc/telescope.txt index b54580f..c053c5f 100644 --- a/doc/telescope.txt +++ b/doc/telescope.txt @@ -955,6 +955,9 @@ builtin.lsp_dynamic_workspace_symbols({opts})*builtin.lsp_dynamic_workspace_symb builtin.lsp_document_diagnostics({opts}) *builtin.lsp_document_diagnostics()* Lists LSP diagnostics for the current buffer + - Fields: + - `All severity flags can be passed as `string` or `number` as per + `:vim.lsp.protocol.DiagnosticSeverity:` - Default keymaps: - ``: show autocompletion menu to prefilter your query with the diagnostic you want to see (i.e. `:warning:`) @@ -964,13 +967,29 @@ builtin.lsp_document_diagnostics({opts}) *builtin.lsp_document_diagnostics()* {opts} (table) options to pass to the picker Fields: ~ - {hide_filename} (boolean) if true, hides the name of the file in the - current picker (default is false) + {hide_filename} (boolean) if true, hides the name of the file + in the current picker (default is + false) + {severity} (string|number) filter diagnostics by severity name + (string) or id (number) + {severity_limit} (string|number) filter for diagnostics equal or more + severe wrt severity name (string) or + id (number) + {severity_bound} (string|number) filter for diagnostics equal or less + severe wrt severity name (string) or + id (number) + {no_sign} (bool) hide LspDiagnosticSigns from Results + (default is false) + {line_width} (number) set length of diagnostic entry text + in Results builtin.lsp_workspace_diagnostics({opts})*builtin.lsp_workspace_diagnostics()* Lists LSP diagnostics for the current workspace if supported, otherwise searches in all open buffers + - Fields: + - `All severity flags can be passed as `string` or `number` as per + `:vim.lsp.protocol.DiagnosticSeverity:` - Default keymaps: - ``: show autocompletion menu to prefilter your query with the diagnostic you want to see (i.e. `:warning:`) @@ -980,8 +999,21 @@ builtin.lsp_workspace_diagnostics({opts})*builtin.lsp_workspace_diagnostics()* {opts} (table) options to pass to the picker Fields: ~ - {hide_filename} (boolean) if true, hides the name of the file in the - current picker (default is false) + {hide_filename} (boolean) if true, hides the name of the file + in the current picker (default is + false) + {severity} (string|number) filter diagnostics by severity name + (string) or id (number) + {severity_limit} (string|number) filter for diagnostics equal or more + severe wrt severity name (string) or + id (number) + {severity_bound} (string|number) filter for diagnostics equal or less + severe wrt severity name (string) or + id (number) + {no_sign} (bool) hide LspDiagnosticSigns from Results + (default is false) + {line_width} (number) set length of diagnostic entry text + in Results diff --git a/lua/telescope/builtin/init.lua b/lua/telescope/builtin/init.lua index ca02a00..cdf6b71 100644 --- a/lua/telescope/builtin/init.lua +++ b/lua/telescope/builtin/init.lua @@ -342,17 +342,31 @@ builtin.lsp_workspace_symbols = require('telescope.builtin.lsp').workspace_symbo builtin.lsp_dynamic_workspace_symbols = require('telescope.builtin.lsp').dynamic_workspace_symbols --- Lists LSP diagnostics for the current buffer +--- - Fields: +--- - `All severity flags can be passed as `string` or `number` as per `:vim.lsp.protocol.DiagnosticSeverity:` --- - Default keymaps: --- - ``: show autocompletion menu to prefilter your query with the diagnostic you want to see (i.e. `:warning:`) ---@param opts table: options to pass to the picker ---@field hide_filename boolean: if true, hides the name of the file in the current picker (default is false) +---@field severity string|number: filter diagnostics by severity name (string) or id (number) +---@field severity_limit string|number: filter for diagnostics equal or more severe wrt severity name (string) or id (number) +---@field severity_bound string|number: filter for diagnostics equal or less severe wrt severity name (string) or id (number) +---@field no_sign bool: hide LspDiagnosticSigns from Results (default is false) +---@field line_width number: set length of diagnostic entry text in Results builtin.lsp_document_diagnostics = require('telescope.builtin.lsp').diagnostics --- Lists LSP diagnostics for the current workspace if supported, otherwise searches in all open buffers +--- - Fields: +--- - `All severity flags can be passed as `string` or `number` as per `:vim.lsp.protocol.DiagnosticSeverity:` --- - Default keymaps: --- - ``: show autocompletion menu to prefilter your query with the diagnostic you want to see (i.e. `:warning:`) ---@param opts table: options to pass to the picker ---@field hide_filename boolean: if true, hides the name of the file in the current picker (default is false) +---@field severity string|number: filter diagnostics by severity name (string) or id (number) +---@field severity_limit string|number: filter for diagnostics equal or more severe wrt severity name (string) or id (number) +---@field severity_bound string|number: filter for diagnostics equal or less severe wrt severity name (string) or id (number) +---@field no_sign bool: hide LspDiagnosticSigns from Results (default is false) +---@field line_width number: set length of diagnostic entry text in Results builtin.lsp_workspace_diagnostics = require('telescope.builtin.lsp').workspace_diagnostics local apply_config = function(mod) diff --git a/lua/telescope/make_entry.lua b/lua/telescope/make_entry.lua index 2339fb6..4fee48d 100644 --- a/lua/telescope/make_entry.lua +++ b/lua/telescope/make_entry.lua @@ -29,13 +29,6 @@ local lsp_type_highlight = { ["Variable"] = "TelescopeResultsVariable", } -local lsp_type_diagnostic = { - [1] = "Error", - [2] = "Warning", - [3] = "Information", - [4] = "Hint" -} - local make_entry = {} do @@ -936,18 +929,21 @@ end function make_entry.gen_from_lsp_diagnostics(opts) opts = opts or {} opts.tail_path = utils.get_default(opts.tail_path, true) + local lsp_type_diagnostic = vim.lsp.protocol.DiagnosticSeverity local signs if not opts.no_sign then signs = {} - for _, v in pairs(lsp_type_diagnostic) do + for severity, _ in pairs(lsp_type_diagnostic) do -- pcall to catch entirely unbound or cleared out sign hl group - local status, sign = pcall( - function() return vim.trim(vim.fn.sign_getdefined("LspDiagnosticsSign" .. v)[1].text) end) - if not status then - sign = v:sub(1,1) + if type(severity) == 'string' then + local status, sign = pcall( + function() return vim.trim(vim.fn.sign_getdefined("LspDiagnosticsSign" .. severity)[1].text) end) + if not status then + sign = severity:sub(1,1) + end + signs[severity] = sign end - signs[v] = sign end end diff --git a/lua/telescope/utils.lua b/lua/telescope/utils.lua index 85e8723..727330d 100644 --- a/lua/telescope/utils.lua +++ b/lua/telescope/utils.lua @@ -82,11 +82,48 @@ utils.quickfix_items_to_entries = function(locations) return results end +local convert_diagnostic_type = function(severity) + -- convert from string to int + if type(severity) == 'string' then + -- make sure that e.g. error is uppercased to Error + return vim.lsp.protocol.DiagnosticSeverity[severity:gsub("^%l", string.upper)] + end + -- otherwise keep original value, incl. nil + return severity +end + +local filter_diag_severity = function(opts, severity) + if opts.severity ~= nil then + return opts.severity == severity + elseif opts.severity_limit ~= nil then + return severity <= opts.severity_limit + elseif opts.severity_bound ~= nil then + return severity >= opts.severity_bound + else + return true + end +end + utils.diagnostics_to_tbl = function(opts) opts = opts or {} local items = {} + local lsp_type_diagnostic = vim.lsp.protocol.DiagnosticSeverity local current_buf = vim.api.nvim_get_current_buf() - local lsp_type_diagnostic = {[1] = "Error", [2] = "Warning", [3] = "Information", [4] = "Hint"} + + opts.severity = convert_diagnostic_type(opts.severity) + opts.severity_limit = convert_diagnostic_type(opts.severity_limit) + opts.severity_bound = convert_diagnostic_type(opts.severity_bound) + + local validate_severity = 0 + for _, v in pairs({opts.severity, opts.severity_limit, opts.severity_bound}) do + if v ~= nil then + validate_severity = validate_severity + 1 + end + if validate_severity > 1 then + print('Please pass valid severity parameters') + return {} + end + end local preprocess_diag = function(diag, bufnr) local filename = vim.api.nvim_buf_get_name(bufnr) @@ -102,11 +139,10 @@ utils.diagnostics_to_tbl = function(opts) col = col + 1, start = start, finish = finish, - -- remove line break to avoid display issues + -- remove line break to avoid display issues text = vim.trim(diag.message:gsub("[\n]", "")), type = lsp_type_diagnostic[diag.severity] or lsp_type_diagnostic[1] } - table.sort(buffer_diag, function(a, b) return a.lnum < b.lnum end) return buffer_diag end @@ -116,10 +152,33 @@ utils.diagnostics_to_tbl = function(opts) for _, diag in pairs(diags) do -- workspace diagnostics may include empty tables for unused bufnr if not vim.tbl_isempty(diag) then - table.insert(items, preprocess_diag(diag, bufnr)) + if filter_diag_severity(opts, diag.severity) then + table.insert(items, preprocess_diag(diag, bufnr)) + end end end end + + -- sort results by bufnr (prioritize cur buf), severity, lnum + table.sort(items, function(a, b) + if a.bufnr == b.bufnr then + if a.type == b.type then + return a.lnum < b.lnum + else + return a.type < b.type + end + else + -- prioritize for current bufnr + if a.bufnr == current_buf then + return true + end + if b.bufnr == current_buf then + return false + end + return a.bufnr < b.bufnr + end + end) + return items end