From 60fea6236e342e1f4aa34d078461746d5f587c74 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Sun, 1 Mar 2026 09:17:53 +0100 Subject: [PATCH 01/46] fix(news): resolve news.txt from $VIMRUNTIME first Plugins that ship their own `doc/news.txt` (e.g. rainbow-delimiters.nvim) can shadow Neovim's bundled file when using `nvim_get_runtime_file()`. First check $VIMRUNTIME, then fall back to the full runtimepath. Fixes #7019 --- lua/lazyvim/util/news.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lua/lazyvim/util/news.lua b/lua/lazyvim/util/news.lua index f473f3a3..c891133f 100644 --- a/lua/lazyvim/util/news.lua +++ b/lua/lazyvim/util/news.lua @@ -51,7 +51,9 @@ function M.open(file, opts) end file = plugin.dir .. "/" .. file elseif opts.rtp then - file = vim.api.nvim_get_runtime_file(file, false)[1] + -- first check if file exists in VIMRUNTIME, then check the full runtimepath + local path = vim.env.VIMRUNTIME .. "/" .. file --[[@as string]] + file = vim.uv.fs_stat(path) and path or vim.api.nvim_get_runtime_file(file, false)[1] end if not file then From 244af66f8b4e376d60c6604f9b3fd758165f5799 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Sun, 1 Mar 2026 09:30:39 +0100 Subject: [PATCH 02/46] fix(leap): update urls to new leap.nvim repo. Fixes #6958 --- lua/lazyvim/plugins/extras/editor/leap.lua | 4 ++-- lua/lazyvim/util/plugin.lua | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lua/lazyvim/plugins/extras/editor/leap.lua b/lua/lazyvim/plugins/extras/editor/leap.lua index 3fe4c5e7..6e82423c 100644 --- a/lua/lazyvim/plugins/extras/editor/leap.lua +++ b/lua/lazyvim/plugins/extras/editor/leap.lua @@ -4,7 +4,7 @@ return { -- easily jump to any location and enhanced f/t motions for Leap { - "ggandor/flit.nvim", + url = "https://codeberg.org/andyg/leap.nvim.git", enabled = true, keys = function() ---@type LazyKeysSpec[] @@ -17,7 +17,7 @@ return { opts = { labeled_modes = "nx" }, }, { - "ggandor/leap.nvim", + url = "https://codeberg.org/andyg/leap.nvim.git", enabled = true, keys = { { "s", mode = { "n", "x", "o" }, desc = "Leap Forward to" }, diff --git a/lua/lazyvim/util/plugin.lua b/lua/lazyvim/util/plugin.lua index 02e6834f..696665e6 100644 --- a/lua/lazyvim/util/plugin.lua +++ b/lua/lazyvim/util/plugin.lua @@ -42,6 +42,7 @@ M.renames = { ["markdown.nvim"] = "render-markdown.nvim", ["williamboman/mason.nvim"] = "mason-org/mason.nvim", ["williamboman/mason-lspconfig.nvim"] = "mason-org/mason-lspconfig.nvim", + ["ggandor/leap.nvim"] = "https://codeberg.org/andyg/leap.nvim.git", } function M.save_core() From a4e19e9c9c939c1a3fc2f30ffefe37311d3ecadf Mon Sep 17 00:00:00 2001 From: Iordanis Petkakis <12776461+dpetka2001@users.noreply.github.com> Date: Sun, 1 Mar 2026 10:31:44 +0200 Subject: [PATCH 03/46] fix(util.lsp): `LazyVim.lsp.execute` only request single client (#6904) ## Description `LazyVim.lsp.execute` uses `vim.lsp.buf_request` which sends the request to all attached clients. `LazyVim.lsp.execute` seems to me to be the equivalent of [vim.lsp.buf.execute_command](https://github.com/neovim/neovim/blob/922816877febf397fe854f01d8013a510d73f1d2/runtime/lua/vim/lsp/buf.lua#L1366-L1376), but adds the option to also open in Trouble. Otherwise the request is being made the same way. This command will be deprecated in 0.12 and it's advised to use `client:exec_cmd` instead. Since LazyVim supports Neovim >=0.11.2, it makes sense to refactor the corresponding codeblock and use `client:cmd_exec` instead (it's already available in Neovim 0.11). I only changed the necessary parts where `vim.lsp.buf_request` was being used and not Trouble (when `opts.open = true`), since I'm not familiar with its codebase. That's also why I went for extending `params` in the `else` branch instead of adding `title` into original `params`, since I didn't know how Trouble will react to this change. Not sure if maybe there also needs to be some change there. ## Related Issue(s) Fixes #6900 ## Screenshots ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- lua/lazyvim/plugins/extras/lang/elixir.lua | 4 ++++ lua/lazyvim/plugins/extras/lang/typescript.lua | 6 +++++- lua/lazyvim/plugins/extras/lang/typst.lua | 2 ++ lua/lazyvim/util/lsp.lua | 12 +++++++++++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lua/lazyvim/plugins/extras/lang/elixir.lua b/lua/lazyvim/plugins/extras/lang/elixir.lua index 289e50df..1be9c846 100644 --- a/lua/lazyvim/plugins/extras/lang/elixir.lua +++ b/lua/lazyvim/plugins/extras/lang/elixir.lua @@ -16,6 +16,8 @@ return { function() local params = vim.lsp.util.make_position_params() LazyVim.lsp.execute({ + title = "toPipe", + filter = "elixirls", command = "manipulatePipes:serverid", arguments = { "toPipe", params.textDocument.uri, params.position.line, params.position.character }, }) @@ -27,6 +29,8 @@ return { function() local params = vim.lsp.util.make_position_params() LazyVim.lsp.execute({ + title = "fromPipe", + filter = "elixirls", command = "manipulatePipes:serverid", arguments = { "fromPipe", params.textDocument.uri, params.position.line, params.position.character }, }) diff --git a/lua/lazyvim/plugins/extras/lang/typescript.lua b/lua/lazyvim/plugins/extras/lang/typescript.lua index 101b83f2..8acbc46a 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript.lua @@ -113,7 +113,11 @@ return { { "cV", function() - LazyVim.lsp.execute({ command = "typescript.selectTypeScriptVersion" }) + LazyVim.lsp.execute({ + title = "Select TypeScript Version", + filter = "vtsls", + command = "typescript.selectTypeScriptVersion", + }) end, desc = "Select TS workspace version", }, diff --git a/lua/lazyvim/plugins/extras/lang/typst.lua b/lua/lazyvim/plugins/extras/lang/typst.lua index 099a6861..9f605351 100644 --- a/lua/lazyvim/plugins/extras/lang/typst.lua +++ b/lua/lazyvim/plugins/extras/lang/typst.lua @@ -24,6 +24,8 @@ return { local buf_name = vim.api.nvim_buf_get_name(0) local file_name = vim.fn.fnamemodify(buf_name, ":t") LazyVim.lsp.execute({ + title = "Pin Main", + filter = "tinymist", command = "tinymist.pinMain", arguments = { buf_name }, }) diff --git a/lua/lazyvim/util/lsp.lua b/lua/lazyvim/util/lsp.lua index 90a6a3c7..83a39cd9 100644 --- a/lua/lazyvim/util/lsp.lua +++ b/lua/lazyvim/util/lsp.lua @@ -70,9 +70,18 @@ M.action = setmetatable({}, { ---@class LspCommand: lsp.ExecuteCommandParams ---@field open? boolean ---@field handler? lsp.Handler +---@field filter? string|vim.lsp.get_clients.Filter +---@field title? string ---@param opts LspCommand function M.execute(opts) + local filter = opts.filter or {} + filter = type(filter) == "string" and { name = filter } or filter + local buf = vim.api.nvim_get_current_buf() + + ---@cast filter vim.lsp.get_clients.Filter + local client = vim.lsp.get_clients(LazyVim.merge({}, filter, { bufnr = buf }))[1] + local params = { command = opts.command, arguments = opts.arguments, @@ -83,7 +92,8 @@ function M.execute(opts) params = params, }) else - return vim.lsp.buf_request(0, "workspace/executeCommand", params, opts.handler) + vim.list_extend(params, { title = opts.title }) + return client:exec_cmd(params, { bufnr = buf }, opts.handler) end end From 27824d79a952c54cd9d93c85a699543e4a031dd4 Mon Sep 17 00:00:00 2001 From: akioweh <0@akioweh.com> Date: Sun, 1 Mar 2026 08:33:20 +0000 Subject: [PATCH 04/46] fix(editor.overseer): migrate to v2 (#6907) ## Description Overseer.nvim recently-ish released v2. This PR updates the extras config according to the breaking changes. A few commands were removed and the `bindings` config key was renamed to `keymaps`. I've also taken the liberty of marking the plugin as not lazy since it lazy-loads itself. The impact on startup is ~<1ms, which I think is acceptable over lazy.nvim command/keymap listener overhead, but this is open to discussion :shrug: ## Related Issue(s) fixes #6876 ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- .../plugins/extras/editor/overseer.lua | 28 ++++--------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/lua/lazyvim/plugins/extras/editor/overseer.lua b/lua/lazyvim/plugins/extras/editor/overseer.lua index 373c0029..c29a13a4 100644 --- a/lua/lazyvim/plugins/extras/editor/overseer.lua +++ b/lua/lazyvim/plugins/extras/editor/overseer.lua @@ -8,29 +8,20 @@ return { }, { "stevearc/overseer.nvim", + lazy = false, -- plugin is self-lazy-loading cmd = { "OverseerOpen", "OverseerClose", "OverseerToggle", - "OverseerSaveBundle", - "OverseerLoadBundle", - "OverseerDeleteBundle", - "OverseerRunCmd", "OverseerRun", - "OverseerInfo", - "OverseerBuild", - "OverseerQuickAction", "OverseerTaskAction", - "OverseerClearCache", }, opts = { dap = false, task_list = { - bindings = { - [""] = false, + keymaps = { [""] = false, [""] = false, - [""] = false, }, }, form = { @@ -38,11 +29,6 @@ return { winblend = 0, }, }, - confirm = { - win_opts = { - winblend = 0, - }, - }, task_win = { win_opts = { winblend = 0, @@ -51,13 +37,9 @@ return { }, -- stylua: ignore keys = { - { "ow", "OverseerToggle", desc = "Task list" }, - { "oo", "OverseerRun", desc = "Run task" }, - { "oq", "OverseerQuickAction", desc = "Action recent task" }, - { "oi", "OverseerInfo", desc = "Overseer Info" }, - { "ob", "OverseerBuild", desc = "Task builder" }, - { "ot", "OverseerTaskAction", desc = "Task action" }, - { "oc", "OverseerClearCache", desc = "Clear cache" }, + { "ow", "OverseerToggle!", desc = "Task list" }, + { "oo", "OverseerRun", desc = "Run task" }, + { "ot", "OverseerTaskAction", desc = "Task action" }, }, }, { From ecd31f844e1004165608b32d92adcd3c6c7d2d80 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Sun, 1 Mar 2026 10:04:26 +0100 Subject: [PATCH 05/46] test(extras): handle plugins using `url` instead of short format Co-Authored-By: Claude Opus 4.6 --- tests/extras/extra_spec.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/extras/extra_spec.lua b/tests/extras/extra_spec.lua index f383c4b9..14f8d741 100644 --- a/tests/extras/extra_spec.lua +++ b/tests/extras/extra_spec.lua @@ -77,10 +77,12 @@ describe("Extra", function() it("it has no renamed plugins", function() for _, p in pairs(spec.plugins) do local short_url = p[1] - assert( - not LazyVim.plugin.renames[short_url], - "Plugin " .. short_url .. " has been renamed to " .. (LazyVim.plugin.renames[short_url] or "") - ) + if short_url then + assert( + not LazyVim.plugin.renames[short_url], + "Plugin " .. short_url .. " has been renamed to " .. (LazyVim.plugin.renames[short_url] or "") + ) + end end end) From 8652c9570377678a78ecb19dbd33695e0e4ec4fc Mon Sep 17 00:00:00 2001 From: Iordanis Petkakis <12776461+dpetka2001@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:06:18 +0200 Subject: [PATCH 06/46] fix(vtsls): remove redundant deno logic, upstreamed in `nvim-lspconfig` (#7011) ## Description Since https://github.com/neovim/nvim-lspconfig/pull/4304 `nvim-lspconfig` has inherent deno logic to disambiguate between deno/non-deno projects. I believe it'd be better to remove the logic from LazyVim, since it might lead to issues because of different behavior compared to `nvim-lspconfig` defaults (whose logic doesn't only rely on the existence of `deno/json`, but also looks for lock files and takes into account which is the largest path with regards to the found pattern files). It'd be better for users to change `root_dir` themselves if they don't agree with the inherent logic. ## Related Issue(s) None ## Screenshots ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- .../plugins/extras/lang/typescript.lua | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/lua/lazyvim/plugins/extras/lang/typescript.lua b/lua/lazyvim/plugins/extras/lang/typescript.lua index 8acbc46a..bc91e830 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript.lua @@ -136,28 +136,6 @@ return { return true end, vtsls = function(_, opts) - if vim.lsp.config.denols and vim.lsp.config.vtsls then - ---@param server string - local resolve = function(server) - local markers, root_dir = vim.lsp.config[server].root_markers, vim.lsp.config[server].root_dir - vim.lsp.config(server, { - root_dir = function(bufnr, on_dir) - local is_deno = vim.fs.root(bufnr, { "deno.json", "deno.jsonc" }) ~= nil - if is_deno == (server == "denols") then - if root_dir then - return root_dir(bufnr, on_dir) - elseif type(markers) == "table" then - local root = vim.fs.root(bufnr, markers) - return root and on_dir(root) - end - end - end, - }) - end - resolve("denols") - resolve("vtsls") - end - Snacks.util.lsp.on({ name = "vtsls" }, function(buffer, client) client.commands["_typescript.moveToFileRefactoring"] = function(command, ctx) ---@type string, string, lsp.Range From 92607e79e09a2761d930877a09edc00438b97fc3 Mon Sep 17 00:00:00 2001 From: Iordanis Petkakis <12776461+dpetka2001@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:08:09 +0200 Subject: [PATCH 07/46] fix(treesitter): remove deleted jsonc parser (#6848) ## Description https://github.com/nvim-treesitter/nvim-treesitter/commit/d2350758b39dce3593ffa8b058f863ea4cfa5b0e removed parsers not hosted on Github, `jsonc` among them. Remove it from LazyVim as well. On a fresh new installation, there's no problem and it doesn't even install, but on existing installation you get an error when updating about parser not available. 2025-12-07_11-24 ## Related Issue(s) None ## Screenshots ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- lua/lazyvim/plugins/treesitter.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/lazyvim/plugins/treesitter.lua b/lua/lazyvim/plugins/treesitter.lua index 4497ff1c..eb3ebf61 100644 --- a/lua/lazyvim/plugins/treesitter.lua +++ b/lua/lazyvim/plugins/treesitter.lua @@ -37,7 +37,6 @@ return { "javascript", "jsdoc", "json", - "jsonc", "lua", "luadoc", "luap", From 16713e6e1200eb90ad4b4a394bb7254fb5612484 Mon Sep 17 00:00:00 2001 From: Iordanis Petkakis <12776461+dpetka2001@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:11:09 +0200 Subject: [PATCH 08/46] fix(treesitter): fix `]c` textobject mappings when in diff mode (#6911) ## Description It seems that after https://github.com/LazyVim/LazyVim/commit/5985ca0cf1a0c1ddee8b2b718c730f988cec7001 the default `]c` Neovim mapping in diff mode broke. This is an attempt to fix that. ## Related Issue(s) None, rather discussion #6910. ## Screenshots ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- lua/lazyvim/plugins/treesitter.lua | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lua/lazyvim/plugins/treesitter.lua b/lua/lazyvim/plugins/treesitter.lua index eb3ebf61..6de91b30 100644 --- a/lua/lazyvim/plugins/treesitter.lua +++ b/lua/lazyvim/plugins/treesitter.lua @@ -180,15 +180,16 @@ return { local desc = table.concat(parts, " or ") 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") - if not (vim.wo.diff and key:find("[cC]")) then - vim.keymap.set({ "n", "x", "o" }, key, function() - require("nvim-treesitter-textobjects.move")[method](query, "textobjects") - end, { - buffer = buf, - desc = desc, - silent = true, - }) - end + vim.keymap.set({ "n", "x", "o" }, key, function() + if vim.wo.diff and key:find("[cC]") then + return vim.cmd("normal! " .. key) + end + require("nvim-treesitter-textobjects.move")[method](query, "textobjects") + end, { + buffer = buf, + desc = desc, + silent = true, + }) end end end From 03f1293e33541073288f23abdaf581a8e0dec4c4 Mon Sep 17 00:00:00 2001 From: Iordanis Petkakis <12776461+dpetka2001@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:12:58 +0200 Subject: [PATCH 09/46] fix(util.lsp): pass `formatters_by_ft` to `opts` (#6894) ## Description Here https://github.com/LazyVim/LazyVim/blob/c64a61734fc9d45470a72603395c02137802bc6f/lua/lazyvim/util/lsp.lua#L50 we call directly `conform.format` with our specific options. `conform.nvim` also allows passing options such as `lsp_format` directly to `formatter_by_ft` as also can be seen [here](https://github.com/stevearc/conform.nvim/blob/5420c4b5ea0aeb99c09cfbd4fd0b70d257b44f25/doc/conform.txt#L20-L21). Those options are not passed when we call `conform.format(opts)` in the LSP formatter. So, we add these options. Also, fix the correct name for general format options, since it had been changed at some time in `conform.nvim` and that change made it to the plugin spec, but not here. ## Related Issue(s) Fixes #6893 ## Screenshots ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- lua/lazyvim/util/lsp.lua | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lua/lazyvim/util/lsp.lua b/lua/lazyvim/util/lsp.lua index 83a39cd9..ff248599 100644 --- a/lua/lazyvim/util/lsp.lua +++ b/lua/lazyvim/util/lsp.lua @@ -35,18 +35,14 @@ end ---@param opts? lsp.Client.format function M.format(opts) - opts = vim.tbl_deep_extend( - "force", - {}, - opts or {}, - LazyVim.opts("nvim-lspconfig").format or {}, - LazyVim.opts("conform.nvim").format or {} - ) + opts = vim.tbl_deep_extend("force", {}, opts or {}, LazyVim.opts("nvim-lspconfig").format or {}) local ok, conform = pcall(require, "conform") -- use conform for formatting with LSP when available, -- since it has better format diffing if ok then - opts.formatters = {} + -- It should be `nil`, otherwise it doesn't fetch options from `formatters_by_ft`, + -- see https://github.com/stevearc/conform.nvim/blob/5420c4b5ea0aeb99c09cfbd4fd0b70d257b44f25/lua/conform/init.lua#L417-L418 + opts.formatters = nil conform.format(opts) else vim.lsp.buf.format(opts) From 730b69114d56834f4499fd3e5aecf18920234c39 Mon Sep 17 00:00:00 2001 From: Iordanis Petkakis <12776461+dpetka2001@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:13:30 +0200 Subject: [PATCH 10/46] fix(lang.clang): fix `clangd_extensions.nvim` (#6804) ## Description `clangd_extensions.nvim` does not seem to take `server` key any more, which was used to setup the plugin with clangd `cmd`, `init_options` etc. Instead you only need to configure the clangd server via lspconfig and the plugin separately according to my understanding. Remove the unnecessary `opts.setup` which also requires the plugin itself and loads it and make the plugin lazy-loaded on c/c++ files only. References: - https://github.com/p00f/clangd_extensions.nvim#configuration - https://github.com/p00f/clangd_extensions.nvim/issues/49#issuecomment-1719654413 PS: I don't do C/C++, so testers would be welcome. ## Related Issue(s) Fixes #6800 ## Screenshots ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- lua/lazyvim/plugins/extras/lang/clangd.lua | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lua/lazyvim/plugins/extras/lang/clangd.lua b/lua/lazyvim/plugins/extras/lang/clangd.lua index cac83194..0dc3a3f5 100644 --- a/lua/lazyvim/plugins/extras/lang/clangd.lua +++ b/lua/lazyvim/plugins/extras/lang/clangd.lua @@ -23,8 +23,7 @@ return { { "p00f/clangd_extensions.nvim", - lazy = true, - config = function() end, + ft = { "c", "cpp", "objc", "objcpp" }, opts = { inlay_hints = { inline = false, @@ -94,13 +93,6 @@ return { }, }, }, - setup = { - clangd = function(_, opts) - local clangd_ext_opts = LazyVim.opts("clangd_extensions.nvim") - require("clangd_extensions").setup(vim.tbl_deep_extend("force", clangd_ext_opts or {}, { server = opts })) - return false - end, - }, }, }, From e77d4ab0d6574efb7142ec40f4f5dcff750a3ee9 Mon Sep 17 00:00:00 2001 From: Talles Borges Date: Sun, 1 Mar 2026 06:31:41 -0300 Subject: [PATCH 11/46] fix(fzf): correct git_diff description from 'hunks' to 'files' (#6983) Fixes #6960 `FzfLua git_diff` runs `git diff --name-only` which lists changed **files**, not hunks. Updated the description from `"Git Diff (hunks)"` to `"Git Diff (files)"` to accurately reflect the command behavior. --- lua/lazyvim/plugins/extras/editor/fzf.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/lazyvim/plugins/extras/editor/fzf.lua b/lua/lazyvim/plugins/extras/editor/fzf.lua index f63716c5..4f703405 100644 --- a/lua/lazyvim/plugins/extras/editor/fzf.lua +++ b/lua/lazyvim/plugins/extras/editor/fzf.lua @@ -227,7 +227,7 @@ return { { "fR", LazyVim.pick("oldfiles", { cwd = vim.uv.cwd() }), desc = "Recent (cwd)" }, -- git { "gc", "FzfLua git_commits", desc = "Commits" }, - { "gd", "FzfLua git_diff", desc = "Git Diff (hunks)" }, + { "gd", "FzfLua git_diff", desc = "Git Diff (files)" }, { "gl", "FzfLua git_commits", desc = "Commits" }, { "gs", "FzfLua git_status", desc = "Status" }, { "gS", "FzfLua git_stash", desc = "Git Stash" }, From 3f91371e21389f75997ce1547912e12fe7916e3e Mon Sep 17 00:00:00 2001 From: plsplsplslol <69408275+plsplsplslol@users.noreply.github.com> Date: Sun, 1 Mar 2026 01:32:37 -0800 Subject: [PATCH 12/46] docs(ui): fix typo (#6978) ## Description this extra disables scope, not scroll ## Related Issue(s) ## Screenshots ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- lua/lazyvim/plugins/extras/ui/mini-indentscope.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/lazyvim/plugins/extras/ui/mini-indentscope.lua b/lua/lazyvim/plugins/extras/ui/mini-indentscope.lua index e043432c..8c25dfa7 100644 --- a/lua/lazyvim/plugins/extras/ui/mini-indentscope.lua +++ b/lua/lazyvim/plugins/extras/ui/mini-indentscope.lua @@ -55,7 +55,7 @@ return { }, }, - -- disable snacks scroll when mini-indentscope is enabled + -- disable snacks scope when mini-indentscope is enabled { "snacks.nvim", opts = { From b2917bd3bfe61c40e686f5a2c20f540430945b73 Mon Sep 17 00:00:00 2001 From: Frederick Zhang Date: Sun, 1 Mar 2026 20:33:07 +1100 Subject: [PATCH 13/46] fix(python): set venv-selector.nvim override_notify = false (#6936) ## Description This is a new option in venv-selector.nvim which stops it from overriding vim.notify, so that it no longer interferes with noice.nvim. See also [1]. [1] https://github.com/linux-cultist/venv-selector.nvim/issues/240 ## Related Issue(s) N/A ## Screenshots N/A ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- lua/lazyvim/plugins/extras/lang/python.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/lazyvim/plugins/extras/lang/python.lua b/lua/lazyvim/plugins/extras/lang/python.lua index bfe9e210..eb0bd5a8 100644 --- a/lua/lazyvim/plugins/extras/lang/python.lua +++ b/lua/lazyvim/plugins/extras/lang/python.lua @@ -114,6 +114,7 @@ return { opts = { options = { notify_user_on_venv_activation = true, + override_notify = false, }, }, -- Call config for Python files and load the cached venv automatically From 87c002789220d922bb94637c690b444bd1ba5611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ph=C3=BAc=20H=2E=20L=C3=AA=20Kh=E1=BA=AFc?= Date: Sun, 1 Mar 2026 16:35:14 +0700 Subject: [PATCH 14/46] feat(dap): close dap-float window with `q`. (#6884) ## Description nvim-dap-ui's widget window to preview value of object under the cursor has ftype `dap-float`. Include it so it can be closed quickly like other popup windows. ## Related Issue(s) ## Screenshots ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- lua/lazyvim/config/autocmds.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/lazyvim/config/autocmds.lua b/lua/lazyvim/config/autocmds.lua index a86594a3..a0b058a6 100644 --- a/lua/lazyvim/config/autocmds.lua +++ b/lua/lazyvim/config/autocmds.lua @@ -56,6 +56,7 @@ vim.api.nvim_create_autocmd("FileType", { pattern = { "PlenaryTestPopup", "checkhealth", + "dap-float", "dbout", "gitsigns-blame", "grug-far", From a50072fa16cfc1f00b1ae282150bc667f1d1e096 Mon Sep 17 00:00:00 2001 From: Chomba Date: Sun, 1 Mar 2026 12:36:15 +0300 Subject: [PATCH 15/46] feat(bufferline): add bj keymap for BufferLinePick (#6968) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Adds `bj` keymap to quickly pick a buffer using BufferLinePick ## Motivation BufferLinePick provides a great UX for quickly jumping to buffers by letter key, similar to LunarVim's buffer picker. This keymap makes it easily discoverable. ## Changes - Added `bj` → `:BufferLinePick` in bufferline plugin config ## Testing - Tested locally with multiple buffers open - Press `bj`, letter labels appear on tabs, press letter to jump --- lua/lazyvim/plugins/ui.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/lazyvim/plugins/ui.lua b/lua/lazyvim/plugins/ui.lua index 23afdc39..041648b7 100644 --- a/lua/lazyvim/plugins/ui.lua +++ b/lua/lazyvim/plugins/ui.lua @@ -15,6 +15,7 @@ return { { "]b", "BufferLineCycleNext", desc = "Next Buffer" }, { "[B", "BufferLineMovePrev", desc = "Move buffer prev" }, { "]B", "BufferLineMoveNext", desc = "Move buffer next" }, + { "bj", "BufferLinePick", desc = "Pick Buffer" }, }, opts = { options = { From fca0af57cc3851b14f96a795a9c9bfafc5096dd1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 10:37:36 +0100 Subject: [PATCH 16/46] chore(main): release 15.14.0 (#6738) :robot: I have created a release *beep* *boop* --- ## [15.14.0](https://github.com/LazyVim/LazyVim/compare/v15.13.0...v15.14.0) (2026-03-01) ### Features * **bufferline:** add <leader>bj keymap for BufferLinePick ([#6968](https://github.com/LazyVim/LazyVim/issues/6968)) ([a50072f](https://github.com/LazyVim/LazyVim/commit/a50072fa16cfc1f00b1ae282150bc667f1d1e096)) * **dap:** close dap-float window with `q`. ([#6884](https://github.com/LazyVim/LazyVim/issues/6884)) ([87c0027](https://github.com/LazyVim/LazyVim/commit/87c002789220d922bb94637c690b444bd1ba5611)) * **treesitter:** support query table in treesitter-textobjects mappings ([#6736](https://github.com/LazyVim/LazyVim/issues/6736)) ([42c9f71](https://github.com/LazyVim/LazyVim/commit/42c9f7152b9bd1a4f739b115390370c208dc2a55)) ### Bug Fixes * **editor.overseer:** migrate to v2 ([#6907](https://github.com/LazyVim/LazyVim/issues/6907)) ([27824d7](https://github.com/LazyVim/LazyVim/commit/27824d79a952c54cd9d93c85a699543e4a031dd4)) * **fzf:** correct git_diff description from 'hunks' to 'files' ([#6983](https://github.com/LazyVim/LazyVim/issues/6983)) ([e77d4ab](https://github.com/LazyVim/LazyVim/commit/e77d4ab0d6574efb7142ec40f4f5dcff750a3ee9)) * **lang.clang:** fix `clangd_extensions.nvim` ([#6804](https://github.com/LazyVim/LazyVim/issues/6804)) ([730b691](https://github.com/LazyVim/LazyVim/commit/730b69114d56834f4499fd3e5aecf18920234c39)) * **leap:** update urls to new leap.nvim repo. Fixes [#6958](https://github.com/LazyVim/LazyVim/issues/6958) ([244af66](https://github.com/LazyVim/LazyVim/commit/244af66f8b4e376d60c6604f9b3fd758165f5799)) * **news:** resolve news.txt from $VIMRUNTIME first ([60fea62](https://github.com/LazyVim/LazyVim/commit/60fea6236e342e1f4aa34d078461746d5f587c74)), closes [#7019](https://github.com/LazyVim/LazyVim/issues/7019) * **python:** set venv-selector.nvim override_notify = false ([#6936](https://github.com/LazyVim/LazyVim/issues/6936)) ([b2917bd](https://github.com/LazyVim/LazyVim/commit/b2917bd3bfe61c40e686f5a2c20f540430945b73)) * **terminal:** add -NoProfile to powershell shellcmdflag ([#6757](https://github.com/LazyVim/LazyVim/issues/6757)) ([a507822](https://github.com/LazyVim/LazyVim/commit/a507822c0f67df661d1411f9274a65ca9cc832f5)) * **terminal:** partially revert previous mappings ([#6770](https://github.com/LazyVim/LazyVim/issues/6770)) ([c64a617](https://github.com/LazyVim/LazyVim/commit/c64a61734fc9d45470a72603395c02137802bc6f)) * **treesitter:** fix `]c` textobject mappings when in diff mode ([#6911](https://github.com/LazyVim/LazyVim/issues/6911)) ([16713e6](https://github.com/LazyVim/LazyVim/commit/16713e6e1200eb90ad4b4a394bb7254fb5612484)) * **treesitter:** remove deleted jsonc parser ([#6848](https://github.com/LazyVim/LazyVim/issues/6848)) ([92607e7](https://github.com/LazyVim/LazyVim/commit/92607e79e09a2761d930877a09edc00438b97fc3)) * **util.lsp:** `LazyVim.lsp.execute` only request single client ([#6904](https://github.com/LazyVim/LazyVim/issues/6904)) ([a4e19e9](https://github.com/LazyVim/LazyVim/commit/a4e19e9c9c939c1a3fc2f30ffefe37311d3ecadf)) * **util.lsp:** pass `formatters_by_ft` to `opts` ([#6894](https://github.com/LazyVim/LazyVim/issues/6894)) ([03f1293](https://github.com/LazyVim/LazyVim/commit/03f1293e33541073288f23abdaf581a8e0dec4c4)) * **vtsls:** remove redundant deno logic, upstreamed in `nvim-lspconfig` ([#7011](https://github.com/LazyVim/LazyVim/issues/7011)) ([8652c95](https://github.com/LazyVim/LazyVim/commit/8652c9570377678a78ecb19dbd33695e0e4ec4fc)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/.release-please-manifest.json | 2 +- CHANGELOG.md | 26 ++++++++++++++++++++++++++ lua/lazyvim/config/init.lua | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.github/.release-please-manifest.json b/.github/.release-please-manifest.json index 27277755..538e599a 100644 --- a/.github/.release-please-manifest.json +++ b/.github/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "15.13.0" + ".": "15.14.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 24045345..f5e25695 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [15.14.0](https://github.com/LazyVim/LazyVim/compare/v15.13.0...v15.14.0) (2026-03-01) + + +### Features + +* **bufferline:** add <leader>bj keymap for BufferLinePick ([#6968](https://github.com/LazyVim/LazyVim/issues/6968)) ([a50072f](https://github.com/LazyVim/LazyVim/commit/a50072fa16cfc1f00b1ae282150bc667f1d1e096)) +* **dap:** close dap-float window with `q`. ([#6884](https://github.com/LazyVim/LazyVim/issues/6884)) ([87c0027](https://github.com/LazyVim/LazyVim/commit/87c002789220d922bb94637c690b444bd1ba5611)) +* **treesitter:** support query table in treesitter-textobjects mappings ([#6736](https://github.com/LazyVim/LazyVim/issues/6736)) ([42c9f71](https://github.com/LazyVim/LazyVim/commit/42c9f7152b9bd1a4f739b115390370c208dc2a55)) + + +### Bug Fixes + +* **editor.overseer:** migrate to v2 ([#6907](https://github.com/LazyVim/LazyVim/issues/6907)) ([27824d7](https://github.com/LazyVim/LazyVim/commit/27824d79a952c54cd9d93c85a699543e4a031dd4)) +* **fzf:** correct git_diff description from 'hunks' to 'files' ([#6983](https://github.com/LazyVim/LazyVim/issues/6983)) ([e77d4ab](https://github.com/LazyVim/LazyVim/commit/e77d4ab0d6574efb7142ec40f4f5dcff750a3ee9)) +* **lang.clang:** fix `clangd_extensions.nvim` ([#6804](https://github.com/LazyVim/LazyVim/issues/6804)) ([730b691](https://github.com/LazyVim/LazyVim/commit/730b69114d56834f4499fd3e5aecf18920234c39)) +* **leap:** update urls to new leap.nvim repo. Fixes [#6958](https://github.com/LazyVim/LazyVim/issues/6958) ([244af66](https://github.com/LazyVim/LazyVim/commit/244af66f8b4e376d60c6604f9b3fd758165f5799)) +* **news:** resolve news.txt from $VIMRUNTIME first ([60fea62](https://github.com/LazyVim/LazyVim/commit/60fea6236e342e1f4aa34d078461746d5f587c74)), closes [#7019](https://github.com/LazyVim/LazyVim/issues/7019) +* **python:** set venv-selector.nvim override_notify = false ([#6936](https://github.com/LazyVim/LazyVim/issues/6936)) ([b2917bd](https://github.com/LazyVim/LazyVim/commit/b2917bd3bfe61c40e686f5a2c20f540430945b73)) +* **terminal:** add -NoProfile to powershell shellcmdflag ([#6757](https://github.com/LazyVim/LazyVim/issues/6757)) ([a507822](https://github.com/LazyVim/LazyVim/commit/a507822c0f67df661d1411f9274a65ca9cc832f5)) +* **terminal:** partially revert previous mappings ([#6770](https://github.com/LazyVim/LazyVim/issues/6770)) ([c64a617](https://github.com/LazyVim/LazyVim/commit/c64a61734fc9d45470a72603395c02137802bc6f)) +* **treesitter:** fix `]c` textobject mappings when in diff mode ([#6911](https://github.com/LazyVim/LazyVim/issues/6911)) ([16713e6](https://github.com/LazyVim/LazyVim/commit/16713e6e1200eb90ad4b4a394bb7254fb5612484)) +* **treesitter:** remove deleted jsonc parser ([#6848](https://github.com/LazyVim/LazyVim/issues/6848)) ([92607e7](https://github.com/LazyVim/LazyVim/commit/92607e79e09a2761d930877a09edc00438b97fc3)) +* **util.lsp:** `LazyVim.lsp.execute` only request single client ([#6904](https://github.com/LazyVim/LazyVim/issues/6904)) ([a4e19e9](https://github.com/LazyVim/LazyVim/commit/a4e19e9c9c939c1a3fc2f30ffefe37311d3ecadf)) +* **util.lsp:** pass `formatters_by_ft` to `opts` ([#6894](https://github.com/LazyVim/LazyVim/issues/6894)) ([03f1293](https://github.com/LazyVim/LazyVim/commit/03f1293e33541073288f23abdaf581a8e0dec4c4)) +* **vtsls:** remove redundant deno logic, upstreamed in `nvim-lspconfig` ([#7011](https://github.com/LazyVim/LazyVim/issues/7011)) ([8652c95](https://github.com/LazyVim/LazyVim/commit/8652c9570377678a78ecb19dbd33695e0e4ec4fc)) + ## [15.13.0](https://github.com/LazyVim/LazyVim/compare/v15.12.2...v15.13.0) (2025-11-01) diff --git a/lua/lazyvim/config/init.lua b/lua/lazyvim/config/init.lua index 562a0687..63355fcc 100644 --- a/lua/lazyvim/config/init.lua +++ b/lua/lazyvim/config/init.lua @@ -3,7 +3,7 @@ _G.LazyVim = require("lazyvim.util") ---@class LazyVimConfig: LazyVimOptions local M = {} -M.version = "15.13.0" -- x-release-please-version +M.version = "15.14.0" -- x-release-please-version LazyVim.config = M ---@class LazyVimOptions From d0fe8c896f4dca003e8d56e2091ee5ec7da7af75 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Sun, 1 Mar 2026 10:50:09 +0100 Subject: [PATCH 17/46] revert(lsp): revert changes for #6456. Closes #6779 --- lua/lazyvim/plugins/lsp/init.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lua/lazyvim/plugins/lsp/init.lua b/lua/lazyvim/plugins/lsp/init.lua index 540b6c5c..1a3708e1 100644 --- a/lua/lazyvim/plugins/lsp/init.lua +++ b/lua/lazyvim/plugins/lsp/init.lua @@ -2,7 +2,7 @@ return { -- lspconfig { "neovim/nvim-lspconfig", - event = "LazyFile", + event = { "BufReadPre", "BufNewFile" }, dependencies = { "mason.nvim", { "mason-org/mason-lspconfig.nvim", config = function() end }, @@ -150,7 +150,7 @@ return { return ret end, ---@param opts PluginLspOpts - config = vim.schedule_wrap(function(_, opts) + config = function(_, opts) -- setup autoformat LazyVim.format.register(LazyVim.lsp.formatter()) @@ -259,7 +259,7 @@ return { automatic_enable = { exclude = mason_exclude }, }) end - end), + end, }, -- cmdline tools and lsp servers From 31caef21fdf4009a7d5c8342a14b7d8b97be611d Mon Sep 17 00:00:00 2001 From: Rubin Bhandari Date: Sun, 1 Mar 2026 19:30:56 +0545 Subject: [PATCH 18/46] refactor(dial): use inbuilt augends (#7035) Dial now has built in augends for weekdays and Pythonic booleans [monaqa/dial.nvim#augend-alias](https://github.com/monaqa/dial.nvim#augend-alias) ## Description ## Related Issue(s) ## Screenshots ## Checklist - [ ] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- lua/lazyvim/plugins/extras/editor/dial.lua | 28 +++------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/lua/lazyvim/plugins/extras/editor/dial.lua b/lua/lazyvim/plugins/extras/editor/dial.lua index 7a9a76ae..3d9a18bf 100644 --- a/lua/lazyvim/plugins/extras/editor/dial.lua +++ b/lua/lazyvim/plugins/extras/editor/dial.lua @@ -53,20 +53,6 @@ return { cyclic = true, }) - local weekdays = augend.constant.new({ - elements = { - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - "Sunday", - }, - word = true, - cyclic = true, - }) - local months = augend.constant.new({ elements = { "January", @@ -86,15 +72,6 @@ return { cyclic = true, }) - local capitalized_boolean = augend.constant.new({ - elements = { - "True", - "False", - }, - word = true, - cyclic = true, - }) - return { dials_by_ft = { css = "css", @@ -116,11 +93,12 @@ return { augend.integer.alias.decimal_int, -- nonnegative and negative decimal number augend.integer.alias.hex, -- nonnegative hex number (0x01, 0x1a1f, etc.) augend.date.alias["%Y/%m/%d"], -- date (2022/02/19, etc.) + augend.constant.alias.en_weekday, -- Mon, Tue, ..., Sat, Sun + augend.constant.alias.en_weekday_full, -- Monday, Tuesday, ..., Saturday, Sunday ordinal_numbers, - weekdays, months, - capitalized_boolean, augend.constant.alias.bool, -- boolean value (true <-> false) + augend.constant.alias.Bool, -- boolean value (True <-> False) logical_alias, }, vue = { From 954d8746e5cf1266d93cf4210c00c1506f20423b Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Mon, 16 Mar 2026 18:11:45 +0100 Subject: [PATCH 19/46] fix(biome): use biome-check in conform that also fixes linting issues and sorts imports --- lua/lazyvim/plugins/extras/formatting/biome.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lua/lazyvim/plugins/extras/formatting/biome.lua b/lua/lazyvim/plugins/extras/formatting/biome.lua index 91e488ca..3d632978 100644 --- a/lua/lazyvim/plugins/extras/formatting/biome.lua +++ b/lua/lazyvim/plugins/extras/formatting/biome.lua @@ -1,3 +1,5 @@ +---@module "conform" + ---@diagnostic disable: inject-field if lazyvim_docs then -- Enable this option to avoid conflicts with Prettier. @@ -31,16 +33,16 @@ return { { "stevearc/conform.nvim", optional = true, - ---@param opts ConformOpts + ---@param opts conform.setupOpts opts = function(_, opts) opts.formatters_by_ft = opts.formatters_by_ft or {} for _, ft in ipairs(supported) do opts.formatters_by_ft[ft] = opts.formatters_by_ft[ft] or {} - table.insert(opts.formatters_by_ft[ft], "biome") + table.insert(opts.formatters_by_ft[ft], "biome-check") end opts.formatters = opts.formatters or {} - opts.formatters.biome = { + opts.formatters["biome-check"] = { require_cwd = true, } end, From 6055e59613b406f9c4312c95e56f604fb839a97e Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Mon, 16 Mar 2026 19:07:44 +0100 Subject: [PATCH 20/46] style: format --- lua/lazyvim/plugins/extras/ai/copilot.lua | 98 +++++++++++------------ 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/lua/lazyvim/plugins/extras/ai/copilot.lua b/lua/lazyvim/plugins/extras/ai/copilot.lua index 989d7d4f..0485b5a4 100644 --- a/lua/lazyvim/plugins/extras/ai/copilot.lua +++ b/lua/lazyvim/plugins/extras/ai/copilot.lua @@ -70,60 +70,58 @@ return { end, }, - vim.g.ai_cmp - and { - -- copilot cmp source + vim.g.ai_cmp and { + -- copilot cmp source + { + "hrsh7th/nvim-cmp", + optional = true, + dependencies = { -- this will only be evaluated if nvim-cmp is enabled { - "hrsh7th/nvim-cmp", - optional = true, - dependencies = { -- this will only be evaluated if nvim-cmp is enabled + "zbirenbaum/copilot-cmp", + opts = {}, + config = function(_, opts) + local copilot_cmp = require("copilot_cmp") + copilot_cmp.setup(opts) + -- attach cmp source whenever copilot attaches + -- fixes lazy-loading issues with the copilot cmp source + Snacks.util.lsp.on({ name = "copilot" }, function() + copilot_cmp._on_insert_enter({}) + end) + end, + specs = { { - "zbirenbaum/copilot-cmp", - opts = {}, - config = function(_, opts) - local copilot_cmp = require("copilot_cmp") - copilot_cmp.setup(opts) - -- attach cmp source whenever copilot attaches - -- fixes lazy-loading issues with the copilot cmp source - Snacks.util.lsp.on({ name = "copilot" }, function() - copilot_cmp._on_insert_enter({}) - end) - end, - specs = { - { - "hrsh7th/nvim-cmp", - optional = true, - ---@param opts cmp.ConfigSchema - opts = function(_, opts) - table.insert(opts.sources, 1, { - name = "copilot", - group_index = 1, - priority = 100, - }) - end, - }, - }, - }, - }, - }, - { - "saghen/blink.cmp", - optional = true, - dependencies = { "fang2hou/blink-copilot" }, - opts = { - sources = { - default = { "copilot" }, - providers = { - copilot = { + "hrsh7th/nvim-cmp", + optional = true, + ---@param opts cmp.ConfigSchema + opts = function(_, opts) + table.insert(opts.sources, 1, { name = "copilot", - module = "blink-copilot", - score_offset = 100, - async = true, - }, - }, + group_index = 1, + priority = 100, + }) + end, }, }, }, - } - or nil, + }, + }, + { + "saghen/blink.cmp", + optional = true, + dependencies = { "fang2hou/blink-copilot" }, + opts = { + sources = { + default = { "copilot" }, + providers = { + copilot = { + name = "copilot", + module = "blink-copilot", + score_offset = 100, + async = true, + }, + }, + }, + }, + }, + } or nil, } From 50159fe344d93329a569cee136c0323e48b0d3da Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 11:08:09 +0100 Subject: [PATCH 21/46] feat(sidekick): ctrl+. focuses sidekick, but when already inside sidekick, hides it --- lua/lazyvim/plugins/extras/ai/sidekick.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/lazyvim/plugins/extras/ai/sidekick.lua b/lua/lazyvim/plugins/extras/ai/sidekick.lua index d9c0c2e2..5131f688 100644 --- a/lua/lazyvim/plugins/extras/ai/sidekick.lua +++ b/lua/lazyvim/plugins/extras/ai/sidekick.lua @@ -82,8 +82,8 @@ return { { "a", "", desc = "+ai", mode = { "n", "v" } }, { "", - function() require("sidekick.cli").toggle() end, - desc = "Sidekick Toggle", + function() require("sidekick.cli").focus() end, + desc = "Sidekick Focus", mode = { "n", "t", "i", "x" }, }, { From b2830cfcc5c9c09ebbf9545beb3947a55ce89dbd Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 12:12:45 +0100 Subject: [PATCH 22/46] feat(biome): enable biome lsp for linting --- lua/lazyvim/plugins/extras/formatting/biome.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lua/lazyvim/plugins/extras/formatting/biome.lua b/lua/lazyvim/plugins/extras/formatting/biome.lua index 3d632978..0806e9a4 100644 --- a/lua/lazyvim/plugins/extras/formatting/biome.lua +++ b/lua/lazyvim/plugins/extras/formatting/biome.lua @@ -10,6 +10,7 @@ end local supported = { "astro", "css", + "scss", "graphql", -- "html", "javascript", @@ -30,6 +31,16 @@ return { opts = { ensure_installed = { "biome" } }, }, + { + "neovim/nvim-lspconfig", + opts = { + servers = { + ---@type lspconfig.settings.biome + biome = {}, + }, + }, + }, + { "stevearc/conform.nvim", optional = true, From e6f26f0f23e9cb4c6bcc351b06474f4863319aff Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 12:13:32 +0100 Subject: [PATCH 23/46] feat(typescript): set `vim.g.lazyvim_ts_lsp = "tsgo"` to use the much faster experimental lsp server --- .../plugins/extras/lang/typescript.lua | 71 +++++++++++++++++-- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/lua/lazyvim/plugins/extras/lang/typescript.lua b/lua/lazyvim/plugins/extras/lang/typescript.lua index bc91e830..9bb459c6 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript.lua @@ -1,3 +1,12 @@ +if lazyvim_docs then + -- LSP Server to use for TypeScript. + vim.g.lazyvim_ts_lsp = "vtsls" -- currently the default + -- Set to "tsgo" to use the new typescript-language-server implementation instead of tsserver. + vim.g.lazyvim_ts_lsp = "tsgo" +end + +local lsp = vim.g.lazyvim_ts_lsp or "vtsls" + return { recommended = function() return LazyVim.extras.wants({ @@ -19,13 +28,50 @@ return { opts = { -- make sure mason installs the server servers = { - --- @deprecated -- tsserver renamed to ts_ls but not yet released, so keep this for now - --- the proper approach is to check the nvim-lspconfig release version when it's released to determine the server name dynamically - tsserver = { - enabled = false, - }, - ts_ls = { - enabled = false, + ---@type lspconfig.settings.tsgo + tsgo = { + -- explicitly add default filetypes, so that we can extend + -- them in related extras + filetypes = { + "javascript", + "javascriptreact", + "javascript.jsx", + "typescript", + "typescriptreact", + "typescript.tsx", + }, + settings = { + typescript = { + inlayHints = { + parameterNames = { + enabled = "literals", + suppressWhenArgumentMatchesName = true, + }, + parameterTypes = { enabled = true }, + variableTypes = { enabled = true }, + propertyDeclarationTypes = { enabled = true }, + functionLikeReturnTypes = { enabled = true }, + enumMemberValues = { enabled = true }, + }, + }, + }, + keys = { + { + "co", + LazyVim.lsp.action["source.organizeImports"], + desc = "Organize Imports", + }, + { + "cu", + LazyVim.lsp.action["source.removeUnused.ts"], + desc = "Remove unused imports", + }, + { + "cD", + LazyVim.lsp.action["source.fixAll.ts"], + desc = "Fix all diagnostics", + }, + }, }, vtsls = { -- explicitly add default filetypes, so that we can extend @@ -194,6 +240,17 @@ return { }, }, + { + "neovim/nvim-lspconfig", + opts = function(_, opts) + local servers = { "tsserver", "ts_ls", "vtsls", "tsgo", lsp } + for _, server in ipairs(servers) do + opts.servers[server] = opts.servers[server] or {} + opts.servers[server].enabled = server == lsp + end + end, + }, + { "mfussenegger/nvim-dap", optional = true, From 36f594716bcb0bec84a05a6c55f702134d2e89c3 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 12:14:02 +0100 Subject: [PATCH 24/46] feat(lazydev): make lspconfig types available on word `lspconfig.settings` --- lua/lazyvim/plugins/coding.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/lazyvim/plugins/coding.lua b/lua/lazyvim/plugins/coding.lua index 7f6bb550..19bd2dad 100644 --- a/lua/lazyvim/plugins/coding.lua +++ b/lua/lazyvim/plugins/coding.lua @@ -82,6 +82,7 @@ return { { path = "LazyVim", words = { "LazyVim" } }, { path = "snacks.nvim", words = { "Snacks" } }, { path = "lazy.nvim", words = { "LazyVim" } }, + { path = "nvim-lspconfig", words = { "lspconfig.settings" } }, }, }, }, From 5450006ccdd7df341f7f60dded58ea4a87aa9c15 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 12:18:26 +0100 Subject: [PATCH 25/46] fix(biome): biome mason install is no longer needed --- lua/lazyvim/plugins/extras/formatting/biome.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lua/lazyvim/plugins/extras/formatting/biome.lua b/lua/lazyvim/plugins/extras/formatting/biome.lua index 0806e9a4..2f349774 100644 --- a/lua/lazyvim/plugins/extras/formatting/biome.lua +++ b/lua/lazyvim/plugins/extras/formatting/biome.lua @@ -26,10 +26,6 @@ local supported = { } return { - { - "mason-org/mason.nvim", - opts = { ensure_installed = { "biome" } }, - }, { "neovim/nvim-lspconfig", From 3b3d6493332798674fb7b82aea600bab18eaf311 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 14:39:02 +0100 Subject: [PATCH 26/46] fix(r): recommend for *.qmd instead of *qmd files --- lua/lazyvim/plugins/extras/lang/r.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/lazyvim/plugins/extras/lang/r.lua b/lua/lazyvim/plugins/extras/lang/r.lua index 5890b415..ef76c9e1 100644 --- a/lua/lazyvim/plugins/extras/lang/r.lua +++ b/lua/lazyvim/plugins/extras/lang/r.lua @@ -2,7 +2,7 @@ return { recommended = function() return LazyVim.extras.wants({ ft = "r", - root = { "*.R", "*.Rmd", "*qmd" }, + root = { "*.R", "*.Rmd", "*.qmd" }, }) end, { From fbf52d54967d262647842f3b51fd535d3b3645b5 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 15:58:39 +0100 Subject: [PATCH 27/46] refactor(typescript): move typescript to sub module init --- .../plugins/extras/lang/{typescript.lua => typescript/init.lua} | 0 lua/lazyvim/util/extras.lua | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename lua/lazyvim/plugins/extras/lang/{typescript.lua => typescript/init.lua} (100%) diff --git a/lua/lazyvim/plugins/extras/lang/typescript.lua b/lua/lazyvim/plugins/extras/lang/typescript/init.lua similarity index 100% rename from lua/lazyvim/plugins/extras/lang/typescript.lua rename to lua/lazyvim/plugins/extras/lang/typescript/init.lua diff --git a/lua/lazyvim/util/extras.lua b/lua/lazyvim/util/extras.lua index 6bc8eca2..06339a92 100644 --- a/lua/lazyvim/util/extras.lua +++ b/lua/lazyvim/util/extras.lua @@ -65,7 +65,7 @@ function M.get() if root then LazyVim.walk(root, function(path, name, type) if (type == "file" or type == "link") and name:match("%.lua$") then - name = path:sub(#root + 2, -5):gsub("/", ".") + name = path:sub(#root + 2, -5):gsub("/", "."):gsub("%.init$", "") local ok, extra = pcall(M.get_extra, source, source.module .. "." .. name) if ok then extras[#extras + 1] = extra From 242f0983de9fdb70f0d82057a8039e32bc171764 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 15:59:25 +0100 Subject: [PATCH 28/46] feat(biome): move biome extra from formatting.biome -> lang.typescript.biome --- .../plugins/extras/{formatting => lang/typescript}/biome.lua | 0 lua/lazyvim/util/plugin.lua | 1 + 2 files changed, 1 insertion(+) rename lua/lazyvim/plugins/extras/{formatting => lang/typescript}/biome.lua (100%) diff --git a/lua/lazyvim/plugins/extras/formatting/biome.lua b/lua/lazyvim/plugins/extras/lang/typescript/biome.lua similarity index 100% rename from lua/lazyvim/plugins/extras/formatting/biome.lua rename to lua/lazyvim/plugins/extras/lang/typescript/biome.lua diff --git a/lua/lazyvim/util/plugin.lua b/lua/lazyvim/util/plugin.lua index 696665e6..19e3d43c 100644 --- a/lua/lazyvim/util/plugin.lua +++ b/lua/lazyvim/util/plugin.lua @@ -28,6 +28,7 @@ M.deprecated_extras = { } M.renamed_extras = { ["lazyvim.plugins.extras.lang.omnisharp"] = "lazyvim.plugins.extras.lang.dotnet", + ["lazyvim.plugins.extras.formatting.biome"] = "lazyvim.plugins.extras.lang.typescript.biome", } M.deprecated_modules = {} From e54689ebdc5458cb30f4a48b954c710bb381cd01 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 16:06:44 +0100 Subject: [PATCH 29/46] feat(lsp): auto add organizeImport keymaps for LSPs that support it --- lua/lazyvim/plugins/extras/lang/python.lua | 17 +------- lua/lazyvim/plugins/extras/lang/svelte.lua | 10 +---- .../plugins/extras/lang/typescript/init.lua | 10 ----- lua/lazyvim/plugins/lsp/init.lua | 6 +++ lua/lazyvim/plugins/lsp/keymaps.lua | 40 +++++++++++++++++-- 5 files changed, 45 insertions(+), 38 deletions(-) diff --git a/lua/lazyvim/plugins/extras/lang/python.lua b/lua/lazyvim/plugins/extras/lang/python.lua index eb0bd5a8..b4cd10da 100644 --- a/lua/lazyvim/plugins/extras/lang/python.lua +++ b/lua/lazyvim/plugins/extras/lang/python.lua @@ -38,23 +38,8 @@ return { logLevel = "error", }, }, - keys = { - { - "co", - LazyVim.lsp.action["source.organizeImports"], - desc = "Organize Imports", - }, - }, - }, - ruff_lsp = { - keys = { - { - "co", - LazyVim.lsp.action["source.organizeImports"], - desc = "Organize Imports", - }, - }, }, + ruff_lsp = {}, }, setup = { [ruff] = function() diff --git a/lua/lazyvim/plugins/extras/lang/svelte.lua b/lua/lazyvim/plugins/extras/lang/svelte.lua index 4060e2f3..5acfc251 100644 --- a/lua/lazyvim/plugins/extras/lang/svelte.lua +++ b/lua/lazyvim/plugins/extras/lang/svelte.lua @@ -23,15 +23,7 @@ return { "neovim/nvim-lspconfig", opts = { servers = { - svelte = { - keys = { - { - "co", - LazyVim.lsp.action["source.organizeImports"], - desc = "Organize Imports", - }, - }, - }, + svelte = {}, }, }, }, diff --git a/lua/lazyvim/plugins/extras/lang/typescript/init.lua b/lua/lazyvim/plugins/extras/lang/typescript/init.lua index 9bb459c6..ffc3b06f 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript/init.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript/init.lua @@ -56,11 +56,6 @@ return { }, }, keys = { - { - "co", - LazyVim.lsp.action["source.organizeImports"], - desc = "Organize Imports", - }, { "cu", LazyVim.lsp.action["source.removeUnused.ts"], @@ -136,11 +131,6 @@ return { end, desc = "File References", }, - { - "co", - LazyVim.lsp.action["source.organizeImports"], - desc = "Organize Imports", - }, { "cM", LazyVim.lsp.action["source.addMissingImports.ts"], diff --git a/lua/lazyvim/plugins/lsp/init.lua b/lua/lazyvim/plugins/lsp/init.lua index 1a3708e1..a4c7709d 100644 --- a/lua/lazyvim/plugins/lsp/init.lua +++ b/lua/lazyvim/plugins/lsp/init.lua @@ -99,6 +99,12 @@ return { desc = "Next Reference", enabled = function() return Snacks.words.is_enabled() end }, { "", function() Snacks.words.jump(-vim.v.count1, true) end, has = "documentHighlight", desc = "Prev Reference", enabled = function() return Snacks.words.is_enabled() end }, + { + "co", + LazyVim.lsp.action["source.organizeImports"], + desc = "Organize Imports", + code_action = "source.organizeImports", + }, }, }, stylua = { enabled = false }, diff --git a/lua/lazyvim/plugins/lsp/keymaps.lua b/lua/lazyvim/plugins/lsp/keymaps.lua index 57280055..74fe971b 100644 --- a/lua/lazyvim/plugins/lsp/keymaps.lua +++ b/lua/lazyvim/plugins/lsp/keymaps.lua @@ -3,8 +3,8 @@ local M = {} ---@type LazyKeysLspSpec[]|nil M._keys = {} ----@alias LazyKeysLspSpec LazyKeysSpec|{has?:string|string[], enabled?:fun():boolean} ----@alias LazyKeysLsp LazyKeys|{has?:string|string[], enabled?:fun():boolean} +---@alias LazyKeysLspSpec LazyKeysSpec|{has?:string|string[], enabled?:(fun():boolean), code_action?:string} +---@alias LazyKeysLsp LazyKeys|{has?:string|string[], code_action?:string, enabled?:fun():boolean} ---@deprecated ---@return LazyKeysLspSpec[] @@ -44,7 +44,41 @@ function M.set(filter, spec) for _, keys in pairs(Keys.resolve(spec)) do ---@cast keys LazyKeysLsp local filters = {} ---@type vim.lsp.get_clients.Filter[] - if keys.has then + if keys.code_action then + filter = vim.tbl_extend("force", vim.deepcopy(filter), { method = "textDocument/codeAction" }) + filters[#filters + 1] = filter + + ---@param kinds? string[] + local function has(kinds) + for _, k in ipairs(kinds or {}) do + if type(k) == "string" and vim.startswith(k, keys.code_action) then + return true + end + end + end + + local enabled = keys.enabled + keys.enabled = function() + if type(enabled) == "function" and not enabled() then + return false + end + local clients = vim.lsp.get_clients(filter) + for _, client in ipairs(clients) do + -- check server cababilities first + if has(vim.tbl_get(client, "server_capabilities", "codeActionProvider", "codeActionKinds")) then + return true + end + -- check dynamic capabilities + local regs = client.dynamic_capabilities:get("codeActionProvider") + for _, reg in ipairs(regs or {}) do + if has(vim.tbl_get(reg, "registerOptions", "codeActionKinds")) then + return true + end + end + end + return false + end + elseif 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) From ad25b31e512892ca51a1fa3ffa96d1375c391039 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 16:09:12 +0100 Subject: [PATCH 30/46] fix(biome): added recommendation when root has biome config file --- lua/lazyvim/plugins/extras/lang/typescript/biome.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lua/lazyvim/plugins/extras/lang/typescript/biome.lua b/lua/lazyvim/plugins/extras/lang/typescript/biome.lua index 2f349774..77834990 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript/biome.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript/biome.lua @@ -26,6 +26,11 @@ local supported = { } return { + recommended = function() + return LazyVim.extras.wants({ + root = { "biome.json", "biome.jsonc" }, + }) + end, { "neovim/nvim-lspconfig", From 53f4eabd7723faba2d7c14afe53226d8c18bf16c Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 19:00:29 +0100 Subject: [PATCH 31/46] fix(typescript): remove keymaps for non-existing code actions --- .../plugins/extras/lang/typescript/init.lua | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lua/lazyvim/plugins/extras/lang/typescript/init.lua b/lua/lazyvim/plugins/extras/lang/typescript/init.lua index ffc3b06f..5d478314 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript/init.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript/init.lua @@ -55,18 +55,6 @@ return { }, }, }, - keys = { - { - "cu", - LazyVim.lsp.action["source.removeUnused.ts"], - desc = "Remove unused imports", - }, - { - "cD", - LazyVim.lsp.action["source.fixAll.ts"], - desc = "Fix all diagnostics", - }, - }, }, vtsls = { -- explicitly add default filetypes, so that we can extend @@ -136,11 +124,6 @@ return { LazyVim.lsp.action["source.addMissingImports.ts"], desc = "Add missing imports", }, - { - "cu", - LazyVim.lsp.action["source.removeUnused.ts"], - desc = "Remove unused imports", - }, { "cD", LazyVim.lsp.action["source.fixAll.ts"], From 76cb567e5c84500bc070755def9a7aa10c74ed20 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 19:01:02 +0100 Subject: [PATCH 32/46] refactor(lsp): cleaner support for code_actions --- lua/lazyvim/plugins/lsp/init.lua | 8 +++++- lua/lazyvim/plugins/lsp/keymaps.lua | 40 +++-------------------------- lua/lazyvim/util/lsp.lua | 17 ++++++++++++ 3 files changed, 27 insertions(+), 38 deletions(-) diff --git a/lua/lazyvim/plugins/lsp/init.lua b/lua/lazyvim/plugins/lsp/init.lua index a4c7709d..9a790b21 100644 --- a/lua/lazyvim/plugins/lsp/init.lua +++ b/lua/lazyvim/plugins/lsp/init.lua @@ -103,7 +103,13 @@ return { "co", LazyVim.lsp.action["source.organizeImports"], desc = "Organize Imports", - code_action = "source.organizeImports", + has = "codeAction", + enabled = function(buf) + local code_actions = vim.tbl_filter(function(action) + return action:find("^source%.organizeImports%.?$") + end, LazyVim.lsp.code_actions({ bufnr = buf })) + return #code_actions > 0 + end }, }, }, diff --git a/lua/lazyvim/plugins/lsp/keymaps.lua b/lua/lazyvim/plugins/lsp/keymaps.lua index 74fe971b..f4059471 100644 --- a/lua/lazyvim/plugins/lsp/keymaps.lua +++ b/lua/lazyvim/plugins/lsp/keymaps.lua @@ -3,8 +3,8 @@ local M = {} ---@type LazyKeysLspSpec[]|nil M._keys = {} ----@alias LazyKeysLspSpec LazyKeysSpec|{has?:string|string[], enabled?:(fun():boolean), code_action?:string} ----@alias LazyKeysLsp LazyKeys|{has?:string|string[], code_action?:string, enabled?:fun():boolean} +---@alias LazyKeysLspSpec LazyKeysSpec|{has?:string|string[], enabled?:(fun(buf:number):boolean)} +---@alias LazyKeysLsp LazyKeys|{has?:string|string[], enabled?:fun(buf:number):boolean} ---@deprecated ---@return LazyKeysLspSpec[] @@ -44,41 +44,7 @@ function M.set(filter, spec) for _, keys in pairs(Keys.resolve(spec)) do ---@cast keys LazyKeysLsp local filters = {} ---@type vim.lsp.get_clients.Filter[] - if keys.code_action then - filter = vim.tbl_extend("force", vim.deepcopy(filter), { method = "textDocument/codeAction" }) - filters[#filters + 1] = filter - - ---@param kinds? string[] - local function has(kinds) - for _, k in ipairs(kinds or {}) do - if type(k) == "string" and vim.startswith(k, keys.code_action) then - return true - end - end - end - - local enabled = keys.enabled - keys.enabled = function() - if type(enabled) == "function" and not enabled() then - return false - end - local clients = vim.lsp.get_clients(filter) - for _, client in ipairs(clients) do - -- check server cababilities first - if has(vim.tbl_get(client, "server_capabilities", "codeActionProvider", "codeActionKinds")) then - return true - end - -- check dynamic capabilities - local regs = client.dynamic_capabilities:get("codeActionProvider") - for _, reg in ipairs(regs or {}) do - if has(vim.tbl_get(reg, "registerOptions", "codeActionKinds")) then - return true - end - end - end - return false - end - elseif keys.has then + 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) diff --git a/lua/lazyvim/util/lsp.lua b/lua/lazyvim/util/lsp.lua index ff248599..f667b12f 100644 --- a/lua/lazyvim/util/lsp.lua +++ b/lua/lazyvim/util/lsp.lua @@ -93,4 +93,21 @@ function M.execute(opts) end end +---@param filter? vim.lsp.get_clients.Filter +function M.code_actions(filter) + filter = filter or {} + local ret = {} ---@type string[] + local clients = vim.lsp.get_clients(filter) + for _, client in ipairs(clients) do + -- check server cababilities first + vim.list_extend(ret, vim.tbl_get(client, "server_capabilities", "codeActionProvider", "codeActionKinds") or {}) + -- check dynamic capabilities + local regs = client.dynamic_capabilities:get("codeActionProvider", filter) + for _, reg in ipairs(regs or {}) do + vim.list_extend(ret, vim.tbl_get(reg, "registerOptions", "codeActionKinds") or {}) + end + end + return LazyVim.dedup(ret) +end + return M From 8764dfbc8fcb8923397153eb3a2cfcac7ea988f1 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 19:56:46 +0100 Subject: [PATCH 33/46] perf(extras): never load nested extras --- lua/lazyvim/util/plugin.lua | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/lua/lazyvim/util/plugin.lua b/lua/lazyvim/util/plugin.lua index 19e3d43c..a78a549f 100644 --- a/lua/lazyvim/util/plugin.lua +++ b/lua/lazyvim/util/plugin.lua @@ -111,15 +111,40 @@ function M.fix_imports() ) spec.import = rename end - local dep = M.deprecated_extras[spec and spec.import] + local dep = M.deprecated_extras[spec.import] if dep then dep = dep .. "\n" .. "Please remove the extra from `lazyvim.json` to hide this warning." LazyVim.warn(dep, { title = "LazyVim", once = true, stacktrace = true, stacklevel = 6 }) return false end + + local modname = spec.import + if type(modname) == "string" and vim.startswith(modname, "lazyvim.plugins.extras.") then + M.single_import(spec) + end end) end +---@param spec LazySpecImport +function M.single_import(spec) + local modname = spec.import + if type(modname) ~= "string" then + return + end + spec.name = modname + spec.import = function() + package.loaded[modname] = nil + local ok, mod, foo = pcall(require, modname) ---@type boolean, table?, unknown + if ok and type(mod) == "table" then + if foo then + return nil, "Spec module returned more than one value. Expected a single value." + end + return mod + end + return nil, mod + end +end + function M.fix_renames() ---@param plugin LazyPluginSpec Meta.add = LazyVim.inject.args(Meta.add, function(self, plugin) From 1b4be534f1d8959480ba1f622a457654bd737ce5 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 20:42:57 +0100 Subject: [PATCH 34/46] fix(util.plugin): single imports for extras --- lua/lazyvim/util/plugin.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lua/lazyvim/util/plugin.lua b/lua/lazyvim/util/plugin.lua index a78a549f..11362dbf 100644 --- a/lua/lazyvim/util/plugin.lua +++ b/lua/lazyvim/util/plugin.lua @@ -133,15 +133,18 @@ function M.single_import(spec) end spec.name = modname spec.import = function() - package.loaded[modname] = nil - local ok, mod, foo = pcall(require, modname) ---@type boolean, table?, unknown - if ok and type(mod) == "table" then + local modinfo = vim.loader.find(modname)[1] + local modpath = modinfo and modinfo.modpath + local mod, err = loadfile(modpath) + if mod then + local ret, foo = mod() if foo then return nil, "Spec module returned more than one value. Expected a single value." end - return mod + return ret + else + return nil, err end - return nil, mod end end From 9029d928d2f7b7f76f132b618d2931499c9b6eb9 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 21:40:30 +0100 Subject: [PATCH 35/46] feat(typescript): split typescript extra in main, vtsls and tsgo --- lua/lazyvim/config/init.lua | 104 ++++++--- .../plugins/extras/lang/typescript/init.lua | 205 +----------------- .../plugins/extras/lang/typescript/tsgo.lua | 58 +++++ .../plugins/extras/lang/typescript/vtsls.lua | 174 +++++++++++++++ lua/lazyvim/util/extras.lua | 7 + 5 files changed, 319 insertions(+), 229 deletions(-) create mode 100644 lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua create mode 100644 lua/lazyvim/plugins/extras/lang/typescript/vtsls.lua diff --git a/lua/lazyvim/config/init.lua b/lua/lazyvim/config/init.lua index 63355fcc..5a4020b6 100644 --- a/lua/lazyvim/config/init.lua +++ b/lua/lazyvim/config/init.lua @@ -348,13 +348,81 @@ function M.init() M.json.load() end ----@alias LazyVimDefault {name: string, extra: string, enabled?: boolean, origin?: "global" | "default" | "extra" } - +---@alias LazyVimDefault {name: string, group: string, extra: string, import: string, enabled?: boolean, origin?: "global" | "default" | "extra" } +--- local default_extras ---@type table + +---@param name string +---@param extras LazyVimDefault[] +function M.register_defaults(name, extras) + assert(default_extras, "defaults should be loaded by now, this should never happen") + local valid = vim.tbl_map(function(extra) + return extra.name + end, extras) --[[@as string[] ]] + + local origin = "default" + local ret ---@type LazyVimDefault? + local use ---@type string? + + local global = vim.g["lazyvim_" .. name] + if vim.tbl_contains(valid, global) then + origin = "global" -- was set by the user in their config + use = global + else + if global and global ~= "auto" then + vim.notify( + ("Invalid value for `vim.g.lazyvim_%s`: `%s`\nValid options are: %s"):format( + name, + global, + table.concat(valid, ", ") + ), + vim.log.levels.ERROR, + { title = "LazyVim" } + ) + end + for _, extra in ipairs(extras) do + if LazyVim.has_extra(extra.extra) then + use = extra.name -- was imported by the user in their lazy spec or added by LazyExtras + origin = "extra" + break + end + end + end + + use = use or valid[1] -- fallback to the first one if nothing was set + + for _, extra in ipairs(extras) do + local import = "lazyvim.plugins.extras." .. extra.extra + extra = vim.deepcopy(extra) + extra.enabled = extra.name == use + extra.import = import + extra.group = name + if extra.enabled then + extra.origin = origin + ret = extra + end + default_extras[import] = extra + end + + return assert(ret, "One of the extras should be enabled, this should never happen") +end + +---@param group string +---@return LazyVimDefault? +function M.get_default(group) + for _, extra in pairs(M.get_defaults()) do + if extra.group == group and extra.enabled then + return extra + end + end +end + function M.get_defaults() if default_extras then return default_extras end + default_extras = {} + ---@type table local checks = { picker = { @@ -378,36 +446,10 @@ function M.get_defaults() table.insert(checks.explorer, 1, table.remove(checks.explorer, 2)) end - default_extras = {} - for name, check in pairs(checks) do - local valid = {} ---@type string[] - for _, extra in ipairs(check) do - if extra.enabled ~= false then - valid[#valid + 1] = extra.name - end - end - local origin = "default" - local use = vim.g["lazyvim_" .. name] - use = vim.tbl_contains(valid, use or "auto") and use or nil - origin = use and "global" or origin - for _, extra in ipairs(use and {} or check) do - if extra.enabled ~= false and LazyVim.has_extra(extra.extra) then - use = extra.name - break - end - end - origin = use and "extra" or origin - use = use or valid[1] - for _, extra in ipairs(check) do - local import = "lazyvim.plugins.extras." .. extra.extra - extra = vim.deepcopy(extra) - extra.enabled = extra.name == use - if extra.enabled then - extra.origin = origin - end - default_extras[import] = extra - end + for name, extras in pairs(checks) do + M.register_defaults(name, extras) end + return default_extras end diff --git a/lua/lazyvim/plugins/extras/lang/typescript/init.lua b/lua/lazyvim/plugins/extras/lang/typescript/init.lua index 5d478314..70a10ae8 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript/init.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript/init.lua @@ -1,11 +1,7 @@ -if lazyvim_docs then - -- LSP Server to use for TypeScript. - vim.g.lazyvim_ts_lsp = "vtsls" -- currently the default - -- Set to "tsgo" to use the new typescript-language-server implementation instead of tsserver. - vim.g.lazyvim_ts_lsp = "tsgo" -end - -local lsp = vim.g.lazyvim_ts_lsp or "vtsls" +local extra = LazyVim.config.register_defaults("ts_lsp", { + { name = "vtsls", extra = "lang.typescript.vtsls" }, + { name = "tsgo", extra = "lang.typescript.tsgo" }, +}) return { recommended = function() @@ -22,200 +18,13 @@ return { }) end, + { import = extra.import }, + -- correctly setup lspconfig - { - "neovim/nvim-lspconfig", - opts = { - -- make sure mason installs the server - servers = { - ---@type lspconfig.settings.tsgo - tsgo = { - -- explicitly add default filetypes, so that we can extend - -- them in related extras - filetypes = { - "javascript", - "javascriptreact", - "javascript.jsx", - "typescript", - "typescriptreact", - "typescript.tsx", - }, - settings = { - typescript = { - inlayHints = { - parameterNames = { - enabled = "literals", - suppressWhenArgumentMatchesName = true, - }, - parameterTypes = { enabled = true }, - variableTypes = { enabled = true }, - propertyDeclarationTypes = { enabled = true }, - functionLikeReturnTypes = { enabled = true }, - enumMemberValues = { enabled = true }, - }, - }, - }, - }, - vtsls = { - -- explicitly add default filetypes, so that we can extend - -- them in related extras - filetypes = { - "javascript", - "javascriptreact", - "javascript.jsx", - "typescript", - "typescriptreact", - "typescript.tsx", - }, - settings = { - complete_function_calls = true, - vtsls = { - enableMoveToFileCodeAction = true, - autoUseWorkspaceTsdk = true, - experimental = { - maxInlayHintLength = 30, - completion = { - enableServerSideFuzzyMatch = true, - }, - }, - }, - typescript = { - updateImportsOnFileMove = { enabled = "always" }, - suggest = { - completeFunctionCalls = true, - }, - inlayHints = { - enumMemberValues = { enabled = true }, - functionLikeReturnTypes = { enabled = true }, - parameterNames = { enabled = "literals" }, - parameterTypes = { enabled = true }, - propertyDeclarationTypes = { enabled = true }, - variableTypes = { enabled = false }, - }, - }, - }, - keys = { - { - "gD", - function() - local win = vim.api.nvim_get_current_win() - local params = vim.lsp.util.make_position_params(win, "utf-16") - LazyVim.lsp.execute({ - command = "typescript.goToSourceDefinition", - arguments = { params.textDocument.uri, params.position }, - open = true, - }) - end, - desc = "Goto Source Definition", - }, - { - "gR", - function() - LazyVim.lsp.execute({ - command = "typescript.findAllFileReferences", - arguments = { vim.uri_from_bufnr(0) }, - open = true, - }) - end, - desc = "File References", - }, - { - "cM", - LazyVim.lsp.action["source.addMissingImports.ts"], - desc = "Add missing imports", - }, - { - "cD", - LazyVim.lsp.action["source.fixAll.ts"], - desc = "Fix all diagnostics", - }, - { - "cV", - function() - LazyVim.lsp.execute({ - title = "Select TypeScript Version", - filter = "vtsls", - command = "typescript.selectTypeScriptVersion", - }) - end, - desc = "Select TS workspace version", - }, - }, - }, - }, - setup = { - --- @deprecated -- tsserver renamed to ts_ls but not yet released, so keep this for now - --- the proper approach is to check the nvim-lspconfig release version when it's released to determine the server name dynamically - tsserver = function() - -- disable tsserver - return true - end, - ts_ls = function() - -- disable tsserver - return true - end, - vtsls = function(_, opts) - Snacks.util.lsp.on({ name = "vtsls" }, function(buffer, client) - client.commands["_typescript.moveToFileRefactoring"] = function(command, ctx) - ---@type string, string, lsp.Range - local action, uri, range = unpack(command.arguments) - - local function move(newf) - client:request("workspace/executeCommand", { - command = command.command, - arguments = { action, uri, range, newf }, - }) - end - - local fname = vim.uri_to_fname(uri) - client:request("workspace/executeCommand", { - command = "typescript.tsserverRequest", - arguments = { - "getMoveToRefactoringFileSuggestions", - { - file = fname, - startLine = range.start.line + 1, - startOffset = range.start.character + 1, - endLine = range["end"].line + 1, - endOffset = range["end"].character + 1, - }, - }, - }, function(_, result) - ---@type string[] - local files = result.body.files - table.insert(files, 1, "Enter new path...") - vim.ui.select(files, { - prompt = "Select move destination:", - format_item = function(f) - return vim.fn.fnamemodify(f, ":~:.") - end, - }, function(f) - if f and f:find("^Enter new path") then - vim.ui.input({ - prompt = "Enter move destination:", - default = vim.fn.fnamemodify(fname, ":h") .. "/", - completion = "file", - }, function(newf) - return newf and move(newf) - end) - elseif f then - move(f) - end - end) - end) - end - end) - -- copy typescript settings to javascript - opts.settings.javascript = - vim.tbl_deep_extend("force", {}, opts.settings.typescript, opts.settings.javascript or {}) - end, - }, - }, - }, - { "neovim/nvim-lspconfig", opts = function(_, opts) + local lsp = extra.name or "vtsls" local servers = { "tsserver", "ts_ls", "vtsls", "tsgo", lsp } for _, server in ipairs(servers) do opts.servers[server] = opts.servers[server] or {} diff --git a/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua b/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua new file mode 100644 index 00000000..97f27693 --- /dev/null +++ b/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua @@ -0,0 +1,58 @@ +return { + recommended = function() + return LazyVim.extras.wants({ + ft = { + "javascript", + "javascriptreact", + "javascript.jsx", + "typescript", + "typescriptreact", + "typescript.tsx", + }, + root = { "tsconfig.json", "package.json", "jsconfig.json" }, + }) + end, + + -- correctly setup lspconfig + { + "neovim/nvim-lspconfig", + opts = { + -- make sure mason installs the server + servers = { + ---@type lspconfig.settings.tsgo + tsgo = { + -- explicitly add default filetypes, so that we can extend + -- them in related extras + filetypes = { + "javascript", + "javascriptreact", + "javascript.jsx", + "typescript", + "typescriptreact", + "typescript.tsx", + }, + settings = { + typescript = { + inlayHints = { + parameterNames = { + enabled = "literals", + suppressWhenArgumentMatchesName = true, + }, + parameterTypes = { enabled = true }, + variableTypes = { enabled = true }, + propertyDeclarationTypes = { enabled = true }, + functionLikeReturnTypes = { enabled = true }, + enumMemberValues = { enabled = true }, + }, + }, + }, + }, + }, + }, + }, + -- correctly setup lspconfig + { + "neovim/nvim-lspconfig", + opts = {}, + }, +} diff --git a/lua/lazyvim/plugins/extras/lang/typescript/vtsls.lua b/lua/lazyvim/plugins/extras/lang/typescript/vtsls.lua new file mode 100644 index 00000000..b21c3805 --- /dev/null +++ b/lua/lazyvim/plugins/extras/lang/typescript/vtsls.lua @@ -0,0 +1,174 @@ +return { + recommended = function() + return LazyVim.extras.wants({ + ft = { + "javascript", + "javascriptreact", + "javascript.jsx", + "typescript", + "typescriptreact", + "typescript.tsx", + }, + root = { "tsconfig.json", "package.json", "jsconfig.json" }, + }) + end, + + -- correctly setup lspconfig + { + "neovim/nvim-lspconfig", + opts = { + -- make sure mason installs the server + servers = { + vtsls = { + -- explicitly add default filetypes, so that we can extend + -- them in related extras + filetypes = { + "javascript", + "javascriptreact", + "javascript.jsx", + "typescript", + "typescriptreact", + "typescript.tsx", + }, + settings = { + complete_function_calls = true, + vtsls = { + enableMoveToFileCodeAction = true, + autoUseWorkspaceTsdk = true, + experimental = { + maxInlayHintLength = 30, + completion = { + enableServerSideFuzzyMatch = true, + }, + }, + }, + typescript = { + updateImportsOnFileMove = { enabled = "always" }, + suggest = { + completeFunctionCalls = true, + }, + inlayHints = { + enumMemberValues = { enabled = true }, + functionLikeReturnTypes = { enabled = true }, + parameterNames = { enabled = "literals" }, + parameterTypes = { enabled = true }, + propertyDeclarationTypes = { enabled = true }, + variableTypes = { enabled = false }, + }, + }, + }, + keys = { + { + "gD", + function() + local win = vim.api.nvim_get_current_win() + local params = vim.lsp.util.make_position_params(win, "utf-16") + LazyVim.lsp.execute({ + command = "typescript.goToSourceDefinition", + arguments = { params.textDocument.uri, params.position }, + open = true, + }) + end, + desc = "Goto Source Definition", + }, + { + "gR", + function() + LazyVim.lsp.execute({ + command = "typescript.findAllFileReferences", + arguments = { vim.uri_from_bufnr(0) }, + open = true, + }) + end, + desc = "File References", + }, + { + "cM", + LazyVim.lsp.action["source.addMissingImports.ts"], + desc = "Add missing imports", + }, + { + "cD", + LazyVim.lsp.action["source.fixAll.ts"], + desc = "Fix all diagnostics", + }, + { + "cV", + function() + LazyVim.lsp.execute({ + title = "Select TypeScript Version", + filter = "vtsls", + command = "typescript.selectTypeScriptVersion", + }) + end, + desc = "Select TS workspace version", + }, + }, + }, + }, + setup = { + vtsls = function(_, opts) + Snacks.util.lsp.on({ name = "vtsls" }, function(buffer, client) + client.commands["_typescript.moveToFileRefactoring"] = function(command, ctx) + ---@type string, string, lsp.Range + local action, uri, range = unpack(command.arguments) + + local function move(newf) + client:request("workspace/executeCommand", { + command = command.command, + arguments = { action, uri, range, newf }, + }) + end + + local fname = vim.uri_to_fname(uri) + client:request("workspace/executeCommand", { + command = "typescript.tsserverRequest", + arguments = { + "getMoveToRefactoringFileSuggestions", + { + file = fname, + startLine = range.start.line + 1, + startOffset = range.start.character + 1, + endLine = range["end"].line + 1, + endOffset = range["end"].character + 1, + }, + }, + }, function(_, result) + ---@type string[] + local files = result.body.files + table.insert(files, 1, "Enter new path...") + vim.ui.select(files, { + prompt = "Select move destination:", + format_item = function(f) + return vim.fn.fnamemodify(f, ":~:.") + end, + }, function(f) + if f and f:find("^Enter new path") then + vim.ui.input({ + prompt = "Enter move destination:", + default = vim.fn.fnamemodify(fname, ":h") .. "/", + completion = "file", + }, function(newf) + return newf and move(newf) + end) + elseif f then + move(f) + end + end) + end) + end + end) + -- copy typescript settings to javascript + opts.settings.javascript = + vim.tbl_deep_extend("force", {}, opts.settings.typescript, opts.settings.javascript or {}) + end, + }, + }, + }, + + -- correctly setup lspconfig + { + "neovim/nvim-lspconfig", + opts = {}, + }, +} diff --git a/lua/lazyvim/util/extras.lua b/lua/lazyvim/util/extras.lua index 06339a92..3a1dce8b 100644 --- a/lua/lazyvim/util/extras.lua +++ b/lua/lazyvim/util/extras.lua @@ -115,6 +115,13 @@ function M.get_extra(source, modname) recommended = M.wants(recommended) end + -- language extras that are disabled because a conflict with another extra is enabled are not recommended + local defaults = LazyVim.config.get_defaults() + local def = defaults[modname] + if def and def.enabled == false and vim.startswith(modname, "lazyvim.plugins.extras.lang.") then + recommended = false + end + ---@type LazyExtra return { source = source, From 4e9eac57aba1ea575ef008a503cba8327257e4a4 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 22:15:34 +0100 Subject: [PATCH 36/46] feat(oxc): added oxc extra for oxfmt and oxlint --- .../plugins/extras/lang/typescript/oxc.lua | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 lua/lazyvim/plugins/extras/lang/typescript/oxc.lua diff --git a/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua b/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua new file mode 100644 index 00000000..4bd3a00d --- /dev/null +++ b/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua @@ -0,0 +1,56 @@ +local supported = { + "javascript", + "javascriptreact", + "typescript", + "typescriptreact", + "json", + "jsonc", + "vue", + "svelte", + "astro", +} + +return { + recommended = function() + return LazyVim.extras.wants({ + root = { + ".oxlintrc.json", + ".oxlintrc.jsonc", + "oxlint.config.ts", + ".oxfmtrc.json", + ".oxfmtrc.jsonc", + "oxfmt.config.ts", + }, + }) + end, + + { + "neovim/nvim-lspconfig", + opts = { + servers = { + ---@type lspconfig.settings.oxlint + oxlint = {}, + --- disable the oxfmt lsp server since we use conform for formatting + oxfmt = { enabled = false }, + }, + }, + }, + + { + "mason-org/mason.nvim", + opts = { ensure_installed = { "oxfmt" } }, + }, + + { + "stevearc/conform.nvim", + optional = true, + ---@param opts conform.setupOpts + opts = function(_, opts) + opts.formatters_by_ft = opts.formatters_by_ft or {} + for _, ft in ipairs(supported) do + opts.formatters_by_ft[ft] = opts.formatters_by_ft[ft] or {} + table.insert(opts.formatters_by_ft[ft], "oxfmt") + end + end, + }, +} From 59126caa31f62c548f2d3af7586522d40d98fed7 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Fri, 20 Mar 2026 23:16:04 +0100 Subject: [PATCH 37/46] test: fix tests --- lua/lazyvim/plugins/extras/lang/typescript/oxc.lua | 1 - tests/extras/extra_spec.lua | 10 +++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua b/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua index 4bd3a00d..a516fc89 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua @@ -44,7 +44,6 @@ return { { "stevearc/conform.nvim", optional = true, - ---@param opts conform.setupOpts opts = function(_, opts) opts.formatters_by_ft = opts.formatters_by_ft or {} for _, ft in ipairs(supported) do diff --git a/tests/extras/extra_spec.lua b/tests/extras/extra_spec.lua index 14f8d741..a1086590 100644 --- a/tests/extras/extra_spec.lua +++ b/tests/extras/extra_spec.lua @@ -5,6 +5,9 @@ local Icons = require("mini.icons") local Plugin = require("lazy.core.plugin") _G.LazyVim = require("lazyvim.util") +require("lazyvim.config") +LazyVim.config.get_defaults() +LazyVim.plugin.setup() describe("Extra", function() local Config = require("lazy.core.config") @@ -93,8 +96,13 @@ describe("Extra", function() local mason = spec.plugins["mason.nvim"] local mason_opts = Plugin.values(mason, "opts", false) - for lsp in pairs(lspconfig_opts.servers or {}) do + for lsp, lsp_opts in pairs(lspconfig_opts.servers or {}) do local lsp_pkg = lsp_to_pkg[lsp] + -- Skip if the LSP server is disabled in the config since mason.nvim won't install it + -- and it might still be used for conform.nvim or nvim-lint, etc. + if type(lsp_opts) == "table" and lsp_opts.enabled == false then + lsp_pkg = false + end assert( not (lsp_pkg and vim.tbl_contains(mason_opts.ensure_installed, lsp_pkg)), "LSP server " From 8bcb6208021bd4e4257de64c9598c6b78688be28 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Sat, 21 Mar 2026 06:40:32 +0100 Subject: [PATCH 38/46] fix(tsgo): disable inlayHints.functionLikeReturnTypes by default. Too noisy --- lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua b/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua index 97f27693..ef075416 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua @@ -41,7 +41,7 @@ return { parameterTypes = { enabled = true }, variableTypes = { enabled = true }, propertyDeclarationTypes = { enabled = true }, - functionLikeReturnTypes = { enabled = true }, + functionLikeReturnTypes = { enabled = false }, enumMemberValues = { enabled = true }, }, }, From 6dadcc206547993bf03bffdaec5e8417c94b6ca8 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Sat, 21 Mar 2026 06:40:53 +0100 Subject: [PATCH 39/46] docs(typescript): add some docs on how to enable tsgo with vim global --- lua/lazyvim/plugins/extras/lang/typescript/init.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lua/lazyvim/plugins/extras/lang/typescript/init.lua b/lua/lazyvim/plugins/extras/lang/typescript/init.lua index 70a10ae8..825d3ba6 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript/init.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript/init.lua @@ -1,3 +1,13 @@ +if lazyvim_docs then + -- LSP Server to use for TypeScript. + ---@type "vtsls" | "tsgo" + vim.g.lazyvim_ts_lsp = "vtsls" -- currently the default + + -- To use the newer, much faster `tsgo` LSP server, either: + -- * enable the `tsgo` extra, or + -- * set `vim.g.lazyvim_ts_lsp = "tsgo"` in your `options.lua` +end + local extra = LazyVim.config.register_defaults("ts_lsp", { { name = "vtsls", extra = "lang.typescript.vtsls" }, { name = "tsgo", extra = "lang.typescript.tsgo" }, From 6d0da34de9c4a82170e3359d4e7853bf89a557b3 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Sat, 21 Mar 2026 08:55:20 +0100 Subject: [PATCH 40/46] fix(lsp): sort server names before setting keymaps Sort server names so that `*` (wildcard) keymaps are registered before named servers, ensuring server-specific keymaps take precedence. Fixes #6956, Fixes #6903 Co-Authored-By: Claude Opus 4.6 (1M context) --- lua/lazyvim/plugins/lsp/init.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lua/lazyvim/plugins/lsp/init.lua b/lua/lazyvim/plugins/lsp/init.lua index 9a790b21..490bec3c 100644 --- a/lua/lazyvim/plugins/lsp/init.lua +++ b/lua/lazyvim/plugins/lsp/init.lua @@ -167,7 +167,10 @@ return { LazyVim.format.register(LazyVim.lsp.formatter()) -- setup keymaps - for server, server_opts in pairs(opts.servers) do + local names = vim.tbl_keys(opts.servers) ---@type string[] + table.sort(names) + for _, server in ipairs(names) do + local server_opts = opts.servers[server] if type(server_opts) == "table" and server_opts.keys then require("lazyvim.plugins.lsp.keymaps").set({ name = server ~= "*" and server or nil }, server_opts.keys) end From 2a5c8928358bd1b1a152be5112e2fab58202857d Mon Sep 17 00:00:00 2001 From: Ira Chan Date: Sat, 21 Mar 2026 16:04:39 +0800 Subject: [PATCH 41/46] fix(clojure): remove redundant on-filetype() call that leaks keymaps (#7065) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary The Conjure spec calls `require("conjure.mapping")["on-filetype"]()` unconditionally in its `config` function. Because the plugin loads on `event = "LazyFile"` (any file open), this sets Conjure's buffer-local keymaps on whatever buffer triggered the load, regardless of filetype. This call is redundant. `require("conjure.main").main()` internally calls `mapping.init(filetypes)`, which: 1. Registers a `FileType` autocmd scoped to supported filetypes. 2. Checks if the current buffer's filetype is in the list before calling `on-filetype()`. From `conjure/mapping.lua`: ```lua M.init = function(filetypes) local group = vim.api.nvim_create_augroup("conjure_init_filetypes", {}) if (true == config["get-in"]({"mapping", "enable_ft_mappings"})) then vim.api.nvim_create_autocmd("FileType", { group = group, pattern = filetypes, callback = autocmd_callback(M["on-filetype"]) }) if core.some(function(x) return x == vim.bo.filetype end, filetypes) then vim.schedule(M["on-filetype"]) end end end ``` The extra `on-filetype()` bypasses this guard. Removing it restores the intended behavior: Conjure keymaps only appear in buffers whose filetype Conjure supports. ## Related Issue(s) Fixes #7064 ## Repro Save as `repro.lua` and run with `nvim -u repro.lua`: ```lua vim.env.LAZY_STDPATH = ".repro" load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))() require("lazy.minit").repro({ spec = { { "LazyVim/LazyVim", import = "lazyvim.plugins" }, { import = "lazyvim.plugins.extras.lang.clojure" }, }, }) ``` Steps: 1. `nvim -u repro.lua` 2. `:e test.md` 3. `:nmap ` — observe 25+ Conjure keymaps on a markdown buffer After this fix, `:nmap ` on `test.md` shows no Conjure keymaps. ## Checklist - [x] I've read the [CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md) guidelines. --- lua/lazyvim/plugins/extras/lang/clojure.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/lazyvim/plugins/extras/lang/clojure.lua b/lua/lazyvim/plugins/extras/lang/clojure.lua index 4c47c623..3d12dd1b 100644 --- a/lua/lazyvim/plugins/extras/lang/clojure.lua +++ b/lua/lazyvim/plugins/extras/lang/clojure.lua @@ -52,7 +52,6 @@ return { event = "LazyFile", config = function(_, _) require("conjure.main").main() - require("conjure.mapping")["on-filetype"]() end, init = function() -- print color codes if baleia.nvim is available From 96f4f18d7d81c786ac0df5723bc7aca058bf2165 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Sat, 21 Mar 2026 09:50:09 +0100 Subject: [PATCH 42/46] fix(terminal): use Snacks.terminal.focus() for mapping Switches from toggle() to focus() so that only hides the terminal when you're currently in it. Restores hide win keys for terminal mode. Closes #7048 Co-Authored-By: Claude Opus 4.6 (1M context) --- lua/lazyvim/config/keymaps.lua | 4 ++-- lua/lazyvim/plugins/util.lua | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lua/lazyvim/config/keymaps.lua b/lua/lazyvim/config/keymaps.lua index 05d07a21..9651e4e6 100644 --- a/lua/lazyvim/config/keymaps.lua +++ b/lua/lazyvim/config/keymaps.lua @@ -189,8 +189,8 @@ map("n", "L", function() LazyVim.news.changelog() end, { desc = "LazyVim -- floating terminal map("n", "fT", function() Snacks.terminal() end, { desc = "Terminal (cwd)" }) map("n", "ft", function() Snacks.terminal(nil, { cwd = LazyVim.root() }) end, { desc = "Terminal (Root Dir)" }) -map({"n","t"}, "",function() Snacks.terminal(nil, { cwd = LazyVim.root() }) end, { desc = "Terminal (Root Dir)" }) -map({"n","t"}, "",function() Snacks.terminal(nil, { cwd = LazyVim.root() }) end, { desc = "which_key_ignore" }) +map({"n","t"}, "",function() Snacks.terminal.focus(nil, { cwd = LazyVim.root() }) end, { desc = "Terminal (Root Dir)" }) +map({"n","t"}, "",function() Snacks.terminal.focus(nil, { cwd = LazyVim.root() }) end, { desc = "which_key_ignore" }) -- windows map("n", "-", "s", { desc = "Split Window Below", remap = true }) diff --git a/lua/lazyvim/plugins/util.lua b/lua/lazyvim/plugins/util.lua index 8d8aa220..9d0d231c 100644 --- a/lua/lazyvim/plugins/util.lua +++ b/lua/lazyvim/plugins/util.lua @@ -23,6 +23,8 @@ return { nav_j = { "", term_nav("j"), desc = "Go to Lower Window", expr = true, mode = "t" }, nav_k = { "", term_nav("k"), desc = "Go to Upper Window", expr = true, mode = "t" }, nav_l = { "", term_nav("l"), desc = "Go to Right Window", expr = true, mode = "t" }, + hide_slash = { "", "hide", desc = "Hide Terminal", mode = "t" }, + hide_underscore = { "", "hide", desc = "which_key_ignore", mode = "t" }, }, }, }, From 85afbbc94bb45891799a4851b2edf753b51f18b0 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Thu, 2 Apr 2026 10:07:50 +0200 Subject: [PATCH 43/46] fix(oxc): added `fixKind = "all"` --- lua/lazyvim/plugins/extras/lang/typescript/oxc.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua b/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua index a516fc89..d4efb30c 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript/oxc.lua @@ -29,7 +29,11 @@ return { opts = { servers = { ---@type lspconfig.settings.oxlint - oxlint = {}, + oxlint = { + settings = { + fixKind = "all", + }, + }, --- disable the oxfmt lsp server since we use conform for formatting oxfmt = { enabled = false }, }, From d07070bf2ff83ae513097d02d71460920af85a91 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Thu, 2 Apr 2026 10:08:02 +0200 Subject: [PATCH 44/46] fix(tsgo): remove some noisy inlay hints --- lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua b/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua index ef075416..b526cef5 100644 --- a/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua +++ b/lua/lazyvim/plugins/extras/lang/typescript/tsgo.lua @@ -34,15 +34,15 @@ return { settings = { typescript = { inlayHints = { + enumMemberValues = { enabled = true }, + functionLikeReturnTypes = { enabled = false }, parameterNames = { enabled = "literals", suppressWhenArgumentMatchesName = true, }, parameterTypes = { enabled = true }, - variableTypes = { enabled = true }, propertyDeclarationTypes = { enabled = true }, - functionLikeReturnTypes = { enabled = false }, - enumMemberValues = { enabled = true }, + variableTypes = { enabled = false }, }, }, }, From ef272ff7cc9b53d48baf6544618b5923d65c0282 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Thu, 2 Apr 2026 10:11:23 +0200 Subject: [PATCH 45/46] fix(treesitter): `nvim-treesitter` on longer support nvim-0.11, so pin when needed. Fixes #7092 --- lua/lazyvim/plugins/treesitter.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/lazyvim/plugins/treesitter.lua b/lua/lazyvim/plugins/treesitter.lua index 6de91b30..4ef68c8f 100644 --- a/lua/lazyvim/plugins/treesitter.lua +++ b/lua/lazyvim/plugins/treesitter.lua @@ -6,6 +6,7 @@ return { { "nvim-treesitter/nvim-treesitter", branch = "main", + commit = vim.fn.has("nvim-0.12") == 0 and "7caec274fd19c12b55902a5b795100d21531391f" or nil, version = false, -- last release is way too old and doesn't work on Windows build = function() local TS = require("nvim-treesitter") From 83d90f339defdb109a6ede333865a66ffc7ef6aa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 10:13:57 +0200 Subject: [PATCH 46/46] chore(main): release 15.15.0 (#7034) :robot: I have created a release *beep* *boop* --- ## [15.15.0](https://github.com/LazyVim/LazyVim/compare/v15.14.0...v15.15.0) (2026-04-02) ### Features * **biome:** enable biome lsp for linting ([b2830cf](https://github.com/LazyVim/LazyVim/commit/b2830cfcc5c9c09ebbf9545beb3947a55ce89dbd)) * **biome:** move biome extra from formatting.biome -> lang.typescript.biome ([242f098](https://github.com/LazyVim/LazyVim/commit/242f0983de9fdb70f0d82057a8039e32bc171764)) * **lazydev:** make lspconfig types available on word `lspconfig.settings` ([36f5947](https://github.com/LazyVim/LazyVim/commit/36f594716bcb0bec84a05a6c55f702134d2e89c3)) * **lsp:** auto add organizeImport keymaps for LSPs that support it ([e54689e](https://github.com/LazyVim/LazyVim/commit/e54689ebdc5458cb30f4a48b954c710bb381cd01)) * **oxc:** added oxc extra for oxfmt and oxlint ([4e9eac5](https://github.com/LazyVim/LazyVim/commit/4e9eac57aba1ea575ef008a503cba8327257e4a4)) * **sidekick:** ctrl+. focuses sidekick, but when already inside sidekick, hides it ([50159fe](https://github.com/LazyVim/LazyVim/commit/50159fe344d93329a569cee136c0323e48b0d3da)) * **typescript:** set `vim.g.lazyvim_ts_lsp = "tsgo"` to use the much faster experimental lsp server ([e6f26f0](https://github.com/LazyVim/LazyVim/commit/e6f26f0f23e9cb4c6bcc351b06474f4863319aff)) * **typescript:** split typescript extra in main, vtsls and tsgo ([9029d92](https://github.com/LazyVim/LazyVim/commit/9029d928d2f7b7f76f132b618d2931499c9b6eb9)) ### Bug Fixes * **biome:** added recommendation when root has biome config file ([ad25b31](https://github.com/LazyVim/LazyVim/commit/ad25b31e512892ca51a1fa3ffa96d1375c391039)) * **biome:** biome mason install is no longer needed ([5450006](https://github.com/LazyVim/LazyVim/commit/5450006ccdd7df341f7f60dded58ea4a87aa9c15)) * **biome:** use biome-check in conform that also fixes linting issues and sorts imports ([954d874](https://github.com/LazyVim/LazyVim/commit/954d8746e5cf1266d93cf4210c00c1506f20423b)) * **lsp:** sort server names before setting keymaps ([6d0da34](https://github.com/LazyVim/LazyVim/commit/6d0da34de9c4a82170e3359d4e7853bf89a557b3)) * **oxc:** added `fixKind = "all"` ([85afbbc](https://github.com/LazyVim/LazyVim/commit/85afbbc94bb45891799a4851b2edf753b51f18b0)) * **r:** recommend for *.qmd instead of *qmd files ([3b3d649](https://github.com/LazyVim/LazyVim/commit/3b3d6493332798674fb7b82aea600bab18eaf311)) * **terminal:** use Snacks.terminal.focus() for <C-/> mapping ([96f4f18](https://github.com/LazyVim/LazyVim/commit/96f4f18d7d81c786ac0df5723bc7aca058bf2165)), closes [#7048](https://github.com/LazyVim/LazyVim/issues/7048) * **treesitter:** `nvim-treesitter` on longer support nvim-0.11, so pin when needed. Fixes [#7092](https://github.com/LazyVim/LazyVim/issues/7092) ([ef272ff](https://github.com/LazyVim/LazyVim/commit/ef272ff7cc9b53d48baf6544618b5923d65c0282)) * **tsgo:** disable inlayHints.functionLikeReturnTypes by default. Too noisy ([8bcb620](https://github.com/LazyVim/LazyVim/commit/8bcb6208021bd4e4257de64c9598c6b78688be28)) * **tsgo:** remove some noisy inlay hints ([d07070b](https://github.com/LazyVim/LazyVim/commit/d07070bf2ff83ae513097d02d71460920af85a91)) * **typescript:** remove keymaps for non-existing code actions ([53f4eab](https://github.com/LazyVim/LazyVim/commit/53f4eabd7723faba2d7c14afe53226d8c18bf16c)) * **util.plugin:** single imports for extras ([1b4be53](https://github.com/LazyVim/LazyVim/commit/1b4be534f1d8959480ba1f622a457654bd737ce5)) ### Performance Improvements * **extras:** never load nested extras ([8764dfb](https://github.com/LazyVim/LazyVim/commit/8764dfbc8fcb8923397153eb3a2cfcac7ea988f1)) ### Reverts * **lsp:** revert changes for [#6456](https://github.com/LazyVim/LazyVim/issues/6456). Closes [#6779](https://github.com/LazyVim/LazyVim/issues/6779) ([d0fe8c8](https://github.com/LazyVim/LazyVim/commit/d0fe8c896f4dca003e8d56e2091ee5ec7da7af75)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/.release-please-manifest.json | 2 +- CHANGELOG.md | 40 +++++++++++++++++++++++++++ lua/lazyvim/config/init.lua | 2 +- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/.github/.release-please-manifest.json b/.github/.release-please-manifest.json index 538e599a..6509ffcb 100644 --- a/.github/.release-please-manifest.json +++ b/.github/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "15.14.0" + ".": "15.15.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index f5e25695..9c2cdedb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,45 @@ # Changelog +## [15.15.0](https://github.com/LazyVim/LazyVim/compare/v15.14.0...v15.15.0) (2026-04-02) + + +### Features + +* **biome:** enable biome lsp for linting ([b2830cf](https://github.com/LazyVim/LazyVim/commit/b2830cfcc5c9c09ebbf9545beb3947a55ce89dbd)) +* **biome:** move biome extra from formatting.biome -> lang.typescript.biome ([242f098](https://github.com/LazyVim/LazyVim/commit/242f0983de9fdb70f0d82057a8039e32bc171764)) +* **lazydev:** make lspconfig types available on word `lspconfig.settings` ([36f5947](https://github.com/LazyVim/LazyVim/commit/36f594716bcb0bec84a05a6c55f702134d2e89c3)) +* **lsp:** auto add organizeImport keymaps for LSPs that support it ([e54689e](https://github.com/LazyVim/LazyVim/commit/e54689ebdc5458cb30f4a48b954c710bb381cd01)) +* **oxc:** added oxc extra for oxfmt and oxlint ([4e9eac5](https://github.com/LazyVim/LazyVim/commit/4e9eac57aba1ea575ef008a503cba8327257e4a4)) +* **sidekick:** ctrl+. focuses sidekick, but when already inside sidekick, hides it ([50159fe](https://github.com/LazyVim/LazyVim/commit/50159fe344d93329a569cee136c0323e48b0d3da)) +* **typescript:** set `vim.g.lazyvim_ts_lsp = "tsgo"` to use the much faster experimental lsp server ([e6f26f0](https://github.com/LazyVim/LazyVim/commit/e6f26f0f23e9cb4c6bcc351b06474f4863319aff)) +* **typescript:** split typescript extra in main, vtsls and tsgo ([9029d92](https://github.com/LazyVim/LazyVim/commit/9029d928d2f7b7f76f132b618d2931499c9b6eb9)) + + +### Bug Fixes + +* **biome:** added recommendation when root has biome config file ([ad25b31](https://github.com/LazyVim/LazyVim/commit/ad25b31e512892ca51a1fa3ffa96d1375c391039)) +* **biome:** biome mason install is no longer needed ([5450006](https://github.com/LazyVim/LazyVim/commit/5450006ccdd7df341f7f60dded58ea4a87aa9c15)) +* **biome:** use biome-check in conform that also fixes linting issues and sorts imports ([954d874](https://github.com/LazyVim/LazyVim/commit/954d8746e5cf1266d93cf4210c00c1506f20423b)) +* **lsp:** sort server names before setting keymaps ([6d0da34](https://github.com/LazyVim/LazyVim/commit/6d0da34de9c4a82170e3359d4e7853bf89a557b3)) +* **oxc:** added `fixKind = "all"` ([85afbbc](https://github.com/LazyVim/LazyVim/commit/85afbbc94bb45891799a4851b2edf753b51f18b0)) +* **r:** recommend for *.qmd instead of *qmd files ([3b3d649](https://github.com/LazyVim/LazyVim/commit/3b3d6493332798674fb7b82aea600bab18eaf311)) +* **terminal:** use Snacks.terminal.focus() for <C-/> mapping ([96f4f18](https://github.com/LazyVim/LazyVim/commit/96f4f18d7d81c786ac0df5723bc7aca058bf2165)), closes [#7048](https://github.com/LazyVim/LazyVim/issues/7048) +* **treesitter:** `nvim-treesitter` on longer support nvim-0.11, so pin when needed. Fixes [#7092](https://github.com/LazyVim/LazyVim/issues/7092) ([ef272ff](https://github.com/LazyVim/LazyVim/commit/ef272ff7cc9b53d48baf6544618b5923d65c0282)) +* **tsgo:** disable inlayHints.functionLikeReturnTypes by default. Too noisy ([8bcb620](https://github.com/LazyVim/LazyVim/commit/8bcb6208021bd4e4257de64c9598c6b78688be28)) +* **tsgo:** remove some noisy inlay hints ([d07070b](https://github.com/LazyVim/LazyVim/commit/d07070bf2ff83ae513097d02d71460920af85a91)) +* **typescript:** remove keymaps for non-existing code actions ([53f4eab](https://github.com/LazyVim/LazyVim/commit/53f4eabd7723faba2d7c14afe53226d8c18bf16c)) +* **util.plugin:** single imports for extras ([1b4be53](https://github.com/LazyVim/LazyVim/commit/1b4be534f1d8959480ba1f622a457654bd737ce5)) + + +### Performance Improvements + +* **extras:** never load nested extras ([8764dfb](https://github.com/LazyVim/LazyVim/commit/8764dfbc8fcb8923397153eb3a2cfcac7ea988f1)) + + +### Reverts + +* **lsp:** revert changes for [#6456](https://github.com/LazyVim/LazyVim/issues/6456). Closes [#6779](https://github.com/LazyVim/LazyVim/issues/6779) ([d0fe8c8](https://github.com/LazyVim/LazyVim/commit/d0fe8c896f4dca003e8d56e2091ee5ec7da7af75)) + ## [15.14.0](https://github.com/LazyVim/LazyVim/compare/v15.13.0...v15.14.0) (2026-03-01) diff --git a/lua/lazyvim/config/init.lua b/lua/lazyvim/config/init.lua index 5a4020b6..62d0b8a5 100644 --- a/lua/lazyvim/config/init.lua +++ b/lua/lazyvim/config/init.lua @@ -3,7 +3,7 @@ _G.LazyVim = require("lazyvim.util") ---@class LazyVimConfig: LazyVimOptions local M = {} -M.version = "15.14.0" -- x-release-please-version +M.version = "15.15.0" -- x-release-please-version LazyVim.config = M ---@class LazyVimOptions