mirror of
https://github.com/LazyVim/LazyVim.git
synced 2026-03-10 09:27:25 +00: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",
|
"neovim/nvim-lspconfig",
|
||||||
opts = function()
|
opts = {
|
||||||
local Keys = require("lazyvim.plugins.lsp.keymaps").get()
|
servers = {
|
||||||
-- stylua: ignore
|
-- stylua: ignore
|
||||||
vim.list_extend(Keys, {
|
["*"] = {
|
||||||
{ "gd", "<cmd>FzfLua lsp_definitions jump1=true ignore_current_line=true<cr>", desc = "Goto Definition", has = "definition" },
|
{ "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 },
|
{ "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" },
|
{ "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" },
|
{ "gy", "<cmd>FzfLua lsp_typedefs jump1=true ignore_current_line=true<cr>", desc = "Goto T[y]pe Definition" },
|
||||||
})
|
},
|
||||||
end,
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ return {
|
|||||||
-- LSP Keymaps
|
-- LSP Keymaps
|
||||||
{
|
{
|
||||||
"neovim/nvim-lspconfig",
|
"neovim/nvim-lspconfig",
|
||||||
opts = function()
|
opts = {
|
||||||
local keys = require("lazyvim.plugins.lsp.keymaps").get()
|
servers = {
|
||||||
keys[#keys + 1] = {
|
["*"] = {
|
||||||
|
keys = {
|
||||||
|
{
|
||||||
"<leader>cr",
|
"<leader>cr",
|
||||||
function()
|
function()
|
||||||
local inc_rename = require("inc_rename")
|
local inc_rename = require("inc_rename")
|
||||||
@@ -23,8 +25,11 @@ return {
|
|||||||
expr = true,
|
expr = true,
|
||||||
desc = "Rename (inc-rename.nvim)",
|
desc = "Rename (inc-rename.nvim)",
|
||||||
has = "rename",
|
has = "rename",
|
||||||
}
|
},
|
||||||
end,
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
--- Noice integration
|
--- Noice integration
|
||||||
|
|||||||
@@ -135,10 +135,11 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"neovim/nvim-lspconfig",
|
"neovim/nvim-lspconfig",
|
||||||
opts = function()
|
opts = {
|
||||||
local Keys = require("lazyvim.plugins.lsp.keymaps").get()
|
servers = {
|
||||||
|
["*"] = {
|
||||||
-- stylua: ignore
|
-- stylua: ignore
|
||||||
vim.list_extend(Keys, {
|
keys = {
|
||||||
{ "gd", function() Snacks.picker.lsp_definitions() end, desc = "Goto Definition", has = "definition" },
|
{ "gd", function() Snacks.picker.lsp_definitions() end, desc = "Goto Definition", has = "definition" },
|
||||||
{ "gr", function() Snacks.picker.lsp_references() end, nowait = true, desc = "References" },
|
{ "gr", function() Snacks.picker.lsp_references() end, nowait = true, desc = "References" },
|
||||||
{ "gI", function() Snacks.picker.lsp_implementations() end, desc = "Goto Implementation" },
|
{ "gI", function() Snacks.picker.lsp_implementations() end, desc = "Goto Implementation" },
|
||||||
@@ -147,8 +148,10 @@ return {
|
|||||||
{ "<leader>sS", function() Snacks.picker.lsp_workspace_symbols({ filter = LazyVim.config.kind_filter }) end, desc = "LSP Workspace Symbols", has = "workspace/symbols" },
|
{ "<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" },
|
{ "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" },
|
{ "gao", function() Snacks.picker.lsp_outgoing_calls() end, desc = "C[a]lls Outgoing", has = "callHierarchy/outgoingCalls" },
|
||||||
})
|
},
|
||||||
end,
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"folke/todo-comments.nvim",
|
"folke/todo-comments.nvim",
|
||||||
|
|||||||
@@ -284,15 +284,18 @@ return {
|
|||||||
|
|
||||||
{
|
{
|
||||||
"neovim/nvim-lspconfig",
|
"neovim/nvim-lspconfig",
|
||||||
opts = function()
|
opts = {
|
||||||
local Keys = require("lazyvim.plugins.lsp.keymaps").get()
|
servers = {
|
||||||
|
["*"] = {
|
||||||
-- stylua: ignore
|
-- stylua: ignore
|
||||||
vim.list_extend(Keys, {
|
keys = {
|
||||||
{ "gd", function() require("telescope.builtin").lsp_definitions({ reuse_win = true }) end, desc = "Goto Definition", has = "definition" },
|
{ "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 },
|
{ "gr", "<cmd>Telescope lsp_references<cr>", desc = "References", nowait = true },
|
||||||
{ "gI", function() require("telescope.builtin").lsp_implementations({ reuse_win = true }) end, desc = "Goto Implementation" },
|
{ "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" },
|
{ "gy", function() require("telescope.builtin").lsp_type_definitions({ reuse_win = true }) end, desc = "Goto T[y]pe Definition" },
|
||||||
})
|
},
|
||||||
end,
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ return {
|
|||||||
"mason.nvim",
|
"mason.nvim",
|
||||||
{ "mason-org/mason-lspconfig.nvim", config = function() end },
|
{ "mason-org/mason-lspconfig.nvim", config = function() end },
|
||||||
},
|
},
|
||||||
|
opts_extend = { "servers.*.keys" },
|
||||||
opts = function()
|
opts = function()
|
||||||
---@class PluginLspOpts
|
---@class PluginLspOpts
|
||||||
local ret = {
|
local ret = {
|
||||||
@@ -51,15 +52,6 @@ return {
|
|||||||
folds = {
|
folds = {
|
||||||
enabled = true,
|
enabled = true,
|
||||||
},
|
},
|
||||||
-- add any global capabilities here
|
|
||||||
capabilities = {
|
|
||||||
workspace = {
|
|
||||||
fileOperations = {
|
|
||||||
didRename = true,
|
|
||||||
willRename = true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
-- options for vim.lsp.buf.format
|
-- options for vim.lsp.buf.format
|
||||||
-- `bufnr` and `filter` is handled by the LazyVim formatter,
|
-- `bufnr` and `filter` is handled by the LazyVim formatter,
|
||||||
-- but can be also overridden when specified
|
-- but can be also overridden when specified
|
||||||
@@ -68,9 +60,47 @@ return {
|
|||||||
timeout_ms = nil,
|
timeout_ms = nil,
|
||||||
},
|
},
|
||||||
-- LSP Server Settings
|
-- 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>
|
---@type table<string, lazyvim.lsp.Config|boolean>
|
||||||
servers = {
|
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 },
|
stylua = { enabled = false },
|
||||||
lua_ls = {
|
lua_ls = {
|
||||||
-- mason = false, -- set to false if you don't want this server to be installed with mason
|
-- 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))
|
vim.diagnostic.config(vim.deepcopy(opts.diagnostics))
|
||||||
|
|
||||||
if opts.capabilities then
|
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
|
end
|
||||||
|
|
||||||
-- get all the servers that are available through mason-lspconfig
|
-- get all the servers that are available through mason-lspconfig
|
||||||
@@ -191,6 +228,9 @@ return {
|
|||||||
|
|
||||||
---@return boolean? exclude automatic setup
|
---@return boolean? exclude automatic setup
|
||||||
local function configure(server)
|
local function configure(server)
|
||||||
|
if server == "*" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
local sopts = opts.servers[server]
|
local sopts = opts.servers[server]
|
||||||
sopts = sopts == true and {} or (not sopts) and { enabled = false } or sopts --[[@as lazyvim.lsp.Config]]
|
sopts = sopts == true and {} or (not sopts) and { enabled = false } or sopts --[[@as lazyvim.lsp.Config]]
|
||||||
|
|
||||||
|
|||||||
@@ -1,97 +1,66 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
---@type LazyKeysLspSpec[]|nil
|
---@type LazyKeysLspSpec[]|nil
|
||||||
M._keys = nil
|
M._keys = {}
|
||||||
|
|
||||||
---@alias LazyKeysLspSpec LazyKeysSpec|{has?:string|string[], cond?:fun():boolean}
|
---@alias LazyKeysLspSpec LazyKeysSpec|{has?:string|string[], cond?:fun():boolean}
|
||||||
---@alias LazyKeysLsp LazyKeys|{has?:string|string[], cond?:fun():boolean}
|
---@alias LazyKeysLsp LazyKeys|{has?:string|string[], cond?:fun():boolean}
|
||||||
|
|
||||||
|
---@deprecated
|
||||||
---@return LazyKeysLspSpec[]
|
---@return LazyKeysLspSpec[]
|
||||||
function M.get()
|
function M.get()
|
||||||
if M._keys then
|
LazyVim.warn({
|
||||||
return M._keys
|
'Adding LSP keymaps via `require("lazyvim.plugins.lsp.keymaps").get()` is deprecated.',
|
||||||
end
|
"Please set keymaps via the `keys` field in the LSP server config.",
|
||||||
-- stylua: ignore
|
[[
|
||||||
M._keys = {
|
```lua
|
||||||
{ "<leader>cl", function() Snacks.picker.lsp_config() end, desc = "Lsp Info" },
|
{
|
||||||
{ "gd", vim.lsp.buf.definition, desc = "Goto Definition", has = "definition" },
|
"neovim/nvim-lspconfig",
|
||||||
{ "gr", vim.lsp.buf.references, desc = "References", nowait = true },
|
opts = {
|
||||||
{ "gI", vim.lsp.buf.implementation, desc = "Goto Implementation" },
|
servers = {
|
||||||
{ "gy", vim.lsp.buf.type_definition, desc = "Goto T[y]pe Definition" },
|
['*'] = {
|
||||||
{ "gD", vim.lsp.buf.declaration, desc = "Goto Declaration" },
|
keys = {
|
||||||
{ "K", function() return vim.lsp.buf.hover() end, desc = "Hover" },
|
{ "gd", "<cmd>lua vim.lsp.buf.definition()<CR>", has = "definition"},
|
||||||
{ "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 },
|
|
||||||
}
|
}
|
||||||
|
```]],
|
||||||
|
}, { stacktrace = true })
|
||||||
|
vim.schedule(function()
|
||||||
|
if #M._keys > 0 then
|
||||||
|
M.set({}, M._keys)
|
||||||
|
M._keys = {}
|
||||||
|
end
|
||||||
|
end)
|
||||||
return M._keys
|
return M._keys
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param method string|string[]
|
---@param filter vim.lsp.get_clients.Filter
|
||||||
function M.has(buffer, method)
|
---@param spec LazyKeysLspSpec[]
|
||||||
if type(method) == "table" then
|
function M.set(filter, spec)
|
||||||
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 = 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")
|
local Keys = require("lazy.core.handler.keys")
|
||||||
if not Keys.resolve then
|
for _, keys in pairs(Keys.resolve(spec)) do
|
||||||
return {}
|
---@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
|
end
|
||||||
local spec = vim.tbl_extend("force", {}, M.get())
|
else
|
||||||
local opts = LazyVim.opts("nvim-lspconfig")
|
filters[#filters + 1] = filter
|
||||||
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
|
end
|
||||||
|
|
||||||
function M.on_attach(_, buffer)
|
for _, f in ipairs(filters) do
|
||||||
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)
|
local opts = Keys.opts(keys)
|
||||||
opts.cond = nil
|
---@cast opts snacks.keymap.set.Opts
|
||||||
opts.has = nil
|
opts.lsp = f
|
||||||
opts.silent = opts.silent ~= false
|
Snacks.keymap.set(keys.mode or "n", keys.lhs, keys.rhs, opts)
|
||||||
opts.buffer = buffer
|
end
|
||||||
vim.keymap.set(keys.mode or "n", keys.lhs, keys.rhs, opts)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ function M.safe_keymap_set(mode, lhs, rhs, opts)
|
|||||||
---@diagnostic disable-next-line: no-unknown
|
---@diagnostic disable-next-line: no-unknown
|
||||||
opts.remap = nil
|
opts.remap = nil
|
||||||
end
|
end
|
||||||
vim.keymap.set(modes, lhs, rhs, opts)
|
Snacks.keymap.set(modes, lhs, rhs, opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user