mirror of
https://github.com/LazyVim/LazyVim.git
synced 2025-12-25 12:14:19 +01:00
feat(treesitter)!: migrate to nvim-treesitter **main** branch
This commit is contained in:
4
NEWS.md
4
NEWS.md
@@ -11,8 +11,8 @@ Going forward, **LazyVim** requires **Neovim** `>= 0.11.2`, and drops support fo
|
||||
- removed compatibility code for Neovim `< 0.11.2`
|
||||
- configure **LSP** with the native `vim.lsp.config`
|
||||
- migrated **mason.nvim** and **mason-lspconfig.nvim** to `v2.x`
|
||||
- added new `treesitter-main` extra to test the new `main` branch of `nvim-treesitter`
|
||||
- after enabling, you will get errors. Update with `:Lazy` and restart Neovim
|
||||
- migrated to [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter/tree/main) **main** branch
|
||||
- replace `nvim-treesitter` incremental selection with `flash.nvim`, since it is no longer supported
|
||||
- enabled [blink.cmp](https://github.com/saghen/blink.cmp) **cmdline** completions
|
||||
- use **LSP** based folding when available (disable with `nvim-lspconfig.folds.enabled = false`)
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ opt.fillchars = {
|
||||
diff = "╱",
|
||||
eob = " ",
|
||||
}
|
||||
opt.foldexpr = "v:lua.require'lazyvim.util'.ui.foldexpr()"
|
||||
opt.foldexpr = "v:lua.LazyVim.ui.foldexpr()" -- treesitter folds
|
||||
opt.foldlevel = 99
|
||||
opt.foldmethod = "expr"
|
||||
opt.foldtext = ""
|
||||
@@ -78,6 +78,7 @@ 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.ui.indentexpr()" -- treesitter indents
|
||||
opt.jumpoptions = "view"
|
||||
opt.laststatus = 3 -- global statusline
|
||||
opt.linebreak = true -- Wrap lines at convenient points
|
||||
|
||||
@@ -40,6 +40,16 @@ return {
|
||||
{ "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" },
|
||||
{ "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" },
|
||||
{ "<c-s>", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" },
|
||||
-- Simulate nvim-treesitter incremental selection
|
||||
{ "<c-space>", mode = { "n", "o", "x" },
|
||||
function()
|
||||
require("flash").treesitter({
|
||||
actions = {
|
||||
["<c-space>"] = "next",
|
||||
["<BS>"] = "prev"
|
||||
}
|
||||
})
|
||||
end, desc = "Treesitter Incremental Selection" },
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
return {
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
version = false, -- last release is way too old and doesn't work on Windows
|
||||
branch = "main",
|
||||
build = ":TSUpdate",
|
||||
lazy = true,
|
||||
cmd = { "TSUpdate", "TSInstall", "TSLog", "TSUninstall" },
|
||||
init = function() end,
|
||||
---@param opts TSConfig
|
||||
config = function(_, opts)
|
||||
if vim.fn.executable("tree-sitter") == 0 then
|
||||
LazyVim.error("**treesitter-main** requires the `tree-sitter` executable to be installed")
|
||||
return
|
||||
end
|
||||
if type(opts.ensure_installed) ~= "table" then
|
||||
error("opts.ensure_installed must be a table")
|
||||
end
|
||||
|
||||
local TS = require("nvim-treesitter")
|
||||
TS.setup(opts)
|
||||
|
||||
local needed = LazyVim.dedup(opts.ensure_installed --[[@as string[] ]])
|
||||
local installed = TS.get_installed("parsers")
|
||||
local install = vim.tbl_filter(function(lang)
|
||||
return not vim.tbl_contains(installed, lang)
|
||||
end, needed)
|
||||
|
||||
if #install > 0 then
|
||||
TS.install(install, { summary = true })
|
||||
vim.list_extend(installed, install)
|
||||
end
|
||||
|
||||
-- backwards compatibility with the old treesitter config for highlight and indent
|
||||
local highlight, indent = vim.tbl_get(opts, "highlight", "enable"), vim.tbl_get(opts, "indent", "enable")
|
||||
if highlight or indent then
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
callback = function(ev)
|
||||
local lang = vim.treesitter.language.get_lang(ev.match)
|
||||
if not vim.tbl_contains(installed, lang) then
|
||||
return
|
||||
end
|
||||
if highlight then
|
||||
pcall(vim.treesitter.start)
|
||||
end
|
||||
if indent then
|
||||
vim.bo[ev.buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
end,
|
||||
},
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter-textobjects",
|
||||
branch = "main",
|
||||
event = "VeryLazy",
|
||||
opts = {},
|
||||
keys = function()
|
||||
local moves = {
|
||||
goto_next_start = { ["]f"] = "@function.outer", ["]c"] = "@class.outer", ["]a"] = "@parameter.inner" },
|
||||
goto_next_end = { ["]F"] = "@function.outer", ["]C"] = "@class.outer", ["]A"] = "@parameter.inner" },
|
||||
goto_previous_start = { ["[f"] = "@function.outer", ["[c"] = "@class.outer", ["[a"] = "@parameter.inner" },
|
||||
goto_previous_end = { ["[F"] = "@function.outer", ["[C"] = "@class.outer", ["[A"] = "@parameter.inner" },
|
||||
}
|
||||
local ret = {} ---@type LazyKeysSpec[]
|
||||
for method, keymaps in pairs(moves) do
|
||||
for key, query in pairs(keymaps) do
|
||||
local desc = query:gsub("@", ""):gsub("%..*", "")
|
||||
desc = desc:sub(1, 1):upper() .. desc:sub(2)
|
||||
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")
|
||||
ret[#ret + 1] = {
|
||||
key,
|
||||
function()
|
||||
require("nvim-treesitter-textobjects.move")[method](query, "textobjects")
|
||||
end,
|
||||
desc = desc,
|
||||
mode = { "n", "x", "o" },
|
||||
silent = true,
|
||||
}
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end,
|
||||
config = function(_, opts)
|
||||
require("nvim-treesitter-textobjects").setup(opts)
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -1,43 +1,25 @@
|
||||
return {
|
||||
{
|
||||
"folke/which-key.nvim",
|
||||
opts = {
|
||||
spec = {
|
||||
{ "<BS>", desc = "Decrement Selection", mode = "x" },
|
||||
{ "<c-space>", desc = "Increment Selection", mode = { "x", "n" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- Treesitter is a new parser generator tool that we can
|
||||
-- use in Neovim to power faster and more accurate
|
||||
-- syntax highlighting.
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
branch = "main",
|
||||
version = false, -- last release is way too old and doesn't work on Windows
|
||||
build = ":TSUpdate",
|
||||
event = { "LazyFile", "VeryLazy" },
|
||||
lazy = vim.fn.argc(-1) == 0, -- load treesitter early when opening a file from the cmdline
|
||||
init = function(plugin)
|
||||
-- PERF: add nvim-treesitter queries to the rtp and it's custom query predicates early
|
||||
-- This is needed because a bunch of plugins no longer `require("nvim-treesitter")`, which
|
||||
-- no longer trigger the **nvim-treesitter** module to be loaded in time.
|
||||
-- Luckily, the only things that those plugins need are the custom queries, which we make available
|
||||
-- during startup.
|
||||
require("lazy.core.loader").add_to_rtp(plugin)
|
||||
require("nvim-treesitter.query_predicates")
|
||||
build = function()
|
||||
local TS = require("nvim-treesitter")
|
||||
if not TS.get_installed then
|
||||
LazyVim.error("Please restart Neovim and run `:TSUpdate` to use the `nvim-treesitter` **main** branch.")
|
||||
return
|
||||
end
|
||||
vim.cmd.TSUpdate()
|
||||
end,
|
||||
cmd = { "TSUpdateSync", "TSUpdate", "TSInstall" },
|
||||
keys = {
|
||||
{ "<c-space>", desc = "Increment Selection" },
|
||||
{ "<bs>", desc = "Decrement Selection", mode = "x" },
|
||||
},
|
||||
lazy = vim.fn.argc(-1) == 0, -- load treesitter early when opening a file from the cmdline
|
||||
event = { "LazyFile", "VeryLazy" },
|
||||
cmd = { "TSUpdate", "TSInstall", "TSLog", "TSUninstall" },
|
||||
opts_extend = { "ensure_installed" },
|
||||
---@type TSConfig
|
||||
---@diagnostic disable-next-line: missing-fields
|
||||
opts = {
|
||||
highlight = { enable = true },
|
||||
indent = { enable = true },
|
||||
ensure_installed = {
|
||||
"bash",
|
||||
"c",
|
||||
@@ -64,65 +46,91 @@ return {
|
||||
"xml",
|
||||
"yaml",
|
||||
},
|
||||
incremental_selection = {
|
||||
enable = true,
|
||||
keymaps = {
|
||||
init_selection = "<C-space>",
|
||||
node_incremental = "<C-space>",
|
||||
scope_incremental = false,
|
||||
node_decremental = "<bs>",
|
||||
},
|
||||
},
|
||||
textobjects = {
|
||||
move = {
|
||||
enable = true,
|
||||
goto_next_start = { ["]f"] = "@function.outer", ["]c"] = "@class.outer", ["]a"] = "@parameter.inner" },
|
||||
goto_next_end = { ["]F"] = "@function.outer", ["]C"] = "@class.outer", ["]A"] = "@parameter.inner" },
|
||||
goto_previous_start = { ["[f"] = "@function.outer", ["[c"] = "@class.outer", ["[a"] = "@parameter.inner" },
|
||||
goto_previous_end = { ["[F"] = "@function.outer", ["[C"] = "@class.outer", ["[A"] = "@parameter.inner" },
|
||||
},
|
||||
},
|
||||
},
|
||||
---@param plugin LazyPlugin
|
||||
---@param opts TSConfig
|
||||
config = function(_, opts)
|
||||
if type(opts.ensure_installed) == "table" then
|
||||
opts.ensure_installed = LazyVim.dedup(opts.ensure_installed)
|
||||
config = function(plugin, opts)
|
||||
if vim.fn.executable("tree-sitter") == 0 then
|
||||
LazyVim.error("**treesitter-main** requires the `tree-sitter` executable to be installed")
|
||||
return
|
||||
end
|
||||
require("nvim-treesitter.configs").setup(opts)
|
||||
if type(opts.ensure_installed) ~= "table" then
|
||||
LazyVim.error("`nvim-treesitter` opts.ensure_installed must be a table")
|
||||
end
|
||||
|
||||
local TS = require("nvim-treesitter")
|
||||
if not TS.get_installed then
|
||||
LazyVim.error("Please use `:Lazy` and update `nvim-treesitter`")
|
||||
return
|
||||
end
|
||||
TS.setup(opts)
|
||||
|
||||
local needed = LazyVim.dedup(opts.ensure_installed --[[@as string[] ]])
|
||||
LazyVim.ui.installed = TS.get_installed("parsers")
|
||||
|
||||
local install = vim.tbl_filter(function(lang)
|
||||
return not LazyVim.ui.have(lang)
|
||||
end, needed)
|
||||
|
||||
if #install > 0 then
|
||||
TS.install(install, { summary = true }):await(function()
|
||||
LazyVim.ui.installed = TS.get_installed("parsers")
|
||||
end)
|
||||
end
|
||||
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
callback = function(ev)
|
||||
if LazyVim.ui.have(ev.match) then
|
||||
pcall(vim.treesitter.start)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter-textobjects",
|
||||
branch = "main",
|
||||
event = "VeryLazy",
|
||||
enabled = true,
|
||||
config = function()
|
||||
-- If treesitter is already loaded, we need to run config again for textobjects
|
||||
if LazyVim.is_loaded("nvim-treesitter") then
|
||||
local opts = LazyVim.opts("nvim-treesitter")
|
||||
require("nvim-treesitter.configs").setup({ textobjects = opts.textobjects })
|
||||
end
|
||||
|
||||
-- When in diff mode, we want to use the default
|
||||
-- vim text objects c & C instead of the treesitter ones.
|
||||
local move = require("nvim-treesitter.textobjects.move") ---@type table<string,fun(...)>
|
||||
local configs = require("nvim-treesitter.configs")
|
||||
for name, fn in pairs(move) do
|
||||
if name:find("goto") == 1 then
|
||||
move[name] = function(q, ...)
|
||||
if vim.wo.diff then
|
||||
local config = configs.get_module("textobjects.move")[name] ---@type table<string,string>
|
||||
for key, query in pairs(config or {}) do
|
||||
if q == query and key:find("[%]%[][cC]") then
|
||||
vim.cmd("normal! " .. key)
|
||||
return
|
||||
end
|
||||
opts = {},
|
||||
keys = function()
|
||||
local moves = {
|
||||
goto_next_start = { ["]f"] = "@function.outer", ["]c"] = "@class.outer", ["]a"] = "@parameter.inner" },
|
||||
goto_next_end = { ["]F"] = "@function.outer", ["]C"] = "@class.outer", ["]A"] = "@parameter.inner" },
|
||||
goto_previous_start = { ["[f"] = "@function.outer", ["[c"] = "@class.outer", ["[a"] = "@parameter.inner" },
|
||||
goto_previous_end = { ["[F"] = "@function.outer", ["[C"] = "@class.outer", ["[A"] = "@parameter.inner" },
|
||||
}
|
||||
local ret = {} ---@type LazyKeysSpec[]
|
||||
for method, keymaps in pairs(moves) do
|
||||
for key, query in pairs(keymaps) do
|
||||
local desc = query:gsub("@", ""):gsub("%..*", "")
|
||||
desc = desc:sub(1, 1):upper() .. desc:sub(2)
|
||||
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")
|
||||
ret[#ret + 1] = {
|
||||
key,
|
||||
function()
|
||||
-- don't use treesitter if in diff mode and the key is one of the c/C keys
|
||||
if vim.wo.diff and key:find("[cC]") then
|
||||
return vim.cmd("normal! " .. key)
|
||||
end
|
||||
end
|
||||
return fn(q, ...)
|
||||
end
|
||||
require("nvim-treesitter-textobjects.move")[method](query, "textobjects")
|
||||
end,
|
||||
desc = desc,
|
||||
mode = { "n", "x", "o" },
|
||||
silent = true,
|
||||
}
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end,
|
||||
config = function(_, opts)
|
||||
local TS = require("nvim-treesitter-textobjects")
|
||||
if not TS.setup then
|
||||
LazyVim.error("Please use `:Lazy` and update `nvim-treesitter`")
|
||||
return
|
||||
end
|
||||
TS.setup(opts)
|
||||
end,
|
||||
},
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ M.deprecated_extras = {
|
||||
["lazyvim.plugins.extras.ui.dashboard"] = "`dashboard.nvim` is now the default **LazyVim** starter.",
|
||||
["lazyvim.plugins.extras.coding.native_snippets"] = "Native snippets are now the default for **Neovim >= 0.10**",
|
||||
["lazyvim.plugins.extras.ui.treesitter-rewrite"] = "Disabled `treesitter-rewrite` extra for now. Not ready yet.",
|
||||
["lazyvim.plugins.extras.ui.treesitter-main"] = "the `nvim-treesitter` main branch is now used by default",
|
||||
["lazyvim.plugins.extras.coding.mini-ai"] = "`mini.ai` is now a core LazyVim plugin (again)",
|
||||
["lazyvim.plugins.extras.lazyrc"] = "local spec files are now a lazy.nvim feature",
|
||||
["lazyvim.plugins.extras.editor.trouble-v3"] = "Trouble v3 has been merged in main",
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
---@class lazyvim.util.ui
|
||||
local M = {}
|
||||
|
||||
-- optimized treesitter foldexpr
|
||||
M.installed = {} ---@type string[]
|
||||
|
||||
---@param ft string
|
||||
function M.have(ft)
|
||||
local lang = vim.treesitter.language.get_lang(ft)
|
||||
return vim.tbl_contains(M.installed, lang)
|
||||
end
|
||||
|
||||
function M.foldexpr()
|
||||
local buf = vim.api.nvim_get_current_buf()
|
||||
if vim.b[buf].ts_folds == nil then
|
||||
-- as long as we don't have a filetype, don't bother
|
||||
-- checking if treesitter is available (it won't)
|
||||
if vim.bo[buf].filetype == "" then
|
||||
return "0"
|
||||
end
|
||||
if vim.bo[buf].filetype:find("dashboard") then
|
||||
vim.b[buf].ts_folds = false
|
||||
else
|
||||
vim.b[buf].ts_folds = pcall(vim.treesitter.get_parser, buf)
|
||||
end
|
||||
end
|
||||
return vim.b[buf].ts_folds and vim.treesitter.foldexpr() or "0"
|
||||
return M.have(vim.b[buf].filetype) and vim.treesitter.foldexpr() or "0"
|
||||
end
|
||||
|
||||
function M.indentexpr()
|
||||
local buf = vim.api.nvim_get_current_buf()
|
||||
return M.have(vim.b[buf].filetype) and require("nvim-treesitter").indentexpr() or -1
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
Reference in New Issue
Block a user