mirror of
https://github.com/LazyVim/LazyVim.git
synced 2025-12-25 12:14:19 +01:00
feat(lsp): lsp keymaps can now be configured with lsp-config.opts.servers['*'].keys like for lsp servers
This commit is contained in:
@@ -289,15 +289,16 @@ return {
|
||||
|
||||
{
|
||||
"neovim/nvim-lspconfig",
|
||||
opts = function()
|
||||
local Keys = require("lazyvim.plugins.lsp.keymaps").get()
|
||||
-- stylua: ignore
|
||||
vim.list_extend(Keys, {
|
||||
{ "gd", "<cmd>FzfLua lsp_definitions jump1=true ignore_current_line=true<cr>", desc = "Goto Definition", has = "definition" },
|
||||
{ "gr", "<cmd>FzfLua lsp_references jump1=true ignore_current_line=true<cr>", desc = "References", nowait = true },
|
||||
{ "gI", "<cmd>FzfLua lsp_implementations jump1=true ignore_current_line=true<cr>", desc = "Goto Implementation" },
|
||||
{ "gy", "<cmd>FzfLua lsp_typedefs jump1=true ignore_current_line=true<cr>", desc = "Goto T[y]pe Definition" },
|
||||
})
|
||||
end,
|
||||
opts = {
|
||||
servers = {
|
||||
-- stylua: ignore
|
||||
["*"] = {
|
||||
{ "gd", "<cmd>FzfLua lsp_definitions jump1=true ignore_current_line=true<cr>", desc = "Goto Definition", has = "definition" },
|
||||
{ "gr", "<cmd>FzfLua lsp_references jump1=true ignore_current_line=true<cr>", desc = "References", nowait = true },
|
||||
{ "gI", "<cmd>FzfLua lsp_implementations jump1=true ignore_current_line=true<cr>", desc = "Goto Implementation" },
|
||||
{ "gy", "<cmd>FzfLua lsp_typedefs jump1=true ignore_current_line=true<cr>", desc = "Goto T[y]pe Definition" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -12,19 +12,24 @@ return {
|
||||
-- LSP Keymaps
|
||||
{
|
||||
"neovim/nvim-lspconfig",
|
||||
opts = function()
|
||||
local keys = require("lazyvim.plugins.lsp.keymaps").get()
|
||||
keys[#keys + 1] = {
|
||||
"<leader>cr",
|
||||
function()
|
||||
local inc_rename = require("inc_rename")
|
||||
return ":" .. inc_rename.config.cmd_name .. " " .. vim.fn.expand("<cword>")
|
||||
end,
|
||||
expr = true,
|
||||
desc = "Rename (inc-rename.nvim)",
|
||||
has = "rename",
|
||||
}
|
||||
end,
|
||||
opts = {
|
||||
servers = {
|
||||
["*"] = {
|
||||
keys = {
|
||||
{
|
||||
"<leader>cr",
|
||||
function()
|
||||
local inc_rename = require("inc_rename")
|
||||
return ":" .. inc_rename.config.cmd_name .. " " .. vim.fn.expand("<cword>")
|
||||
end,
|
||||
expr = true,
|
||||
desc = "Rename (inc-rename.nvim)",
|
||||
has = "rename",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
--- Noice integration
|
||||
|
||||
@@ -135,20 +135,23 @@ return {
|
||||
},
|
||||
{
|
||||
"neovim/nvim-lspconfig",
|
||||
opts = function()
|
||||
local Keys = require("lazyvim.plugins.lsp.keymaps").get()
|
||||
-- stylua: ignore
|
||||
vim.list_extend(Keys, {
|
||||
{ "gd", function() Snacks.picker.lsp_definitions() end, desc = "Goto Definition", has = "definition" },
|
||||
{ "gr", function() Snacks.picker.lsp_references() end, nowait = true, desc = "References" },
|
||||
{ "gI", function() Snacks.picker.lsp_implementations() end, desc = "Goto Implementation" },
|
||||
{ "gy", function() Snacks.picker.lsp_type_definitions() end, desc = "Goto T[y]pe Definition" },
|
||||
{ "<leader>ss", function() Snacks.picker.lsp_symbols({ filter = LazyVim.config.kind_filter }) end, desc = "LSP Symbols", has = "documentSymbol" },
|
||||
{ "<leader>sS", function() Snacks.picker.lsp_workspace_symbols({ filter = LazyVim.config.kind_filter }) end, desc = "LSP Workspace Symbols", has = "workspace/symbols" },
|
||||
{ "gai", function() Snacks.picker.lsp_incoming_calls() end, desc = "C[a]lls Incoming", has = "callHierarchy/incomingCalls" },
|
||||
{ "gao", function() Snacks.picker.lsp_outgoing_calls() end, desc = "C[a]lls Outgoing", has = "callHierarchy/outgoingCalls" },
|
||||
})
|
||||
end,
|
||||
opts = {
|
||||
servers = {
|
||||
["*"] = {
|
||||
-- stylua: ignore
|
||||
keys = {
|
||||
{ "gd", function() Snacks.picker.lsp_definitions() end, desc = "Goto Definition", has = "definition" },
|
||||
{ "gr", function() Snacks.picker.lsp_references() end, nowait = true, desc = "References" },
|
||||
{ "gI", function() Snacks.picker.lsp_implementations() end, desc = "Goto Implementation" },
|
||||
{ "gy", function() Snacks.picker.lsp_type_definitions() end, desc = "Goto T[y]pe Definition" },
|
||||
{ "<leader>ss", function() Snacks.picker.lsp_symbols({ filter = LazyVim.config.kind_filter }) end, desc = "LSP Symbols", has = "documentSymbol" },
|
||||
{ "<leader>sS", function() Snacks.picker.lsp_workspace_symbols({ filter = LazyVim.config.kind_filter }) end, desc = "LSP Workspace Symbols", has = "workspace/symbols" },
|
||||
{ "gai", function() Snacks.picker.lsp_incoming_calls() end, desc = "C[a]lls Incoming", has = "callHierarchy/incomingCalls" },
|
||||
{ "gao", function() Snacks.picker.lsp_outgoing_calls() end, desc = "C[a]lls Outgoing", has = "callHierarchy/outgoingCalls" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"folke/todo-comments.nvim",
|
||||
|
||||
@@ -284,15 +284,18 @@ return {
|
||||
|
||||
{
|
||||
"neovim/nvim-lspconfig",
|
||||
opts = function()
|
||||
local Keys = require("lazyvim.plugins.lsp.keymaps").get()
|
||||
-- stylua: ignore
|
||||
vim.list_extend(Keys, {
|
||||
{ "gd", function() require("telescope.builtin").lsp_definitions({ reuse_win = true }) end, desc = "Goto Definition", has = "definition" },
|
||||
{ "gr", "<cmd>Telescope lsp_references<cr>", desc = "References", nowait = true },
|
||||
{ "gI", function() require("telescope.builtin").lsp_implementations({ reuse_win = true }) end, desc = "Goto Implementation" },
|
||||
{ "gy", function() require("telescope.builtin").lsp_type_definitions({ reuse_win = true }) end, desc = "Goto T[y]pe Definition" },
|
||||
})
|
||||
end,
|
||||
opts = {
|
||||
servers = {
|
||||
["*"] = {
|
||||
-- stylua: ignore
|
||||
keys = {
|
||||
{ "gd", function() require("telescope.builtin").lsp_definitions({ reuse_win = true }) end, desc = "Goto Definition", has = "definition" },
|
||||
{ "gr", "<cmd>Telescope lsp_references<cr>", desc = "References", nowait = true },
|
||||
{ "gI", function() require("telescope.builtin").lsp_implementations({ reuse_win = true }) end, desc = "Goto Implementation" },
|
||||
{ "gy", function() require("telescope.builtin").lsp_type_definitions({ reuse_win = true }) end, desc = "Goto T[y]pe Definition" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ return {
|
||||
"mason.nvim",
|
||||
{ "mason-org/mason-lspconfig.nvim", config = function() end },
|
||||
},
|
||||
opts_extend = { "servers.*.keys" },
|
||||
opts = function()
|
||||
---@class PluginLspOpts
|
||||
local ret = {
|
||||
@@ -51,15 +52,6 @@ return {
|
||||
folds = {
|
||||
enabled = true,
|
||||
},
|
||||
-- add any global capabilities here
|
||||
capabilities = {
|
||||
workspace = {
|
||||
fileOperations = {
|
||||
didRename = true,
|
||||
willRename = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
-- options for vim.lsp.buf.format
|
||||
-- `bufnr` and `filter` is handled by the LazyVim formatter,
|
||||
-- but can be also overridden when specified
|
||||
@@ -68,9 +60,47 @@ return {
|
||||
timeout_ms = nil,
|
||||
},
|
||||
-- LSP Server Settings
|
||||
---@alias lazyvim.lsp.Config vim.lsp.Config|{mason?:boolean, enabled?:boolean}
|
||||
-- Sets the default configuration for an LSP client (or all clients if the special name "*" is used).
|
||||
---@alias lazyvim.lsp.Config vim.lsp.Config|{mason?:boolean, enabled?:boolean, keys?:LazyKeysLspSpec[]}
|
||||
---@type table<string, lazyvim.lsp.Config|boolean>
|
||||
servers = {
|
||||
-- configuration for all lsp servers
|
||||
["*"] = {
|
||||
capabilities = {
|
||||
workspace = {
|
||||
fileOperations = {
|
||||
didRename = true,
|
||||
willRename = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
-- stylua: ignore
|
||||
keys = {
|
||||
{ "<leader>cl", function() Snacks.picker.lsp_config() end, 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", "x" }, has = "codeAction" },
|
||||
{ "<leader>cc", vim.lsp.codelens.run, desc = "Run Codelens", mode = { "n", "x" }, 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 },
|
||||
},
|
||||
},
|
||||
stylua = { enabled = false },
|
||||
lua_ls = {
|
||||
-- mason = false, -- set to false if you don't want this server to be installed with mason
|
||||
@@ -179,7 +209,14 @@ return {
|
||||
vim.diagnostic.config(vim.deepcopy(opts.diagnostics))
|
||||
|
||||
if opts.capabilities then
|
||||
vim.lsp.config("*", { capabilities = opts.capabilities })
|
||||
LazyVim.deprecate("lsp-config.opts.capabilities", "Use lsp-config.opts.servers['*'].capabilities instead")
|
||||
opts.servers["*"] = vim.tbl_deep_extend("force", opts.servers["*"] or {}, {
|
||||
capabilities = opts.capabilities,
|
||||
})
|
||||
end
|
||||
|
||||
if opts.servers["*"] then
|
||||
vim.lsp.config("*", opts.servers["*"])
|
||||
end
|
||||
|
||||
-- get all the servers that are available through mason-lspconfig
|
||||
@@ -191,6 +228,9 @@ return {
|
||||
|
||||
---@return boolean? exclude automatic setup
|
||||
local function configure(server)
|
||||
if server == "*" then
|
||||
return false
|
||||
end
|
||||
local sopts = opts.servers[server]
|
||||
sopts = sopts == true and {} or (not sopts) and { enabled = false } or sopts --[[@as lazyvim.lsp.Config]]
|
||||
|
||||
|
||||
@@ -1,97 +1,66 @@
|
||||
local M = {}
|
||||
|
||||
---@type LazyKeysLspSpec[]|nil
|
||||
M._keys = nil
|
||||
M._keys = {}
|
||||
|
||||
---@alias LazyKeysLspSpec LazyKeysSpec|{has?:string|string[], cond?:fun():boolean}
|
||||
---@alias LazyKeysLsp LazyKeys|{has?:string|string[], cond?:fun():boolean}
|
||||
|
||||
---@deprecated
|
||||
---@return LazyKeysLspSpec[]
|
||||
function M.get()
|
||||
if M._keys then
|
||||
return M._keys
|
||||
end
|
||||
-- stylua: ignore
|
||||
M._keys = {
|
||||
{ "<leader>cl", function() Snacks.picker.lsp_config() end, 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", "x" }, has = "codeAction" },
|
||||
{ "<leader>cc", vim.lsp.codelens.run, desc = "Run Codelens", mode = { "n", "x" }, 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 },
|
||||
}
|
||||
|
||||
LazyVim.warn({
|
||||
'Adding LSP keymaps via `require("lazyvim.plugins.lsp.keymaps").get()` is deprecated.',
|
||||
"Please set keymaps via the `keys` field in the LSP server config.",
|
||||
[[
|
||||
```lua
|
||||
{
|
||||
"neovim/nvim-lspconfig",
|
||||
opts = {
|
||||
servers = {
|
||||
['*'] = {
|
||||
keys = {
|
||||
{ "gd", "<cmd>lua vim.lsp.buf.definition()<CR>", has = "definition"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```]],
|
||||
}, { stacktrace = true })
|
||||
vim.schedule(function()
|
||||
if #M._keys > 0 then
|
||||
M.set({}, M._keys)
|
||||
M._keys = {}
|
||||
end
|
||||
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
|
||||
---@param filter vim.lsp.get_clients.Filter
|
||||
---@param spec LazyKeysLspSpec[]
|
||||
function M.set(filter, spec)
|
||||
local Keys = require("lazy.core.handler.keys")
|
||||
for _, keys in pairs(Keys.resolve(spec)) do
|
||||
---@cast keys LazyKeysLsp
|
||||
if keys.cond == nil or keys.cond() then
|
||||
local filters = {} ---@type vim.lsp.get_clients.Filter[]
|
||||
if keys.has then
|
||||
local methods = type(keys.has) == "string" and { keys.has } or keys.has --[[@as string[] ]]
|
||||
for _, method in ipairs(methods) do
|
||||
method = method:find("/") and method or ("textDocument/" .. method)
|
||||
filters[#filters + 1] = vim.tbl_extend("force", vim.deepcopy(filter), { method = method })
|
||||
end
|
||||
else
|
||||
filters[#filters + 1] = filter
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
method = method:find("/") and method or "textDocument/" .. method
|
||||
local clients = vim.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 = vim.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)
|
||||
for _, f in ipairs(filters) do
|
||||
local opts = Keys.opts(keys)
|
||||
---@cast opts snacks.keymap.set.Opts
|
||||
opts.lsp = f
|
||||
Snacks.keymap.set(keys.mode or "n", keys.lhs, keys.rhs, opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -221,7 +221,7 @@ function M.safe_keymap_set(mode, lhs, rhs, opts)
|
||||
---@diagnostic disable-next-line: no-unknown
|
||||
opts.remap = nil
|
||||
end
|
||||
vim.keymap.set(modes, lhs, rhs, opts)
|
||||
Snacks.keymap.set(modes, lhs, rhs, opts)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user