From 5bf237820d7938b1b6490164fbd75e4117d341c1 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Thu, 18 Sep 2025 09:46:49 +0200 Subject: [PATCH 1/5] fix(snacks): safe wrapper around snacks statuscolumn to prevent errors when LazyVim is still installing --- lua/lazyvim/config/options.lua | 2 +- lua/lazyvim/util/init.lua | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lua/lazyvim/config/options.lua b/lua/lazyvim/config/options.lua index 2872d2a4..618d4e7e 100644 --- a/lua/lazyvim/config/options.lua +++ b/lua/lazyvim/config/options.lua @@ -104,7 +104,7 @@ opt.spelllang = { "en" } opt.splitbelow = true -- Put new windows below current opt.splitkeep = "screen" opt.splitright = true -- Put new windows right of current -opt.statuscolumn = [[%!v:lua.require'snacks.statuscolumn'.get()]] +opt.statuscolumn = [[%!v:lua.LazyVim.statuscolumn()]] opt.tabstop = 2 -- Number of spaces tabs count for opt.termguicolors = true -- True color support opt.timeoutlen = vim.g.vscode and 1000 or 300 -- Lower than default (1000) to quickly trigger which-key diff --git a/lua/lazyvim/util/init.lua b/lua/lazyvim/util/init.lua index 7561b385..44a135ad 100644 --- a/lua/lazyvim/util/init.lua +++ b/lua/lazyvim/util/init.lua @@ -299,4 +299,9 @@ function M.memoize(fn) end end +-- Safe wrapper around snacks to prevent errors when LazyVim is still installing +function M.statuscolumn() + return package.loaded.snacks and require("snacks.statuscolumn").get() or "" +end + return M From b93303d2339b1117171780cebed1d710fd3805d5 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Thu, 18 Sep 2025 09:48:43 +0200 Subject: [PATCH 2/5] feat(treesitter): refactored setting up treesitter indent/highlight/folds --- lua/lazyvim/config/options.lua | 4 +--- lua/lazyvim/plugins/lsp/init.lua | 1 + lua/lazyvim/plugins/treesitter.lua | 30 ++++++++++++++++++++---------- lua/lazyvim/util/treesitter.lua | 19 +++++++++++-------- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/lua/lazyvim/config/options.lua b/lua/lazyvim/config/options.lua index 618d4e7e..2ae1b38d 100644 --- a/lua/lazyvim/config/options.lua +++ b/lua/lazyvim/config/options.lua @@ -68,9 +68,8 @@ opt.fillchars = { diff = "╱", eob = " ", } -opt.foldexpr = "v:lua.LazyVim.treesitter.foldexpr()" -- treesitter folds opt.foldlevel = 99 -opt.foldmethod = "expr" +opt.foldmethod = "indent" opt.foldtext = "" opt.formatexpr = "v:lua.LazyVim.format.formatexpr()" opt.formatoptions = "jcroqlnt" -- tcqj @@ -78,7 +77,6 @@ opt.grepformat = "%f:%l:%c:%m" opt.grepprg = "rg --vimgrep" opt.ignorecase = true -- Ignore case opt.inccommand = "nosplit" -- preview incremental substitute -opt.indentexpr = "v:lua.LazyVim.treesitter.indentexpr()" -- treesitter indents opt.jumpoptions = "view" opt.laststatus = 3 -- global statusline opt.linebreak = true -- Wrap lines at convenient points diff --git a/lua/lazyvim/plugins/lsp/init.lua b/lua/lazyvim/plugins/lsp/init.lua index 00a698fc..1984c31b 100644 --- a/lua/lazyvim/plugins/lsp/init.lua +++ b/lua/lazyvim/plugins/lsp/init.lua @@ -148,6 +148,7 @@ return { LazyVim.lsp.on_supports_method("textDocument/foldingRange", function(client, buffer) local win = vim.api.nvim_get_current_win() vim.wo[win][0].foldexpr = "v:lua.vim.lsp.foldexpr()" + vim.wo[win][0].foldmethod = "expr" end) end diff --git a/lua/lazyvim/plugins/treesitter.lua b/lua/lazyvim/plugins/treesitter.lua index b36c24d3..bb842763 100644 --- a/lua/lazyvim/plugins/treesitter.lua +++ b/lua/lazyvim/plugins/treesitter.lua @@ -22,6 +22,9 @@ return { ---@class lazyvim.TSConfig: TSConfig opts = { -- LazyVim config for treesitter + indent = { enable = true }, + highlight = { enable = true }, + folds = { enable = true }, ensure_installed = { "bash", "c", @@ -80,20 +83,27 @@ return { end) end - -- treesitter highlighting vim.api.nvim_create_autocmd("FileType", { group = vim.api.nvim_create_augroup("lazyvim_treesitter", { clear = true }), callback = function(ev) - if LazyVim.treesitter.have(ev.match) then - pcall(vim.treesitter.start) + if not LazyVim.treesitter.have(ev.match) then + return + end - -- check if ftplugins changed foldexpr/indentexpr - for _, option in ipairs({ "foldexpr", "indentexpr" }) do - local expr = "v:lua.LazyVim.treesitter." .. option .. "()" - if vim.opt_global[option]:get() == expr then - vim.opt_local[option] = expr - end - end + -- highlighting + if vim.tbl_get(opts, "highlight", "enable") ~= false then + pcall(vim.treesitter.start) + end + + -- indents + if vim.tbl_get(opts, "indent", "enable") ~= false then + vim.bo[ev.buf].indentexpr = "v:lua.LazyVim.treesitter.indentexpr()" + end + + -- folds + if vim.tbl_get(opts, "folds", "enable") ~= false then + vim.wo.foldmethod = "expr" + vim.wo.foldexpr = "v:lua.LazyVim.treesitter.foldexpr()" end end, }) diff --git a/lua/lazyvim/util/treesitter.lua b/lua/lazyvim/util/treesitter.lua index bf7c12f8..73e925fc 100644 --- a/lua/lazyvim/util/treesitter.lua +++ b/lua/lazyvim/util/treesitter.lua @@ -14,20 +14,23 @@ function M.get_installed(update) return M._installed or {} end ----@param ft string -function M.have(ft) - local lang = vim.treesitter.language.get_lang(ft) - return lang and M.get_installed()[lang] +---@param what string|number|nil +---@overload fun(buf?:number):boolean +---@overload fun(ft:string):boolean +---@return boolean +function M.have(what) + what = what or vim.api.nvim_get_current_buf() + what = type(what) == "number" and vim.bo[what].filetype or what --[[@as string]] + local lang = vim.treesitter.language.get_lang(what) + return lang ~= nil and M.get_installed()[lang] ~= nil end function M.foldexpr() - local buf = vim.api.nvim_get_current_buf() - return M.have(vim.bo[buf].filetype) and vim.treesitter.foldexpr() or "0" + return M.have() and vim.treesitter.foldexpr() or "0" end function M.indentexpr() - local buf = vim.api.nvim_get_current_buf() - return M.have(vim.bo[buf].filetype) and require("nvim-treesitter").indentexpr() or -1 + return M.have() and require("nvim-treesitter").indentexpr() or -1 end return M From 725d048e009b866425b2a0cc620ba2c413e8b65f Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Thu, 18 Sep 2025 09:49:20 +0200 Subject: [PATCH 3/5] feat(treesitter): automatically install and use mason's tree-sitter-cli if not installed on system --- lua/lazyvim/plugins/treesitter.lua | 16 +++++----- lua/lazyvim/util/treesitter.lua | 47 ++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/lua/lazyvim/plugins/treesitter.lua b/lua/lazyvim/plugins/treesitter.lua index bb842763..a7ef7ed8 100644 --- a/lua/lazyvim/plugins/treesitter.lua +++ b/lua/lazyvim/plugins/treesitter.lua @@ -13,7 +13,9 @@ return { LazyVim.error("Please restart Neovim and run `:TSUpdate` to use the `nvim-treesitter` **main** branch.") return end - TS.update(nil, { summary = true }) + LazyVim.treesitter.ensure_treesitter_cli(function() + TS.update(nil, { summary = true }) + end) end, lazy = vim.fn.argc(-1) == 0, -- load treesitter early when opening a file from the cmdline event = { "LazyFile", "VeryLazy" }, @@ -59,18 +61,12 @@ return { -- some quick sanity checks if not TS.get_installed then return LazyVim.error("Please use `:Lazy` and update `nvim-treesitter`") - elseif vim.fn.executable("tree-sitter") == 0 then - return LazyVim.error({ - "**treesitter-main** requires the `tree-sitter` CLI executable to be installed.", - "Run `:checkhealth nvim-treesitter` for more information.", - }) elseif type(opts.ensure_installed) ~= "table" then return LazyVim.error("`nvim-treesitter` opts.ensure_installed must be a table") end -- setup treesitter TS.setup(opts) - LazyVim.treesitter.get_installed(true) -- initialize the installed langs -- install missing parsers @@ -78,8 +74,10 @@ return { return not LazyVim.treesitter.have(lang) end, opts.ensure_installed or {}) if #install > 0 then - TS.install(install, { summary = true }):await(function() - LazyVim.treesitter.get_installed(true) -- refresh the installed langs + LazyVim.treesitter.ensure_treesitter_cli(function() + TS.install(install, { summary = true }):await(function() + LazyVim.treesitter.get_installed(true) -- refresh the installed langs + end) end) end diff --git a/lua/lazyvim/util/treesitter.lua b/lua/lazyvim/util/treesitter.lua index 73e925fc..5df6aa53 100644 --- a/lua/lazyvim/util/treesitter.lua +++ b/lua/lazyvim/util/treesitter.lua @@ -33,4 +33,51 @@ function M.indentexpr() return M.have() and require("nvim-treesitter").indentexpr() or -1 end +---@param cb fun() +function M.ensure_treesitter_cli(cb) + if vim.fn.executable("tree-sitter") == 1 then + return cb() + end + + ---@param msg? string + local function fail(msg) + return LazyVim.error({ + "**treesitter-nvim** `main` requires the `tree-sitter` CLI executable to be installed.", + "Please install it manually from https://github.com/tree-sitter/tree-sitter/tree/master/crates/cli or", + "use your system package manager.", + "Run `:checkhealth nvim-treesitter` for more information.", + msg, + }) + end + + -- try installing with mason + if not pcall(require, "mason") then + return fail("`mason.nvim` is disabled in your config, so we cannot install it automatically.") + end + + -- check again since we might have installed it already + if vim.fn.executable("tree-sitter") == 1 then + return cb() + end + + local mr = require("mason-registry") + mr.refresh(function() + local p = mr.get_package("tree-sitter-cli") + if not p:is_installed() then + LazyVim.info("Installing `tree-sitter-cli` with `mason.nvim`...") + p:install( + nil, + vim.schedule_wrap(function(success) + if success then + LazyVim.info("Installed `tree-sitter-cli` with `mason.nvim`.") + cb() + else + fail("Failed to install `tree-sitter-cli` with `mason.nvim`.") + end + end) + ) + end + end) +end + return M From 1dece3be15bdd2e95e6997017b050fb08f01d143 Mon Sep 17 00:00:00 2001 From: folke <292349+folke@users.noreply.github.com> Date: Thu, 18 Sep 2025 07:51:02 +0000 Subject: [PATCH 4/5] chore(build): auto-generate docs --- doc/LazyVim.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/LazyVim.txt b/doc/LazyVim.txt index 9f4b59fd..5c3e670d 100644 --- a/doc/LazyVim.txt +++ b/doc/LazyVim.txt @@ -1,4 +1,4 @@ -*LazyVim.txt* For Neovim Last change: 2025 September 17 +*LazyVim.txt* For Neovim Last change: 2025 September 18 ============================================================================== Table of Contents *LazyVim-table-of-contents* From a467ce074f00edd1d2667e55afe72904c5aeaf24 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 18 Sep 2025 10:03:59 +0200 Subject: [PATCH 5/5] chore(main): release 15.1.0 (#6452) :robot: I have created a release *beep* *boop* --- ## [15.1.0](https://github.com/LazyVim/LazyVim/compare/v15.0.3...v15.1.0) (2025-09-18) ### Features * **treesitter:** automatically install and use mason's tree-sitter-cli if not installed on system ([725d048](https://github.com/LazyVim/LazyVim/commit/725d048e009b866425b2a0cc620ba2c413e8b65f)) * **treesitter:** refactored setting up treesitter indent/highlight/folds ([b93303d](https://github.com/LazyVim/LazyVim/commit/b93303d2339b1117171780cebed1d710fd3805d5)) ### Bug Fixes * **snacks:** safe wrapper around snacks statuscolumn to prevent errors when LazyVim is still installing ([5bf2378](https://github.com/LazyVim/LazyVim/commit/5bf237820d7938b1b6490164fbd75e4117d341c1)) --- 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 | 13 +++++++++++++ lua/lazyvim/config/init.lua | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/.release-please-manifest.json b/.github/.release-please-manifest.json index fbbae712..9da34491 100644 --- a/.github/.release-please-manifest.json +++ b/.github/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "15.0.3" + ".": "15.1.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index b6be3e05..7b8723e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [15.1.0](https://github.com/LazyVim/LazyVim/compare/v15.0.3...v15.1.0) (2025-09-18) + + +### Features + +* **treesitter:** automatically install and use mason's tree-sitter-cli if not installed on system ([725d048](https://github.com/LazyVim/LazyVim/commit/725d048e009b866425b2a0cc620ba2c413e8b65f)) +* **treesitter:** refactored setting up treesitter indent/highlight/folds ([b93303d](https://github.com/LazyVim/LazyVim/commit/b93303d2339b1117171780cebed1d710fd3805d5)) + + +### Bug Fixes + +* **snacks:** safe wrapper around snacks statuscolumn to prevent errors when LazyVim is still installing ([5bf2378](https://github.com/LazyVim/LazyVim/commit/5bf237820d7938b1b6490164fbd75e4117d341c1)) + ## [15.0.3](https://github.com/LazyVim/LazyVim/compare/v15.0.2...v15.0.3) (2025-09-17) diff --git a/lua/lazyvim/config/init.lua b/lua/lazyvim/config/init.lua index baad77a5..d12f2ac0 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.0.3" -- x-release-please-version +M.version = "15.1.0" -- x-release-please-version LazyVim.config = M ---@class LazyVimOptions