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