Merge branch 'main' into dev

This commit is contained in:
ChuYanLon 2025-12-08 15:06:45 +08:00 committed by GitHub
commit e2fe9a19be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 332 additions and 282 deletions

View file

@ -1,3 +1,3 @@
{ {
".": "15.10.1" ".": "15.13.0"
} }

3
.markdownlint-cli2.yaml Normal file
View file

@ -0,0 +1,3 @@
config:
MD013: false
MD033: false

View file

@ -1,5 +1,64 @@
# Changelog # Changelog
## [15.13.0](https://github.com/LazyVim/LazyVim/compare/v15.12.2...v15.13.0) (2025-11-01)
### Features
* **snacks:** `snacks.gh` integration. Enabled by default, unless the `util.octo` extra is enabled. ([5e981f9](https://github.com/LazyVim/LazyVim/commit/5e981f9a8cd75eb6f49756e188411037b82b8045))
### Bug Fixes
* **treesitter:** remove node requirement ([6b52a30](https://github.com/LazyVim/LazyVim/commit/6b52a3059e52eed062b6ff3f56e70cffcbf879fe))
## [15.12.2](https://github.com/LazyVim/LazyVim/compare/v15.12.1...v15.12.2) (2025-10-26)
### Bug Fixes
* **lsp.keymaps:** make cond -> enabled work again. Closes [#6697](https://github.com/LazyVim/LazyVim/issues/6697) ([1a40162](https://github.com/LazyVim/LazyVim/commit/1a401627146c66beaeb213f66dd02662f1006e82))
## [15.12.1](https://github.com/LazyVim/LazyVim/compare/v15.12.0...v15.12.1) (2025-10-26)
### Bug Fixes
* **fzf-lua:** LSP keymaps. Closes [#6698](https://github.com/LazyVim/LazyVim/issues/6698) ([b5ea1e9](https://github.com/LazyVim/LazyVim/commit/b5ea1e9d25202e38a47f0b03ac35cc587c80e6d7))
* **navic:** navic attach. Closes [#6702](https://github.com/LazyVim/LazyVim/issues/6702) ([d2d0c64](https://github.com/LazyVim/LazyVim/commit/d2d0c641ed443f8d2ea9e131ec90df59ea149d0a))
## [15.12.0](https://github.com/LazyVim/LazyVim/compare/v15.11.0...v15.12.0) (2025-10-25)
### Features
* **keymaps:** added `<localleader>r` to run the selection/file with lua ([acc3538](https://github.com/LazyVim/LazyVim/commit/acc35382294d91b279b319510b906249a03b2764))
* **lsp:** lsp keymaps can now be configured with `lsp-config.opts.servers['*'].keys` like for lsp servers ([cd8c497](https://github.com/LazyVim/LazyVim/commit/cd8c4977a0a8e80750ed6a10992f988f811c6417))
* **lsp:** refactor lsp code to use `Snacks.util.lsp.on` ([3964433](https://github.com/LazyVim/LazyVim/commit/39644330624139dddb857ed833987c1cfd8432cf))
* **sidekick:** added NES toggle `<leader>uN`. Closes [#6692](https://github.com/LazyVim/LazyVim/issues/6692) ([84ca4df](https://github.com/LazyVim/LazyVim/commit/84ca4dffdbf175a5e7bc39904157700854d8b2ad))
### Bug Fixes
* **chezmoi:** use vim.env.HOME instead of os.getenv("HOME") for Windows compatibility ([231e476](https://github.com/LazyVim/LazyVim/commit/231e476ec9292b56258f86e28773843cddaf34b8))
* **clipboard:** connecting via vscpde's remote-ssh extension causes severe lag during yank and copy operations. ([#6664](https://github.com/LazyVim/LazyVim/issues/6664)) ([5098a69](https://github.com/LazyVim/LazyVim/commit/5098a6987009199d5a5c4bfb8086d0fe4a94e0bb))
* **lang.ember:** remove '.git' lang.ember ([#6685](https://github.com/LazyVim/LazyVim/issues/6685)) ([4796fb4](https://github.com/LazyVim/LazyVim/commit/4796fb4ac54744b69a45a6044655543b1c4231f0))
* **root:** don't use fs_realpath on windows ([46e419d](https://github.com/LazyVim/LazyVim/commit/46e419d27efb5b7282a5ab17a49f4745ce23b55a))
## [15.11.0](https://github.com/LazyVim/LazyVim/compare/v15.10.1...v15.11.0) (2025-10-23)
### Features
* **snacks_picker:** added gai/gao keymaps for calls incoming/outgoing ([b6e48a5](https://github.com/LazyVim/LazyVim/commit/b6e48a57fb4ad7a79f24646016926eef68ce3002))
* **snacks.picker:** added `<leader>gD` to diff against merge base of branch/PR ([f0a91d9](https://github.com/LazyVim/LazyVim/commit/f0a91d9fa5f0cf27d6ba5fac759fa1d4e0df97a3))
### Bug Fixes
* **avante:** unset default keymaps ([#6657](https://github.com/LazyVim/LazyVim/issues/6657)) ([e8a1d8b](https://github.com/LazyVim/LazyVim/commit/e8a1d8b6286f82d75e5830de5ea93bd7622cec8c))
* **extras:** remove custom formatter opts for dart/solidity. Closes [#6665](https://github.com/LazyVim/LazyVim/issues/6665) ([b38de4e](https://github.com/LazyVim/LazyVim/commit/b38de4e2fe4ad887cae1604fd9f1fbd230e0118f))
## [15.10.1](https://github.com/LazyVim/LazyVim/compare/v15.10.0...v15.10.1) (2025-10-20) ## [15.10.1](https://github.com/LazyVim/LazyVim/compare/v15.10.0...v15.10.1) (2025-10-20)

View file

@ -29,3 +29,21 @@
- Every language extra requires a `recommended` section as part of the extra. - Every language extra requires a `recommended` section as part of the extra.
Check lspconfig server configurations for the proper filetypes and root directories. Check lspconfig server configurations for the proper filetypes and root directories.
Refer to other extras for creating the `recommended` section. Refer to other extras for creating the `recommended` section.
### Language-Specific Keymaps
- Use `<localleader>` for language-specific keymaps (follows Vim/Neovim convention for filetype-specific mappings).
- For LSP servers, define keymaps in the server's `keys` field, not in `on_attach`:
```lua
servers = {
rust_analyzer = {
keys = {
{ "<localleader>e", function() vim.cmd.RustLsp("expandMacro") end, desc = "Expand Macro" },
}
}
}
```
- LazyVim's LSP system will automatically resolve and apply these keymaps (see `lua/lazyvim/plugins/lsp/keymaps.lua`).
- Don't override standard LSP keymaps (like `K` for hover, `gd` for definition) unless absolutely necessary.
- Use standard `<leader>c*` keymaps where they make sense (e.g., `<leader>co` for organize imports).
- Refer to the R and Haskell extras for examples of proper `<localleader>` usage.

View file

@ -1,4 +1,4 @@
*LazyVim.txt* For Neovim Last change: 2025 October 22 *LazyVim.txt* LazyVim docs
============================================================================== ==============================================================================
Table of Contents *LazyVim-table-of-contents* Table of Contents *LazyVim-table-of-contents*

View file

@ -3,7 +3,7 @@ _G.LazyVim = require("lazyvim.util")
---@class LazyVimConfig: LazyVimOptions ---@class LazyVimConfig: LazyVimOptions
local M = {} local M = {}
M.version = "15.10.1" -- x-release-please-version M.version = "15.13.0" -- x-release-please-version
LazyVim.config = M LazyVim.config = M
---@class LazyVimOptions ---@class LazyVimOptions
@ -34,7 +34,9 @@ local defaults = {
dots = "󰇘", dots = "󰇘",
}, },
ft = { ft = {
octo = "", octo = "",
gh = "",
["markdown.gh"] = "",
}, },
dap = { dap = {
Stopped = { "󰁕 ", "DiagnosticWarn", "DapStoppedLine" }, Stopped = { "󰁕 ", "DiagnosticWarn", "DapStoppedLine" },

View file

@ -200,3 +200,6 @@ map("n", "<leader><tab><tab>", "<cmd>tabnew<cr>", { desc = "New Tab" })
map("n", "<leader><tab>]", "<cmd>tabnext<cr>", { desc = "Next Tab" }) map("n", "<leader><tab>]", "<cmd>tabnext<cr>", { desc = "Next Tab" })
map("n", "<leader><tab>d", "<cmd>tabclose<cr>", { desc = "Close Tab" }) map("n", "<leader><tab>d", "<cmd>tabclose<cr>", { desc = "Close Tab" })
map("n", "<leader><tab>[", "<cmd>tabprevious<cr>", { desc = "Previous Tab" }) map("n", "<leader><tab>[", "<cmd>tabprevious<cr>", { desc = "Previous Tab" })
-- lua
map({"n", "x"}, "<localleader>r", function() Snacks.debug.run() end, { desc = "Run Lua", ft = "lua" })

View file

@ -54,7 +54,7 @@ local opt = vim.opt
opt.autowrite = true -- Enable auto write opt.autowrite = true -- Enable auto write
-- only set clipboard if not in ssh, to make sure the OSC 52 -- only set clipboard if not in ssh, to make sure the OSC 52
-- integration works automatically. -- integration works automatically.
opt.clipboard = vim.env.SSH_TTY and "" or "unnamedplus" -- Sync with system clipboard opt.clipboard = vim.env.SSH_CONNECTION and "" or "unnamedplus" -- Sync with system clipboard
opt.completeopt = "menu,menuone,noselect" opt.completeopt = "menu,menuone,noselect"
opt.conceallevel = 2 -- Hide * markup for bold and italic, but not markers with substitutions opt.conceallevel = 2 -- Hide * markup for bold and italic, but not markers with substitutions
opt.confirm = true -- Confirm to save changes before exiting modified buffer opt.confirm = true -- Confirm to save changes before exiting modified buffer

View file

@ -5,7 +5,7 @@ if lazyvim_docs then
end end
if LazyVim.has_extra("ai.copilot-native") then if LazyVim.has_extra("ai.copilot-native") then
if not vim.lsp.inline_completion then if vim.fn.has("nvim-0.12") == 0 then
LazyVim.error("You need Neovim >= 0.12 to use the `ai.copilot-native` extra.") LazyVim.error("You need Neovim >= 0.12 to use the `ai.copilot-native` extra.")
return {} return {}
end end

View file

@ -85,9 +85,9 @@ return {
copilot_cmp.setup(opts) copilot_cmp.setup(opts)
-- attach cmp source whenever copilot attaches -- attach cmp source whenever copilot attaches
-- fixes lazy-loading issues with the copilot cmp source -- fixes lazy-loading issues with the copilot cmp source
LazyVim.lsp.on_attach(function() Snacks.util.lsp.on({ name = "copilot" }, function()
copilot_cmp._on_insert_enter({}) copilot_cmp._on_insert_enter({})
end, "copilot") end)
end, end,
specs = { specs = {
{ {

View file

@ -65,6 +65,15 @@ return {
return true return true
end end
end end
Snacks.toggle({
name = "Sidekick NES",
get = function()
return require("sidekick.nes").enabled
end,
set = function(state)
require("sidekick.nes").enable(state)
end,
}):map("<leader>uN")
end, end,
-- stylua: ignore -- stylua: ignore
keys = { keys = {

View file

@ -5,6 +5,9 @@ return {
desc = "Better Yank/Paste", desc = "Better Yank/Paste",
event = "LazyFile", event = "LazyFile",
opts = { opts = {
system_clipboard = {
sync_with_ring = not vim.env.SSH_CONNECTION,
},
highlight = { timer = 150 }, highlight = { timer = 150 },
}, },
keys = { keys = {

View file

@ -289,15 +289,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, { ["*"] = {
{ "gd", "<cmd>FzfLua lsp_definitions jump1=true ignore_current_line=true<cr>", desc = "Goto Definition", has = "definition" }, keys = {
{ "gr", "<cmd>FzfLua lsp_references jump1=true ignore_current_line=true<cr>", desc = "References", nowait = true }, { "gd", "<cmd>FzfLua lsp_definitions jump1=true ignore_current_line=true<cr>", desc = "Goto Definition", has = "definition" },
{ "gI", "<cmd>FzfLua lsp_implementations jump1=true ignore_current_line=true<cr>", desc = "Goto Implementation" }, { "gr", "<cmd>FzfLua lsp_references jump1=true ignore_current_line=true<cr>", desc = "References", nowait = true },
{ "gy", "<cmd>FzfLua lsp_typedefs jump1=true ignore_current_line=true<cr>", desc = "Goto T[y]pe Definition" }, { "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, }
},
},
},
}, },
} }

View file

@ -12,19 +12,24 @@ 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] = { ["*"] = {
"<leader>cr", keys = {
function() {
local inc_rename = require("inc_rename") "<leader>cr",
return ":" .. inc_rename.config.cmd_name .. " " .. vim.fn.expand("<cword>") function()
end, local inc_rename = require("inc_rename")
expr = true, return ":" .. inc_rename.config.cmd_name .. " " .. vim.fn.expand("<cword>")
desc = "Rename (inc-rename.nvim)", end,
has = "rename", expr = true,
} desc = "Rename (inc-rename.nvim)",
end, has = "rename",
},
},
},
},
},
}, },
--- Noice integration --- Noice integration

View file

@ -7,13 +7,11 @@ return {
lazy = true, lazy = true,
init = function() init = function()
vim.g.navic_silence = true vim.g.navic_silence = true
LazyVim.lsp.on_attach(function(client, buffer)
if client:supports_method("textDocument/documentSymbol") then
require("nvim-navic").attach(client, buffer)
end
end)
end, end,
opts = function() opts = function()
Snacks.util.lsp.on({ method = "textDocument/documentSymbol" }, function(buffer, client)
require("nvim-navic").attach(client, buffer)
end)
return { return {
separator = " ", separator = " ",
highlight = true, highlight = true,

View file

@ -107,16 +107,23 @@ return {
}, },
{ {
"neovim/nvim-lspconfig", "neovim/nvim-lspconfig",
opts = function() opts = {
local Keys = require("lazyvim.plugins.lsp.keymaps").get() servers = {
-- stylua: ignore ["*"] = {
vim.list_extend(Keys, { -- stylua: ignore
{ "gd", function() Snacks.picker.lsp_definitions() end, desc = "Goto Definition", has = "definition" }, keys = {
{ "gr", function() Snacks.picker.lsp_references() end, nowait = true, desc = "References" }, { "gd", function() Snacks.picker.lsp_definitions() end, desc = "Goto Definition", has = "definition" },
{ "gi", function() Snacks.picker.lsp_implementations() end, desc = "Goto Implementation" }, { "gr", function() Snacks.picker.lsp_references() end, nowait = true, desc = "References" },
{ "gy", function() Snacks.picker.lsp_type_definitions() end, desc = "Goto T[y]pe Definition" }, { "gI", function() Snacks.picker.lsp_implementations() end, desc = "Goto Implementation" },
}) { "gy", function() Snacks.picker.lsp_type_definitions() end, desc = "Goto T[y]pe Definition" },
end, { "<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", "folke/todo-comments.nvim",

View file

@ -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 ["*"] = {
vim.list_extend(Keys, { -- stylua: ignore
{ "gd", function() require("telescope.builtin").lsp_definitions({ reuse_win = true }) end, desc = "Goto Definition", has = "definition" }, keys = {
{ "gr", "<cmd>Telescope lsp_references<cr>", desc = "References", nowait = true }, { "gd", function() require("telescope.builtin").lsp_definitions({ reuse_win = true }) end, desc = "Goto Definition", has = "definition" },
{ "gI", function() require("telescope.builtin").lsp_implementations({ reuse_win = true }) end, desc = "Goto Implementation" }, { "gr", "<cmd>Telescope lsp_references<cr>", desc = "References", nowait = true },
{ "gy", function() require("telescope.builtin").lsp_type_definitions({ reuse_win = true }) end, desc = "Goto T[y]pe Definition" }, { "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, },
},
},
},
}, },
} }

View file

@ -35,10 +35,10 @@ return {
}, },
setup = { setup = {
angularls = function() angularls = function()
LazyVim.lsp.on_attach(function(client) Snacks.util.lsp.on({ name = "angularls" }, function(_, client)
--HACK: disable angular renaming capability due to duplicate rename popping up --HACK: disable angular renaming capability due to duplicate rename popping up
client.server_capabilities.renameProvider = false client.server_capabilities.renameProvider = false
end, "angularls") end)
end, end,
}, },
}, },

View file

@ -2,7 +2,7 @@ return {
recommended = function() recommended = function()
return LazyVim.extras.wants({ return LazyVim.extras.wants({
ft = { "handlebars", "typescript", "javascript", "typescript.glimmer", "javascript.glimmer" }, ft = { "handlebars", "typescript", "javascript", "typescript.glimmer", "javascript.glimmer" },
root = { "ember-cli-build.js", ".git" }, root = { "ember-cli-build.js" },
}) })
end, end,
{ {

View file

@ -55,7 +55,7 @@ return {
gopls = function(_, opts) gopls = function(_, opts)
-- workaround for gopls not supporting semanticTokensProvider -- workaround for gopls not supporting semanticTokensProvider
-- https://github.com/golang/go/issues/54531#issuecomment-1464982242 -- https://github.com/golang/go/issues/54531#issuecomment-1464982242
LazyVim.lsp.on_attach(function(client, _) Snacks.util.lsp.on({ name = "gopls" }, function(_, client)
if not client.server_capabilities.semanticTokensProvider then if not client.server_capabilities.semanticTokensProvider then
local semantic = client.config.capabilities.textDocument.semanticTokens local semantic = client.config.capabilities.textDocument.semanticTokens
client.server_capabilities.semanticTokensProvider = { client.server_capabilities.semanticTokensProvider = {
@ -67,7 +67,7 @@ return {
range = true, range = true,
} }
end end
end, "gopls") end)
-- end workaround -- end workaround
end, end,
}, },

View file

@ -58,10 +58,10 @@ return {
}, },
setup = { setup = {
[ruff] = function() [ruff] = function()
LazyVim.lsp.on_attach(function(client, _) Snacks.util.lsp.on({ name = ruff }, function(_, client)
-- Disable hover in favor of Pyright -- Disable hover in favor of Pyright
client.server_capabilities.hoverProvider = false client.server_capabilities.hoverProvider = false
end, ruff) end)
end, end,
}, },
}, },

View file

@ -161,7 +161,7 @@ return {
resolve("vtsls") resolve("vtsls")
end end
LazyVim.lsp.on_attach(function(client, buffer) Snacks.util.lsp.on({ name = "vtsls" }, function(buffer, client)
client.commands["_typescript.moveToFileRefactoring"] = function(command, ctx) client.commands["_typescript.moveToFileRefactoring"] = function(command, ctx)
---@type string, string, lsp.Range ---@type string, string, lsp.Range
local action, uri, range = unpack(command.arguments) local action, uri, range = unpack(command.arguments)
@ -210,7 +210,7 @@ return {
end) end)
end) end)
end end
end, "vtsls") end)
-- copy typescript settings to javascript -- copy typescript settings to javascript
opts.settings.javascript = opts.settings.javascript =
vim.tbl_deep_extend("force", {}, opts.settings.typescript, opts.settings.javascript or {}) vim.tbl_deep_extend("force", {}, opts.settings.typescript, opts.settings.javascript or {})

View file

@ -5,10 +5,15 @@ local pick_chezmoi = function()
local fzf_lua = require("fzf-lua") local fzf_lua = require("fzf-lua")
local actions = { local actions = {
["enter"] = function(selected) ["enter"] = function(selected)
fzf_lua.actions.vimcmd_entry("ChezmoiEdit", selected, { cwd = os.getenv("HOME") }) fzf_lua.actions.vimcmd_entry("ChezmoiEdit", selected, { cwd = vim.env.HOME })
end, end,
} }
fzf_lua.files({ cmd = "chezmoi managed --include=files,symlinks", actions = actions, hidden = false }) fzf_lua.files({
cmd = "chezmoi managed --include=files,symlinks",
actions = actions,
cwd = vim.env.HOME,
hidden = false,
})
elseif LazyVim.pick.picker.name == "snacks" then elseif LazyVim.pick.picker.name == "snacks" then
local results = require("chezmoi.commands").list({ local results = require("chezmoi.commands").list({
args = { args = {
@ -50,7 +55,7 @@ return {
"alker0/chezmoi.vim", "alker0/chezmoi.vim",
init = function() init = function()
vim.g["chezmoi#use_tmp_buffer"] = 1 vim.g["chezmoi#use_tmp_buffer"] = 1
vim.g["chezmoi#source_dir_path"] = os.getenv("HOME") .. "/.local/share/chezmoi" vim.g["chezmoi#source_dir_path"] = vim.env.HOME .. "/.local/share/chezmoi"
end, end,
}, },
{ {
@ -80,7 +85,7 @@ return {
init = function() init = function()
-- run chezmoi edit on file enter -- run chezmoi edit on file enter
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, { vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
pattern = { os.getenv("HOME") .. "/.local/share/chezmoi/*" }, pattern = { vim.env.HOME .. "/.local/share/chezmoi/*" },
callback = function() callback = function()
vim.schedule(require("chezmoi.commands.__edit").watch) vim.schedule(require("chezmoi.commands.__edit").watch)
end, end,

View file

@ -3,6 +3,16 @@ return {
-- depends on the git extra for highlighting and auto-completion of github issues/prs -- depends on the git extra for highlighting and auto-completion of github issues/prs
{ import = "lazyvim.plugins.extras.lang.git" }, { import = "lazyvim.plugins.extras.lang.git" },
{
"folke/snacks.nvim",
keys = { -- disable conflicting keymaps
{ "<leader>gi", false },
{ "<leader>gI", false },
{ "<leader>gp", false },
{ "<leader>gP", false },
},
},
-- Octo -- Octo
{ {
"pwntester/octo.nvim", "pwntester/octo.nvim",

View file

@ -7,14 +7,6 @@ if vim.fn.has("nvim-0.11.2") == 0 then
vim.fn.getchar() vim.fn.getchar()
vim.cmd([[quit]]) vim.cmd([[quit]])
return {} return {}
elseif not vim.lsp.is_enabled then
vim.schedule(function()
LazyVim.warn({
"You're using an **old** `nightly` version of **Neovim**",
"Please update to a recent `nightly`,",
"or a stable version (`>= 0.11.2`).",
})
end)
end end
require("lazyvim.config").init() require("lazyvim.config").init()

View file

@ -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", enabled = function() return Snacks.words.is_enabled() end },
{ "[[", function() Snacks.words.jump(-vim.v.count1) end, has = "documentHighlight",
desc = "Prev Reference", enabled = function() return Snacks.words.is_enabled() end },
{ "<a-n>", function() Snacks.words.jump(vim.v.count1, true) end, has = "documentHighlight",
desc = "Next Reference", enabled = function() return Snacks.words.is_enabled() end },
{ "<a-p>", function() Snacks.words.jump(-vim.v.count1, true) end, has = "documentHighlight",
desc = "Prev Reference", enabled = 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
@ -125,16 +155,15 @@ return {
LazyVim.format.register(LazyVim.lsp.formatter()) LazyVim.format.register(LazyVim.lsp.formatter())
-- setup keymaps -- setup keymaps
LazyVim.lsp.on_attach(function(client, buffer) for server, server_opts in pairs(opts.servers) do
require("lazyvim.plugins.lsp.keymaps").on_attach(client, buffer) if type(server_opts) == "table" and server_opts.keys then
end) require("lazyvim.plugins.lsp.keymaps").set({ name = server ~= "*" and server or nil }, server_opts.keys)
end
LazyVim.lsp.setup() end
LazyVim.lsp.on_dynamic_capability(require("lazyvim.plugins.lsp.keymaps").on_attach)
-- inlay hints -- inlay hints
if opts.inlay_hints.enabled then if opts.inlay_hints.enabled then
LazyVim.lsp.on_supports_method("textDocument/inlayHint", function(client, buffer) Snacks.util.lsp.on({ method = "textDocument/inlayHint" }, function(buffer)
if if
vim.api.nvim_buf_is_valid(buffer) vim.api.nvim_buf_is_valid(buffer)
and vim.bo[buffer].buftype == "" and vim.bo[buffer].buftype == ""
@ -147,7 +176,7 @@ return {
-- folds -- folds
if opts.folds.enabled then if opts.folds.enabled then
LazyVim.lsp.on_supports_method("textDocument/foldingRange", function(client, buffer) Snacks.util.lsp.on({ method = "textDocument/foldingRange" }, function()
if LazyVim.set_default("foldmethod", "expr") then if LazyVim.set_default("foldmethod", "expr") then
LazyVim.set_default("foldexpr", "v:lua.vim.lsp.foldexpr()") LazyVim.set_default("foldexpr", "v:lua.vim.lsp.foldexpr()")
end end
@ -156,7 +185,7 @@ return {
-- code lens -- code lens
if opts.codelens.enabled and vim.lsp.codelens then if opts.codelens.enabled and vim.lsp.codelens then
LazyVim.lsp.on_supports_method("textDocument/codeLens", function(client, buffer) Snacks.util.lsp.on({ method = "textDocument/codeLens" }, function(buffer)
vim.lsp.codelens.refresh() vim.lsp.codelens.refresh()
vim.api.nvim_create_autocmd({ "BufEnter", "CursorHold", "InsertLeave" }, { vim.api.nvim_create_autocmd({ "BufEnter", "CursorHold", "InsertLeave" }, {
buffer = buffer, buffer = buffer,
@ -180,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
@ -192,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]]

View file

@ -1,96 +1,65 @@
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[], enabled?:fun():boolean}
---@alias LazyKeysLsp LazyKeys|{has?:string|string[], cond?:fun():boolean} ---@alias LazyKeysLsp LazyKeys|{has?:string|string[], enabled?: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" }, },
{ "<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" }, }, { stacktrace = true })
{ "]]", function() Snacks.words.jump(vim.v.count1) end, has = "documentHighlight", vim.schedule(function()
desc = "Next Reference", cond = function() return Snacks.words.is_enabled() end }, if #M._keys > 0 then
{ "[[", function() Snacks.words.jump(-vim.v.count1) end, has = "documentHighlight", M.set({}, M._keys)
desc = "Prev Reference", cond = function() return Snacks.words.is_enabled() end }, M._keys = {}
{ "<a-n>", function() Snacks.words.jump(vim.v.count1, true) end, has = "documentHighlight", end
desc = "Next Reference", cond = function() return Snacks.words.is_enabled() end }, 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 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 local Keys = require("lazy.core.handler.keys")
if M.has(buffer, m) then for _, keys in pairs(Keys.resolve(spec)) do
return true ---@cast keys LazyKeysLsp
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
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[] for _, f in ipairs(filters) do
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) 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 opts.enabled = keys.enabled
opts.buffer = buffer Snacks.keymap.set(keys.mode or "n", keys.lhs, keys.rhs, opts)
vim.keymap.set(keys.mode or "n", keys.lhs, keys.rhs, opts)
end end
end end
end end

View file

@ -171,8 +171,14 @@ return {
for method, keymaps in pairs(moves) do for method, keymaps in pairs(moves) do
for key, query in pairs(keymaps) do for key, query in pairs(keymaps) do
local desc = query:gsub("@", ""):gsub("%..*", "") local queries = type(query) == "table" and query or { query }
desc = desc:sub(1, 1):upper() .. desc:sub(2) local parts = {}
for _, q in ipairs(queries) do
local part = q:gsub("@", ""):gsub("%..*", "")
part = part:sub(1, 1):upper() .. part:sub(2)
table.insert(parts, part)
end
local desc = table.concat(parts, " or ")
desc = (key:sub(1, 1) == "[" and "Prev " or "Next ") .. desc desc = (key:sub(1, 1) == "[" and "Prev " or "Next ") .. desc
desc = desc .. (key:sub(2, 2) == key:sub(2, 2):upper() and " End" or " Start") desc = desc .. (key:sub(2, 2) == key:sub(2, 2):upper() and " End" or " Start")
if not (vim.wo.diff and key:find("[cC]")) then if not (vim.wo.diff and key:find("[cC]")) then

View file

@ -23,8 +23,6 @@ return {
nav_j = { "<C-j>", term_nav("j"), desc = "Go to Lower Window", expr = true, mode = "t" }, nav_j = { "<C-j>", term_nav("j"), desc = "Go to Lower Window", expr = true, mode = "t" },
nav_k = { "<C-k>", term_nav("k"), desc = "Go to Upper Window", expr = true, mode = "t" }, nav_k = { "<C-k>", term_nav("k"), desc = "Go to Upper Window", expr = true, mode = "t" },
nav_l = { "<C-l>", term_nav("l"), desc = "Go to Right Window", expr = true, mode = "t" }, nav_l = { "<C-l>", term_nav("l"), desc = "Go to Right Window", expr = true, mode = "t" },
hide_slash = { "<C-/>", "hide", desc = "Hide Terminal", mode = { "t", "n" } },
hide_underscore = { "<c-_>", "hide", desc = "which_key_ignore", mode = { "t", "n" } },
}, },
}, },
}, },

View file

@ -6,6 +6,22 @@ M.moved = {
rename_file = { "Snacks.rename.rename_file" }, rename_file = { "Snacks.rename.rename_file" },
on_rename = { "Snacks.rename.on_rename_file" }, on_rename = { "Snacks.rename.on_rename_file" },
words = { "Snacks.words" }, words = { "Snacks.words" },
on_supports_method = {
"Snacks.util.lsp.on",
fn = function(method, cb)
return Snacks.util.lsp.on({ method = method }, function(buffer, client)
cb(client, buffer)
end)
end,
},
on_attach = {
"Snacks.util.lsp.on",
fn = function(cb, name)
return Snacks.util.lsp.on({ name = name }, function(buffer, client)
cb(client, buffer)
end)
end,
},
}, },
terminal = { terminal = {
open = { "Snacks.terminal" }, open = { "Snacks.terminal" },

View file

@ -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

View file

@ -1,103 +1,6 @@
---@class lazyvim.util.lsp ---@class lazyvim.util.lsp
local M = {} local M = {}
---@param on_attach fun(client:vim.lsp.Client, buffer)
---@param name? string
function M.on_attach(on_attach, name)
return vim.api.nvim_create_autocmd("LspAttach", {
callback = function(args)
local buffer = args.buf ---@type number
local client = vim.lsp.get_client_by_id(args.data.client_id)
if client and (not name or client.name == name) then
return on_attach(client, buffer)
end
end,
})
end
---@type table<string, table<vim.lsp.Client, table<number, boolean>>>
M._supports_method = {}
function M.setup()
local register_capability = vim.lsp.handlers["client/registerCapability"]
vim.lsp.handlers["client/registerCapability"] = function(err, res, ctx)
---@diagnostic disable-next-line: no-unknown
local ret = register_capability(err, res, ctx)
local client = vim.lsp.get_client_by_id(ctx.client_id)
if client then
for buffer in pairs(client.attached_buffers) do
vim.api.nvim_exec_autocmds("User", {
pattern = "LspDynamicCapability",
data = { client_id = client.id, buffer = buffer },
})
end
end
return ret
end
M.on_attach(M._check_methods)
M.on_dynamic_capability(M._check_methods)
end
---@param client vim.lsp.Client
function M._check_methods(client, buffer)
-- don't trigger on invalid buffers
if not vim.api.nvim_buf_is_valid(buffer) then
return
end
-- don't trigger on non-listed buffers
if not vim.bo[buffer].buflisted then
return
end
-- don't trigger on nofile buffers
if vim.bo[buffer].buftype == "nofile" then
return
end
for method, clients in pairs(M._supports_method) do
clients[client] = clients[client] or {}
if not clients[client][buffer] then
if client.supports_method and client:supports_method(method, buffer) then
clients[client][buffer] = true
vim.api.nvim_exec_autocmds("User", {
pattern = "LspSupportsMethod",
data = { client_id = client.id, buffer = buffer, method = method },
})
end
end
end
end
---@param fn fun(client:vim.lsp.Client, buffer):boolean?
---@param opts? {group?: integer}
function M.on_dynamic_capability(fn, opts)
return vim.api.nvim_create_autocmd("User", {
pattern = "LspDynamicCapability",
group = opts and opts.group or nil,
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
local buffer = args.data.buffer ---@type number
if client then
return fn(client, buffer)
end
end,
})
end
---@param method string
---@param fn fun(client:vim.lsp.Client, buffer)
function M.on_supports_method(method, fn)
M._supports_method[method] = M._supports_method[method] or setmetatable({}, { __mode = "k" })
return vim.api.nvim_create_autocmd("User", {
pattern = "LspSupportsMethod",
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
local buffer = args.data.buffer ---@type number
if client and method == args.data.method then
return fn(client, buffer)
end
end,
})
end
---@param opts? LazyFormatter| {filter?: (string|vim.lsp.get_clients.Filter)} ---@param opts? LazyFormatter| {filter?: (string|vim.lsp.get_clients.Filter)}
function M.formatter(opts) function M.formatter(opts)
opts = opts or {} opts = opts or {}

View file

@ -78,7 +78,7 @@ function M.realpath(path)
if path == "" or path == nil then if path == "" or path == nil then
return nil return nil
end end
path = vim.uv.fs_realpath(path) or path path = vim.fn.has("win32") == 0 and vim.uv.fs_realpath(path) or path
return LazyVim.norm(path) return LazyVim.norm(path)
end end

View file

@ -18,7 +18,7 @@ function M.setup(shell)
-- Setting shell command flags -- Setting shell command flags
vim.o.shellcmdflag = vim.o.shellcmdflag =
"-NoLogo -NonInteractive -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();$PSDefaultParameterValues['Out-File:Encoding']='utf8';$PSStyle.OutputRendering='plaintext';Remove-Alias -Force -ErrorAction SilentlyContinue tee;" "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();$PSDefaultParameterValues['Out-File:Encoding']='utf8';$PSStyle.OutputRendering='plaintext';Remove-Alias -Force -ErrorAction SilentlyContinue tee;"
-- Setting shell redirection -- Setting shell redirection
vim.o.shellredir = '2>&1 | %%{ "$_" } | Out-File %s; exit $LastExitCode' vim.o.shellredir = '2>&1 | %%{ "$_" } | Out-File %s; exit $LastExitCode'

View file

@ -80,7 +80,6 @@ function M.check()
["C compiler"] = have_cc, ["C compiler"] = have_cc,
tar = have("tar"), tar = have("tar"),
curl = have("curl"), curl = have("curl"),
node = have("node"),
} }
local ok = true local ok = true
for _, v in pairs(ret) do for _, v in pairs(ret) do