]> git.rmz.io Git - dotfiles.git/commitdiff
lazyvim: absorb lspconfig
authorSamir Benmendil <me@rmz.io>
Sun, 9 Feb 2025 18:09:24 +0000 (18:09 +0000)
committerSamir Benmendil <me@rmz.io>
Sun, 2 Mar 2025 16:05:27 +0000 (16:05 +0000)
nvim/lua/plugins/lsp.lua [deleted file]
nvim/lua/plugins/lsp/init.lua [new file with mode: 0644]
nvim/lua/plugins/lsp/keymaps.lua [new file with mode: 0644]
nvim/lua/plugins/picker.lua

diff --git a/nvim/lua/plugins/lsp.lua b/nvim/lua/plugins/lsp.lua
deleted file mode 100644 (file)
index d020443..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-return {
-  -- lspconfig
-  {
-    "neovim/nvim-lspconfig",
-    ---@class PluginLspOpts
-    opts = function()
-      local keys = require("lazyvim.plugins.lsp.keymaps").get()
-      -- TODO: setup a new mapping for this
-      -- { "gr", "<cmd>Telescope lsp_references<cr>", desc = "References" },
-      keys[#keys+1] = { "gr", false }
-
-      return {
-        diagnostics = {
-          underline = true,
-          update_in_insert = false,
-          virtual_text = {
-            spacing = 4,
-            source = "if_mani",
-            prefix = "●",
-          },
-          severity_sort = true,
-          signs = {
-            text = {
-              [vim.diagnostic.severity.ERROR] = " ",
-              [vim.diagnostic.severity.WARN]  = " ",
-              [vim.diagnostic.severity.HINT]  = " ",
-              [vim.diagnostic.severity.INFO]  = " ",
-            },
-          },
-        },
-        inlay_hints = { enabled = false, },
-        codelens = { enabled = false, },
-        document_highlight = { enabled = true, },
-        capabilities = {
-          workspace = {
-            fileOperations = {
-              didRename = true,
-              willRename = true,
-            },
-          },
-        },
-        format = {
-          formatting_options = nil,
-          timeout_ms = nil,
-        },
-        -- Automatically format on save
-        -- autoformat = false,
-        -- LSP Server Settings
-        ---@type lspconfig.options
-        servers = {
-          lua_ls = {
-            settings = {
-              Lua = {
-                workspace = { checkThirdParty = false, },
-                codeLens = { enable = true, },
-                completion = { callSnippet = "Replace", },
-                doc = { privateName = { "^_" }, },
-                hint = {
-                  enable = true,
-                  setType = false,
-                  paramType = true,
-                  paramName = "Disable",
-                  semicolon = "Disable",
-                  arrayIndex = "Disable",
-                },
-                diagnostics = {
-                  disable = { "missing-fields", },
-                },
-              },
-            },
-          },
-          -- Add clangd extensions
-          -- https://github.com/p00f/clangd_extensions.nvim
-        },
-        -- you can do any additional lsp server setup here
-        -- return true if you don't want this server to be setup with lspconfig
-        ---@type table<string, fun(server:string, opts:_.lspconfig.options):boolean?>
-        setup = {
-          -- example to setup with typescript.nvim
-          -- tsserver = function(_, opts)
-          --   require("typescript").setup({ server = opts })
-          --   return true
-          -- end,
-          -- Specify * to use this function as a fallback for any server
-          -- ["*"] = function(server, opts) end,
-        },
-      }
-    end,
-  },
-
-  -- cmdline tools and lsp servers
-  {
-
-    "williamboman/mason.nvim",
-    cmd = "Mason",
-    keys = { { "<leader>cm", "<cmd>Mason<cr>", desc = "Mason" } },
-    opts = {
-      ensure_installed = {
-        "stylua",
-        "shfmt",
-        -- "flake8",
-      },
-    },
-    ---@param opts MasonSettings | {ensure_installed: string[]}
-    config = function(_, opts)
-      require("mason").setup(opts)
-      local mr = require("mason-registry")
-      local function ensure_installed()
-        for _, tool in ipairs(opts.ensure_installed) do
-          local p = mr.get_package(tool)
-          if not p:is_installed() then
-            p:install()
-          end
-        end
-      end
-      if mr.refresh then
-        mr.refresh(ensure_installed)
-      else
-        ensure_installed()
-      end
-    end,
-  },
-}
diff --git a/nvim/lua/plugins/lsp/init.lua b/nvim/lua/plugins/lsp/init.lua
new file mode 100644 (file)
index 0000000..351f060
--- /dev/null
@@ -0,0 +1,176 @@
+return {
+  { "neovim/nvim-lspconfig",
+    event = "LazyFile",
+    dependencies = {
+      "mason.nvim",
+      { "williamboman/mason-lspconfig.nvim", config = function() end }, -- don't configure yet
+    },
+    ---@class PluginLspOpts
+    opts = {
+      ---@type vim.diagnostic.Opts
+      diagnostics = {
+        underline = true,
+        update_in_insert = false,
+        virtual_text = {
+          spacing = 4,
+          source = "if_many",
+          prefix = "●",
+        },
+        severity_sort = true,
+        signs = {
+          text = {
+            [vim.diagnostic.severity.ERROR] = " ",
+            [vim.diagnostic.severity.WARN]  = " ",
+            [vim.diagnostic.severity.HINT]  = " ",
+            [vim.diagnostic.severity.INFO]  = " ",
+          },
+        },
+      },
+      inlay_hints = { enabled = false, },
+      codelens = { enabled = false, },
+      document_highlight = { enabled = true, },
+      capabilities = {
+        workspace = {
+          fileOperations = {
+            didRename = true,
+            willRename = true,
+          },
+        },
+      },
+      format = {
+        formatting_options = nil,
+        timeout_ms = nil,
+      },
+      -- LSP Server Settings
+      ---@type lspconfig.options
+      servers = {
+        lua_ls = {
+          settings = {
+            Lua = {
+              workspace = { checkThirdParty = false, },
+              codeLens = { enable = true, },
+              completion = { callSnippet = "Replace", },
+              doc = { privateName = { "^_" }, },
+              hint = {
+                enable = true,
+                setType = false,
+                paramType = true,
+                paramName = "Disable",
+                semicolon = "Disable",
+                arrayIndex = "Disable",
+              },
+              diagnostics = {
+                disable = { "missing-fields", },
+              },
+            },
+          },
+        },
+        -- TODO: Add clangd extensions
+        -- https://github.com/p00f/clangd_extensions.nvim
+      },
+      -- you can do any additional lsp server setup here
+      -- return true if you don't want this server to be setup with lspconfig
+      ---@type table<string, fun(server:string, opts:_.lspconfig.options):boolean?>
+      setup = {
+        -- example to setup with typescript.nvim
+        -- tsserver = function(_, opts)
+        --   require("typescript").setup({ server = opts })
+        --   return true
+        -- end,
+        -- Specify * to use this function as a fallback for any server
+        -- ["*"] = function(server, opts) end,
+      },
+    },
+    ---@param opts PluginLspOpts
+    config = function(_, opts)
+      local lspconfig = require('lspconfig')
+      for server, config in pairs(opts.servers) do
+        local capabilities = vim.tbl_deep_extend("force",
+          vim.lsp.protocol.make_client_capabilities() or {},
+          require('blink.cmp').get_lsp_capabilities() or {},
+          config.capabilities or {}
+        )
+        config.capabilities = capabilities
+        lspconfig[server].setup(config)
+      end
+
+      -- setup keymaps
+      LazyVim.lsp.on_attach(function(client, buffer)
+        require("plugins.lsp.keymaps").on_attach(client, buffer)
+      end)
+
+      LazyVim.lsp.setup()
+      LazyVim.lsp.on_dynamic_capability(require("plugins.lsp.keymaps").on_attach)
+      -- TODO: should vim.diagnostics be condigured directly?
+      vim.diagnostic.config(vim.deepcopy(opts.diagnostics))
+
+      -- get all the servers that are available through mason-lspconfig
+      local have_mason, mlsp = pcall(require, "mason-lspconfig")
+      local all_mslp_servers = {}
+      if have_mason then
+        all_mslp_servers = vim.tbl_keys(require("mason-lspconfig.mappings.server").lspconfig_to_package)
+      end
+
+      local ensure_installed = {} ---@type string[]
+      for server, server_opts in pairs(opts.servers) do
+        if server_opts then
+          server_opts = server_opts == true and {} or server_opts
+          if server_opts.enabled ~= false then
+            -- run manual setup if mason=false or if this is a server that cannot be installed with mason-lspconfig
+            if server_opts.mason == false or not vim.tbl_contains(all_mslp_servers, server) then
+              require("lspconfig")[server].setup(server_opts)
+            else
+              ensure_installed[#ensure_installed + 1] = server
+            end
+          end
+        end
+      end
+
+      if have_mason then
+        mlsp.setup({
+          ensure_installed = vim.tbl_deep_extend(
+            "force",
+            ensure_installed,
+            LazyVim.opts("mason-lspconfig.nvim").ensure_installed or {}
+          ),
+          handlers = { setup },
+        })
+      end
+    end
+  },
+  { "williamboman/mason.nvim",
+    cmd = "Mason",
+    keys = { { "<leader>cm", "<cmd>Mason<cr>", desc = "Mason" } },
+    build = ":MasonUpdate",
+    opts_extend = { "ensure_installed" },
+    opts = {
+      ensure_installed = {
+        "stylua",
+        "shfmt",
+      },
+    },
+    ---@param opts MasonSettings | {ensure_installed: string[]}
+    config = function(_, opts)
+      require("mason").setup(opts)
+      local mr = require("mason-registry")
+      mr:on("package:install:success", function()
+        vim.defer_fn(function()
+          -- trigger FileType event to possibly load this newly installed LSP server
+          require("lazy.core.handler.event").trigger({
+            event = "FileType",
+            buf = vim.api.nvim_get_current_buf(),
+          })
+        end, 100)
+      end)
+
+      mr.refresh(function()
+        for _, tool in ipairs(opts.ensure_installed) do
+          local p = mr.get_package(tool)
+          if not p:is_installed() then
+            p:install()
+          end
+        end
+      end)
+    end,
+  },
+}
diff --git a/nvim/lua/plugins/lsp/keymaps.lua b/nvim/lua/plugins/lsp/keymaps.lua
new file mode 100644 (file)
index 0000000..72cfa51
--- /dev/null
@@ -0,0 +1,99 @@
+local M = {}
+
+---@type LazyKeysLspSpec[]|nil
+M._keys = nil
+
+---@alias LazyKeysLspSpec LazyKeysSpec|{has?:string|string[], cond?:fun():boolean}
+---@alias LazyKeysLsp LazyKeys|{has?:string|string[], cond?:fun():boolean}
+
+---@return LazyKeysLspSpec[]
+function M.get()
+  if M._keys then
+    return M._keys
+  end
+    -- stylua: ignore
+    M._keys =  {
+      { "<leader>cl", "<cmd>LspInfo<cr>", desc = "Lsp Info" },
+      { "gd", vim.lsp.buf.definition, desc = "Goto Definition", has = "definition" },
+      -- { "gr", vim.lsp.buf.references, desc = "References", nowait = true },
+      { "gI", vim.lsp.buf.implementation, desc = "Goto Implementation" },
+      { "gy", vim.lsp.buf.type_definition, desc = "Goto T[y]pe Definition" },
+      { "gD", vim.lsp.buf.declaration, desc = "Goto Declaration" },
+      { "K", function() return vim.lsp.buf.hover() end, desc = "Hover" },
+      { "gK", function() return vim.lsp.buf.signature_help() end, desc = "Signature Help", has = "signatureHelp" },
+      { "<c-k>", function() return vim.lsp.buf.signature_help() end, mode = "i", desc = "Signature Help", has = "signatureHelp" },
+      { "<leader>ca", vim.lsp.buf.code_action, desc = "Code Action", mode = { "n", "v" }, has = "codeAction" },
+      { "<leader>cc", vim.lsp.codelens.run, desc = "Run Codelens", mode = { "n", "v" }, has = "codeLens" },
+      { "<leader>cC", vim.lsp.codelens.refresh, desc = "Refresh & Display Codelens", mode = { "n" }, has = "codeLens" },
+      { "<leader>cR", function() Snacks.rename.rename_file() end, desc = "Rename File", mode ={"n"}, has = { "workspace/didRenameFiles", "workspace/willRenameFiles" } },
+      { "<leader>cr", vim.lsp.buf.rename, desc = "Rename", has = "rename" },
+      { "<leader>cA", LazyVim.lsp.action.source, desc = "Source Action", has = "codeAction" },
+      { "]]", function() Snacks.words.jump(vim.v.count1) end, has = "documentHighlight",
+        desc = "Next Reference", cond = function() return Snacks.words.is_enabled() end },
+      { "[[", function() Snacks.words.jump(-vim.v.count1) end, has = "documentHighlight",
+        desc = "Prev Reference", cond = function() return Snacks.words.is_enabled() end },
+      { "<a-n>", function() Snacks.words.jump(vim.v.count1, true) end, has = "documentHighlight",
+        desc = "Next Reference", cond = function() return Snacks.words.is_enabled() end },
+      { "<a-p>", function() Snacks.words.jump(-vim.v.count1, true) end, has = "documentHighlight",
+        desc = "Prev Reference", cond = function() return Snacks.words.is_enabled() end },
+    }
+
+  return M._keys
+end
+
+---@param method string|string[]
+function M.has(buffer, method)
+  if type(method) == "table" then
+    for _, m in ipairs(method) do
+      if M.has(buffer, m) then
+        return true
+      end
+    end
+    return false
+  end
+  method = method:find("/") and method or "textDocument/" .. method
+  local clients = LazyVim.lsp.get_clients({ bufnr = buffer })
+  for _, client in ipairs(clients) do
+    if client.supports_method(method) then
+      return true
+    end
+  end
+  return false
+end
+
+---@return LazyKeysLsp[]
+function M.resolve(buffer)
+  local Keys = require("lazy.core.handler.keys")
+  if not Keys.resolve then
+    return {}
+  end
+  local spec = vim.tbl_extend("force", {}, M.get())
+  local opts = LazyVim.opts("nvim-lspconfig")
+  local clients = LazyVim.lsp.get_clients({ bufnr = buffer })
+  for _, client in ipairs(clients) do
+    local maps = opts.servers[client.name] and opts.servers[client.name].keys or {}
+    vim.list_extend(spec, maps)
+  end
+  return Keys.resolve(spec)
+end
+
+function M.on_attach(_, buffer)
+  local Keys = require("lazy.core.handler.keys")
+  local keymaps = M.resolve(buffer)
+
+  for _, keys in pairs(keymaps) do
+    local has = not keys.has or M.has(buffer, keys.has)
+    local cond = not (keys.cond == false or ((type(keys.cond) == "function") and not keys.cond()))
+
+    if has and cond then
+      local opts = Keys.opts(keys)
+      opts.cond = nil
+      opts.has = nil
+      opts.silent = opts.silent ~= false
+      opts.buffer = buffer
+      vim.keymap.set(keys.mode or "n", keys.lhs, keys.rhs, opts)
+    end
+  end
+end
+
+return M
index 347804fb428cadb6212ecda647a106918b3f581f..6f69fc2ba752a832cc253067a5c9721acf9c5c68 100644 (file)
@@ -65,7 +65,7 @@ return {
   },
   { "neovim/nvim-lspconfig",
     opts = function()
   },
   { "neovim/nvim-lspconfig",
     opts = function()
-      local Keys = require("lazyvim.plugins.lsp.keymaps").get()
+      local Keys = require("plugins.lsp.keymaps").get()
       -- stylua: ignore
       vim.list_extend(Keys, {
         { "gd", function() Snacks.picker.lsp_definitions() end, desc = "Goto Definition", has = "definition" },
       -- stylua: ignore
       vim.list_extend(Keys, {
         { "gd", function() Snacks.picker.lsp_definitions() end, desc = "Goto Definition", has = "definition" },