diff --git a/README.md b/README.md index ab080f2..f9050dd 100644 --- a/README.md +++ b/README.md @@ -377,6 +377,7 @@ require'navigator'.setup({ | n | gG | show diagnostic for all buffers | | n | ]d | next diagnostic | | n | [d | previous diagnostic | +| n | \ dt | diagnostic toggle(enable/disable) | | n | ]r | next treesitter reference/usage | | n | [r | previous treesitter reference/usage | | n | \ wa | add workspace folder | diff --git a/lua/navigator.lua b/lua/navigator.lua index 60bbc63..8c554bf 100644 --- a/lua/navigator.lua +++ b/lua/navigator.lua @@ -159,7 +159,7 @@ end M.setup = function(cfg) extend_config(cfg) - vim.cmd([[autocmd FileType * lua require'navigator.lspclient.clients'.setup()]]) -- BufWinEnter BufNewFile,BufRead ? + vim.cmd([[autocmd FileType,BufEnter * lua require'navigator.lspclient.clients'.setup()]]) -- BufWinEnter BufNewFile,BufRead ? -- local log = require"navigator.util".log -- log(debug.traceback()) -- log(cfg, _NgConfigValues) diff --git a/lua/navigator/codeAction.lua b/lua/navigator/codeAction.lua index 14af099..146c04c 100644 --- a/lua/navigator/codeAction.lua +++ b/lua/navigator/codeAction.lua @@ -12,75 +12,76 @@ local sign_name = "NavigatorLightBulb" --- `codeAction/resolve` -- from neovim buf.lua, change vim.ui.select to gui local function on_code_action_results(results, ctx) + local trace = log local action_tuples = {} - for client_id, result in pairs(results) do - for _, action in pairs(result.result or {}) do - table.insert(action_tuples, {client_id, action}) - end - end - if #action_tuples == 0 then - vim.notify('No code actions available', vim.log.levels.INFO) - return - end - trace(action_tuples, ctx) local data = {"  Auto Fix Apply Exit"} - for i, act in pairs(action_tuples) do - local title = 'apply action' - local action = act[2] - trace(action) - if action.edit and action.edit.title then - local edit = action.edit - title = edit.title:gsub("\n", " ↳ ") - elseif action.title then - title = action.title:gsub("\n", " ↳ ") - elseif action.command and action.command.title then - title = action.command.title:gsub("\n", " ↳ ") - end - local edit = action.edit or {} - -- trace(edit.documentChanges) - if edit.documentChanges or edit.changes then - local changes = edit.documentChanges or edit.changes - -- trace(action.edit.documentChanges) - for _, change in pairs(changes or {}) do - -- trace(change) - if change.edits then - title = title .. " [newText:]" - for _, ed in pairs(change.edits) do - -- trace(ed) - if ed.newText and ed.newText ~= "" then - local newText = ed.newText:gsub("\n\t", " ↳ ") - newText = newText:gsub("\n", "↳") - title = title .. " (" .. newText - if ed.range then - title = title .. " line: " .. tostring(ed.range.start.line) .. ")" - else - title = title .. ")" + for client_id, result in pairs(results) do + for i, action in pairs(result.result or {}) do + local title = 'apply action' + trace(action) + if action.edit and action.edit.title then + local edit = action.edit + title = edit.title:gsub("\r\n", " ↳ ") + title = title:gsub("\n", " ↳ ") + elseif action.title then + title = action.title:gsub("\r\n", " ↳ ") + title = title:gsub("\n", " ↳ ") + elseif action.command and action.command.title then + title = action.command.title:gsub("\n", " ↳ ") + title = title:gsub("\n", " ↳ ") + end + + local edit = action.edit or {} + -- trace(edit.documentChanges) + if edit.documentChanges or edit.changes then + local changes = edit.documentChanges or edit.changes + -- trace(action.edit.documentChanges) + for _, change in pairs(changes or {}) do + -- trace(change) + if change.edits then + title = title .. " [newText:]" + for _, ed in pairs(change.edits) do + -- trace(ed) + if ed.newText and ed.newText ~= "" then + local newText = ed.newText:gsub("\n\t", " ↳ ") + newText = newText:gsub("\n", "↳") + title = title .. " (" .. newText + if ed.range then + title = title .. " line: " .. tostring(ed.range.start.line) .. ")" + else + title = title .. ")" + end end end + elseif change.newText and change.newText ~= "" then + local newText = change.newText:gsub("\"\n\t\"", " ↳ ") + newText = newText:gsub("\n", "↳") + title = title .. " (newText: " .. newText + if change.range then + title = title .. " line: " .. tostring(change.range.start.line) .. ")" + else + title = title .. ")" + end end - elseif change.newText and change.newText ~= "" then - local newText = change.newText:gsub("\"\n\t\"", " ↳ ") - newText = newText:gsub("\n", "↳") - title = title .. " (newText: " .. newText - if change.range then - title = title .. " line: " .. tostring(change.range.start.line) .. ")" - else - title = title .. ")" - end - end + end end - end - title = title:gsub("\n", "\\n") - title = string.format("[%d] %s", i, title) - table.insert(data, title) - action_tuples[i].display_title = title + title = string.format("[%d] %s", i, title) + table.insert(data, title) + table.insert(action_tuples, {client_id, action, title, i}) + end end log(action_tuples) + log(data) + + if #action_tuples == 0 then + vim.notify('No code actions available', vim.log.levels.INFO) + return + end local width = 42 for _, str in ipairs(data) do if #str > width then @@ -102,17 +103,12 @@ local function on_code_action_results(results, ctx) on_confirm = function(item) trace(item) local action_chosen = nil - for key, value in pairs(action_tuples) do - if value.display_title == item then + for _, value in pairs(action_tuples) do + if value[3] == item then action_chosen = value + return require('navigator.lspwrapper').on_user_choice(action_chosen, ctx) end end - if action_chosen == nil then - log("no match for ", item, action_tuples) - return - end - require('navigator.lspwrapper').on_user_choice(action_chosen, ctx) - end, on_move = function(pos) trace(pos) @@ -126,66 +122,12 @@ local function on_code_action_results(results, ctx) end local diagnostic = vim.diagnostic or vim.lsp.diagnostic -code_action.code_action_handler = util.mk_handler(function(err, actions, ctx, cfg) - if actions == nil or vim.tbl_isempty(actions) or err then - log("No code actions available") +code_action.code_action_handler = util.mk_handler(function(err, results, ctx, cfg) + if err ~= nil then + log("code action err", err, results, ctx, cfg) return end - - log(actions, ctx) - local data = {"  Auto Fix Apply Exit"} - for i, action in ipairs(actions) do - local title = action.title:gsub("\r\n", "\\r\\n") - title = title:gsub("\n", "\\n") - title = string.format("[%d] %s", i, title) - table.insert(data, title) - actions[i].display_title = title - end - local width = 42 - for _, str in ipairs(data) do - if #str > width then - width = #str - end - end - - local divider = string.rep('─', width + 2) - - table.insert(data, 2, divider) - local apply = require('navigator.lspwrapper').apply_action - local function apply_action(action) - local action_chosen = nil - for key, value in pairs(actions) do - if value.display_title == action then - action_chosen = value - end - end - - if action_chosen == nil then - log("no match for ", action, actions) - return - end - apply(action_chosen) - end - - local listview = gui.new_list_view { - items = data, - width = width + 4, - loc = "top_center", - relative = "cursor", - rawdata = true, - data = data, - on_confirm = function(pos) - trace(pos) - apply_action(pos) - end, - on_move = function(pos) - trace(pos) - return pos - end - } - - log("new buffer", listview.bufnr) - vim.api.nvim_buf_add_highlight(listview.bufnr, -1, 'Title', 0, 0, -1) + on_code_action_results(results, ctx) end) -- https://github.com/glepnir/lspsaga.nvim/blob/main/lua/lspsaga/codeaction.lua @@ -219,8 +161,10 @@ end local function _update_sign(line) if vim.tbl_isempty(vim.fn.sign_getdefined(sign_name)) then - vim.fn.sign_define(sign_name, - {text = config.icons.code_action_icon, texthl = "LspDiagnosticsSignHint"}) + vim.fn.sign_define(sign_name, { + text = config.icons.code_action_icon, + texthl = "LspDiagnosticsSignHint" + }) end local winid = get_current_winid() if code_action[winid] == nil then diff --git a/lua/navigator/definition.lua b/lua/navigator/definition.lua index 1e175ae..666e321 100644 --- a/lua/navigator/definition.lua +++ b/lua/navigator/definition.lua @@ -104,9 +104,8 @@ local function def_preview(timeout_ms) local width = 40 for key, value in pairs(definition) do -- log(key, value, width) - width = math.max(width, #value) - width = math.min(90, width) - + width = math.max(width, #value + 4) + width = math.min(120, width) end definition = vim.list_extend({"  [" .. get_symbol() .. "] Definition: "}, definition) local filetype = vim.api.nvim_buf_get_option(bufnr, "filetype") @@ -116,7 +115,7 @@ local function def_preview(timeout_ms) relative = "cursor", style = "minimal", ft = filetype, - width = width, + rect = {width = width, height = #definition + 2}, data = definition, enter = true, border = _NgConfigValues.border or "shadow" diff --git a/lua/navigator/diagnostics.lua b/lua/navigator/diagnostics.lua index 430af0b..a260da1 100644 --- a/lua/navigator/diagnostics.lua +++ b/lua/navigator/diagnostics.lua @@ -287,6 +287,15 @@ M.hide_diagnostic = function() end end +M.toggle_diagnostics = function() + if M.diagnostic_enabled then + M.diagnostic_enabled = false + return vim.diagnostic.disable() + end + vim.diagnostic.enable() + M.diagnostic_enabled = true +end + M.show_buf_diagnostics = function() if diagnostic_list[vim.bo.filetype] ~= nil then -- log(diagnostic_list[vim.bo.filetype]) diff --git a/lua/navigator/lspclient/clients.lua b/lua/navigator/lspclient/clients.lua index 9b4a30c..8c8cda6 100644 --- a/lua/navigator/lspclient/clients.lua +++ b/lua/navigator/lspclient/clients.lua @@ -546,6 +546,10 @@ local function setup(user_opts) log("navigator user setup", user_opts) end trace(debug.traceback()) + if #vim.lsp.buf_get_clients() > 0 and user_opts == nil then + log("already setup") + return + end user_opts = user_opts or config -- incase setup was triggered from autocmd if ft == nil then diff --git a/lua/navigator/lspclient/mapping.lua b/lua/navigator/lspclient/mapping.lua index 8b4c0a2..241665d 100644 --- a/lua/navigator/lspclient/mapping.lua +++ b/lua/navigator/lspclient/mapping.lua @@ -33,6 +33,7 @@ local key_maps = { {key = "D", func = "type_definition()"}, {key = "gL", func = "require('navigator.diagnostics').show_diagnostics()"}, {key = "gG", func = "require('navigator.diagnostics').show_buf_diagnostics()"}, + {key = "dt", func = "require('navigator.diagnostics').toggle_diagnostics()"}, {key = "]d", func = "diagnostic.goto_next({ border = 'rounded', max_width = 80})"}, {key = "[d", func = "diagnostic.goto_prev({ border = 'rounded', max_width = 80})"}, {key = "]r", func = "require('navigator.treesitter').goto_next_usage()"}, diff --git a/lua/navigator/lspwrapper.lua b/lua/navigator/lspwrapper.lua index 7d9b9ef..fc72486 100644 --- a/lua/navigator/lspwrapper.lua +++ b/lua/navigator/lspwrapper.lua @@ -409,25 +409,23 @@ function M.locations_to_items(locations, max_items) return items, width + 24, second_part -- TODO handle long line? end -function M.apply_action(action_chosen) - assert(action_chosen ~= nil, "action must not be nil") - local bufnr = api.nvim_get_current_buf() - local switch = string.format("silent b %d", bufnr) - if action_chosen.edit or type(action_chosen.command) == "table" then - if action_chosen.edit then - vim.lsp.util.apply_workspace_edit(action_chosen.edit) - end - if type(action_chosen.command) == "table" then - -- switch buff - vim.cmd(switch) - vim.lsp.buf.execute_command(action_chosen.command) +function M.apply_action(action, ctx, client) + assert(action ~= nil, "action must not be nil") + if action.edit then + vim.lsp.util.apply_workspace_edit(action.edit) + end + if action.command then + local command = type(action.command) == 'table' and action.command or action + local fn = client.commands[command.command] or (vim.lsp.commands and vim.lsp.commands[command.command]) + if fn then + local enriched_ctx = vim.deepcopy(ctx) + enriched_ctx.client_id = client.id + fn(command, enriched_ctx) + else + M.execute_command(command) end - else - vim.cmd(switch) - vim.lsp.buf.execute_command(action_chosen) end - - log(action_chosen) + log(action) end