From b0b23d4de6a3046387757ed921a3b45eeef88359 Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Wed, 26 Oct 2022 19:31:00 -0500 Subject: feat(lsp): improve handlers, previews and floats --- nvim/.config/nvim/lua/tobyvin/keymaps.lua | 3 + nvim/.config/nvim/lua/tobyvin/lsp.lua | 3 +- nvim/.config/nvim/lua/tobyvin/lsp/handlers.lua | 77 ++++++++-------------- .../nvim/lua/tobyvin/plugins/rust-tools.lua | 54 +++++++++++++-- 4 files changed, 81 insertions(+), 56 deletions(-) (limited to 'nvim/.config') diff --git a/nvim/.config/nvim/lua/tobyvin/keymaps.lua b/nvim/.config/nvim/lua/tobyvin/keymaps.lua index 0f14731..8e3ff40 100644 --- a/nvim/.config/nvim/lua/tobyvin/keymaps.lua +++ b/nvim/.config/nvim/lua/tobyvin/keymaps.lua @@ -16,11 +16,14 @@ M.setup = function() vim.keymap.set("n", "gn", "bnext", { desc = "bnext" }) vim.keymap.set("n", "gp", "bprev", { desc = "bprev" }) vim.keymap.set("n", "gb", utils.buffer.bselect, { desc = "bselect" }) + vim.keymap.set("n", "gk", utils.documentation.open, { desc = "Documentation" }) + vim.keymap.set("n", "q", "qall", { desc = "quit" }) vim.keymap.set("n", "c", utils.buffer.bdelete, { desc = "bdelete" }) vim.keymap.set("n", "x", "close", { desc = "close" }) vim.keymap.set("n", "z", "tabclose", { desc = "tabclose" }) vim.keymap.set("n", "w", "write", { desc = "write" }) + vim.keymap.set("n", "", "zz", { desc = "Up half page and center" }) vim.keymap.set("n", "", "zz", { desc = "Down half page and center" }) vim.keymap.set("n", "", "m +1", { desc = "Move line down" }) diff --git a/nvim/.config/nvim/lua/tobyvin/lsp.lua b/nvim/.config/nvim/lua/tobyvin/lsp.lua index 8aadee6..2dd1678 100644 --- a/nvim/.config/nvim/lua/tobyvin/lsp.lua +++ b/nvim/.config/nvim/lua/tobyvin/lsp.lua @@ -12,7 +12,7 @@ lsp.setup = function() lsp.formatting.setup() vim.api.nvim_create_autocmd("LspAttach", { - group = vim.api.nvim_create_augroup("tobyvin_lsp", { clear = true }), + group = vim.api.nvim_create_augroup("tobyvin_lsp", { clear = true }), desc = "lsp", callback = function(args) local bufnr = args.buf @@ -20,7 +20,6 @@ lsp.setup = function() utils.keymap.group("n", "l", { desc = "LSP", buffer = bufnr }) vim.keymap.set("n", "L", "LspInfo", { desc = "LSP info" }) - vim.keymap.set("n", "k", utils.documentation.open, { desc = "Documentation", buffer = bufnr }) vim.api.nvim_exec_autocmds("User", { pattern = "LspAttach", data = { client_id = client.id } }) end, }) diff --git a/nvim/.config/nvim/lua/tobyvin/lsp/handlers.lua b/nvim/.config/nvim/lua/tobyvin/lsp/handlers.lua index 66dcc7a..761b1e6 100644 --- a/nvim/.config/nvim/lua/tobyvin/lsp/handlers.lua +++ b/nvim/.config/nvim/lua/tobyvin/lsp/handlers.lua @@ -1,59 +1,39 @@ ----@diagnostic disable: missing-parameter +local utils = require("tobyvin.utils") local M = {} -M.goto_handler = function(method) - local callback = vim.lsp.handlers[method] +M.wrap_handler = function(method, handler) + handler = vim.F.if_nil(handler, vim.lsp.handlers[method]) return function(err, result, ctx, config) if result == nil or vim.tbl_isempty(result) then vim.notify("No location found", vim.log.levels.INFO, { title = "[LSP] " .. ctx.method }) return nil end - -- workaround for LSPs returning two results on (2) anonymous function (1) variable assignments, e.g. this func - if ctx.method == "textDocument/definition" and vim.tbl_islist(result) and #result > 1 then - for _, k in pairs(vim.tbl_keys(result[1])) do - if - (k == "range" or k == "targetRange") - and result[1][k].start ~= nil - and result[1][k].start.line == result[2][k].start.line - then - result[2][k].start = result[1][k].start - table.remove(result, 1) - break - end - end - end - - if vim.tbl_islist(result) and #result == 1 then + if vim.tbl_islist(result) then result = result[1] end - callback(err, result, ctx, config) + handler(err, result, ctx, config) end end -M.preview_handler = function(method) - local preview_callback = function(_, result, _, _) - if vim.tbl_islist(result) then - vim.lsp.util.preview_location(result[1]) - else - vim.lsp.util.preview_location(result) - end - end +M.with_float = function(name) + local method = string.format("textDocument/%s", name) + local handler = M.wrap_handler(method, function(_, result) + vim.lsp.util.preview_location(result, { + focus_id = "preview_" .. name, + close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" }, + border = "single", + scope = "cursor", + }) + end) return function() + ---@diagnostic disable-next-line: missing-parameter local params = vim.lsp.util.make_position_params() - return vim.lsp.buf_request(0, method, params, M.goto_handler(preview_callback)) + return vim.lsp.buf_request(0, method, params, handler) end end -M.preview = { - definition = M.preview_handler("textDocument/definition"), - declaration = M.preview_handler("textDocument/declaration"), - type_definition = M.preview_handler("textDocument/type_definition"), - implementation = M.preview_handler("textDocument/implementation"), - references = M.preview_handler("textDocument/references"), -} - M.setup = function() vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.handlers["textDocument/publishDiagnostics"], { @@ -81,12 +61,12 @@ M.setup = function() local bufnr = args.buf local client = vim.lsp.get_client_by_id(args.data.client_id) - if client.name ~= "rust-analyzer" then - vim.lsp.handlers["textDocument/definition"] = M.goto_handler("textDocument/definition") - vim.lsp.handlers["textDocument/declaration"] = M.goto_handler("textDocument/declaration") - vim.lsp.handlers["textDocument/type_definition"] = M.goto_handler("textDocument/type_definition") - vim.lsp.handlers["textDocument/implementation"] = M.goto_handler("textDocument/implementation") - vim.lsp.handlers["textDocument/references"] = M.goto_handler("textDocument/references") + if client.name ~= "rust_analyzer" then + vim.lsp.handlers["textDocument/definition"] = M.wrap_handler("textDocument/definition") + vim.lsp.handlers["textDocument/declaration"] = M.wrap_handler("textDocument/declaration") + vim.lsp.handlers["textDocument/type_definition"] = M.wrap_handler("textDocument/type_definition") + vim.lsp.handlers["textDocument/implementation"] = M.wrap_handler("textDocument/implementation") + vim.lsp.handlers["textDocument/references"] = M.wrap_handler("textDocument/references") end if client.server_capabilities["definitionProvider"] then @@ -102,11 +82,12 @@ M.setup = function() vim.keymap.set("n", "gi", vim.lsp.buf.implementation, { desc = "Implementation", buffer = bufnr }) vim.keymap.set("n", "gr", vim.lsp.buf.references, { desc = "References", buffer = bufnr }) - vim.keymap.set("n", "g", M.preview.definition, { desc = "Definition", buffer = bufnr }) - vim.keymap.set("n", "g", M.preview.declaration, { desc = "Preview Declaration", buffer = bufnr }) - vim.keymap.set("n", "g", M.preview.type_definition, { desc = "Preview Type", buffer = bufnr }) - vim.keymap.set("n", "g", M.preview.implementation, { desc = "Preview Implementation", buffer = bufnr }) - vim.keymap.set("n", "g", M.preview.references, { desc = "Preview References", buffer = bufnr }) + utils.keymap.group("n", "gf", { desc = "Float" }) + vim.keymap.set("n", "gfd", M.with_float("definition"), { desc = "Definition", buffer = bufnr }) + vim.keymap.set("n", "gfD", M.with_float("declaration"), { desc = "Declaration", buffer = bufnr }) + vim.keymap.set("n", "gft", M.with_float("type_definition"), { desc = "Type", buffer = bufnr }) + vim.keymap.set("n", "gfi", M.with_float("implementation"), { desc = "Implementation", buffer = bufnr }) + vim.keymap.set("n", "gfr", M.with_float("references"), { desc = "References", buffer = bufnr }) vim.keymap.set("n", "la", vim.lsp.buf.code_action, { desc = "Code Action", buffer = bufnr }) vim.keymap.set("n", "ll", vim.lsp.codelens.run, { desc = "Codelens", buffer = bufnr }) diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua b/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua index 7be3a4a..6f4d57d 100644 --- a/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua +++ b/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua @@ -3,6 +3,7 @@ local lsp = require("tobyvin.lsp") local M = { codelldb = "/usr/lib/codelldb/adapter/codelldb", liblldb = "/usr/lib/codelldb/lldb/lib/liblldb.so", + popup_id = "", } M.setup = function() @@ -12,13 +13,53 @@ M.setup = function() return end + local function parse_lines(t) + local ret = {} + + local name = t.name + local text = "// Recursive expansion of the " .. name .. " macro" + table.insert(ret, "// " .. string.rep("=", string.len(text) - 3)) + table.insert(ret, text) + table.insert(ret, "// " .. string.rep("=", string.len(text) - 3)) + table.insert(ret, "") + + local expansion = t.expansion + for string in string.gmatch(expansion, "([^\n]+)") do + table.insert(ret, string) + end + + return ret + end + + local handler = function(_, result) + if result == nil then + vim.api.nvim_out_write("No macro under cursor!\n") + return + end + + local contents = parse_lines(result) + local opts = { + focus_id = "expand_macro", + close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" }, + border = "single", + scope = "cursor", + } + vim.lsp.util.open_floating_preview(contents, "rust", opts) + end + + require("rust-tools.expand_macro").expand_macro = function() + ---@diagnostic disable-next-line: missing-parameter + local params = vim.lsp.util.make_position_params() + rust_tools.utils.request(0, "rust-analyzer/expandMacro", params, handler) + end + vim.api.nvim_create_autocmd("LspAttach", { - group = vim.api.nvim_create_augroup("tobyvin_rust-tools", { clear = true }), + group = vim.api.nvim_create_augroup("tobyvin_rust-tools", { clear = true }), desc = "setup rust-tools", callback = function(args) local bufnr = args.buf local client = vim.lsp.get_client_by_id(args.data.client_id) - if client.name ~= "rust-analyzer" then + if client.name ~= "rust_analyzer" then return end @@ -26,11 +67,12 @@ M.setup = function() local debuggables = rust_tools.debuggables.debuggables local open_cargo_toml = rust_tools.open_cargo_toml.open_cargo_toml local external_docs = rust_tools.external_docs.open_external_docs + local expand_macro = rust_tools.expand_macro.expand_macro - utils.keymap.group("n", "r", { desc = "Run" }) - vim.keymap.set("n", "rr", runnables, { desc = "Runnables", buffer = bufnr }) - vim.keymap.set("n", "rd", debuggables, { desc = "Debug", buffer = bufnr }) - vim.keymap.set("n", "ro", open_cargo_toml, { desc = "Open Cargo.toml", buffer = bufnr }) + vim.keymap.set("n", "dd", debuggables, { desc = "Debug", buffer = bufnr }) + vim.keymap.set("n", "lr", runnables, { desc = "Run", buffer = bufnr }) + vim.keymap.set("n", "lo", open_cargo_toml, { desc = "Open Cargo.toml", buffer = bufnr }) + vim.keymap.set("n", "le", expand_macro, { desc = "Expand macro", buffer = bufnr }) utils.documentation.register("rust", external_docs) end, -- cgit v1.2.3-70-g09d2