diff --git a/lua/plugins/lsp/keymaps.lua b/lua/plugins/lsp/keymaps.lua index 4b34031d..0feb82f3 100644 --- a/lua/plugins/lsp/keymaps.lua +++ b/lua/plugins/lsp/keymaps.lua @@ -1,58 +1,65 @@ local M = {} function M.on_attach(client, buffer) - local cap = client.server_capabilities + local self = M.new(client, buffer) - local function map(lhs, rhs, opts) - opts = opts or {} - vim.keymap.set( - opts.mode or "n", - lhs, - type(rhs) == "string" and ("%s"):format(rhs) or rhs, - { silent = true, buffer = buffer, expr = opts.expr, desc = opts.desc } - ) - end + self:map("cd", vim.diagnostic.open_float, { desc = "Line Diagnostics" }) + self:map("cl", "LspInfo", { desc = "Lsp Info" }) + self:map("xd", "Telescope diagnostics", { desc = "Telescope Diagnostics" }) + self:map("gd", "Telescope lsp_definitions", { desc = "Goto Definition" }) + self:map("gr", "Telescope lsp_references", { desc = "References" }) + self:map("gD", "Telescope lsp_declarations", { desc = "Goto Declaration" }) + self:map("gI", "Telescope lsp_implementations", { desc = "Goto Implementation" }) + self:map("gt", "Telescope lsp_type_definitions", { desc = "Goto Type Definition" }) + self:map("K", vim.lsp.buf.hover, { desc = "Hover" }) + self:map("[d", M.diagnostic_goto(true), { desc = "Next Diagnostic" }) + self:map("]d", M.diagnostic_goto(false), { desc = "Prev Diagnostic" }) + self:map("]e", M.diagnostic_goto(true, "ERROR"), { desc = "Next Error" }) + self:map("[e", M.diagnostic_goto(false, "ERROR"), { desc = "Prev Error" }) + self:map("]w", M.diagnostic_goto(true, "WARNING"), { desc = "Next Warning" }) + self:map("[w", M.diagnostic_goto(false, "WARNING"), { desc = "Prev Warning" }) - map("ca", vim.lsp.buf.code_action, { desc = "Code Action", mode = { "n", "v" } }) - map("cd", vim.diagnostic.open_float, { desc = "Line Diagnostics" }) - map("cl", "LspInfo", { desc = "Lsp Info" }) - map("xd", "Telescope diagnostics", { desc = "Telescope Diagnostics" }) - map("gd", "Telescope lsp_definitions", { desc = "Goto Definition" }) - map("gr", "Telescope lsp_references", { desc = "References" }) - map("gR", "Trouble lsp_references", { desc = "Trouble References" }) - map("gD", "Telescope lsp_declarations", { desc = "Goto Declaration" }) - map("gI", "Telescope lsp_implementations", { desc = "Goto Implementation" }) - map("gt", "Telescope lsp_type_definitions", { desc = "Goto Type Definition" }) - map("", vim.lsp.buf.signature_help, { desc = "Signature Help", mode = { "i", "n" } }) - map("K", vim.lsp.buf.hover, { desc = "Hover" }) - map("[d", M.diagnostic_goto(true), { desc = "Next Diagnostic" }) - map("]d", M.diagnostic_goto(false), { desc = "Prev Diagnostic" }) - map("]e", M.diagnostic_goto(true, "ERROR"), { desc = "Next Error" }) - map("[e", M.diagnostic_goto(false, "ERROR"), { desc = "Prev Error" }) - map("]w", M.diagnostic_goto(true, "WARNING"), { desc = "Next Warning" }) - map("[w", M.diagnostic_goto(false, "WARNING"), { desc = "Prev Warning" }) + self:map("", vim.lsp.buf.signature_help, { desc = "Signature Help", mode = { "i", "n" }, has = "signatureHelp" }) + self:map("ca", vim.lsp.buf.code_action, { desc = "Code Action", mode = { "n", "v" }, has = "codeAction" }) - if cap.documentFormatting then - map("cf", require("plugins.lsp.format").format, { desc = "Format Document" }) - end - - if cap.documentRangeFormatting then - map("cf", require("plugins.lsp.format").format, { desc = "Format Range", mode = "v" }) - end - - if cap.renameProvider then - map("cr", function() - if pcall(require, "inc_rename") then - return ":IncRename " .. vim.fn.expand("") - else - vim.lsp.buf.rename() - end - end, { expr = true, desc = "Rename" }) - end + local format = require("plugins.lsp.format").format + self:map("cf", format, { desc = "Format Document", has = "documentFormatting" }) + self:map("cf", format, { desc = "Format Range", mode = "v", has = "documentRangeFormatting" }) + self:map("cr", M.rename, { expr = true, desc = "Rename", has = "rename" }) if client.name == "tsserver" and pcall(require, "typescript") then - map("co", "TypescriptOrganizeImports", { desc = "Organize Imports" }) - map("cR", "TypescriptRenameFile", { desc = "Rename File" }) + self:map("co", "TypescriptOrganizeImports", { desc = "Organize Imports" }) + self:map("cR", "TypescriptRenameFile", { desc = "Rename File" }) + end +end + +function M.new(client, buffer) + return setmetatable({ client = client, buffer = buffer }, { __index = M }) +end + +function M:has(cap) + return self.client.server_capabilities[cap .. "Provider"] +end + +function M:map(lhs, rhs, opts) + opts = opts or {} + if opts.has and not self:has(opts.has) then + return + end + vim.keymap.set( + opts.mode or "n", + lhs, + type(rhs) == "string" and ("%s"):format(rhs) or rhs, + ---@diagnostic disable-next-line: no-unknown + { silent = true, buffer = self.buffer, expr = opts.expr, desc = opts.desc } + ) +end + +function M.rename() + if pcall(require, "inc_rename") then + return ":IncRename " .. vim.fn.expand("") + else + vim.lsp.buf.rename() end end