mirror of
https://github.com/LazyVim/LazyVim.git
synced 2025-12-25 12:14:19 +01:00
## Description
<!-- Describe the big picture of your changes to communicate to the
maintainers
why we should accept this pull request. -->
`treesitter-textobjects` mappings accept a table query (for the "move"
mappings, at least, I haven't checked the others). Currently, in
LazyVim, using a table causes an error due to the assumption that
`query` is a string in the `config` function that creates the keymap
description. This PR adds a simple loop to gather the queries from a
table and join them with "or" in the description.
Here is an example config and the resulting error. Everything works as
expected with the PR and string (single) queries still behave as
expected.
```lua
{
"nvim-treesitter/nvim-treesitter-textobjects",
opts = {
move = {
keys = {
goto_next_start = { ["]j"] = { "@function.outer", "@class.outer" } },
goto_next_end = { ["]J"] = { "@function.outer", "@class.outer" } },
goto_previous_start = { ["[j"] = { "@function.outer", "@class.outer" } },
goto_previous_end = { ["[J"] = { "@function.outer", "@class.outer" } },
},
},
},
}
```
```lua
Failed to run `config` for nvim-treesitter-textobjects
...vim-local/opt/LazyVim/lua/lazyvim/plugins/treesitter.lua:174: attempt to call method 'gsub' (a nil value)
# stacktrace:
- repos/nvim-local/opt/LazyVim/lua/lazyvim/plugins/treesitter.lua:174
- vim/shared.lua:0 _in_ **tbl_map**
- repos/nvim-local/opt/LazyVim/lua/lazyvim/plugins/treesitter.lua:197 _in_ **config**
```
## Checklist
- [x] I've read the
[CONTRIBUTING](https://github.com/LazyVim/LazyVim/blob/main/CONTRIBUTING.md)
guidelines.
214 lines
7.1 KiB
Lua
214 lines
7.1 KiB
Lua
return {
|
|
|
|
-- 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 = 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
|
|
-- make sure we're using the latest treesitter util
|
|
package.loaded["lazyvim.util.treesitter"] = nil
|
|
LazyVim.treesitter.build(function()
|
|
TS.update(nil, { summary = true })
|
|
end)
|
|
end,
|
|
event = { "LazyFile", "VeryLazy" },
|
|
cmd = { "TSUpdate", "TSInstall", "TSLog", "TSUninstall" },
|
|
opts_extend = { "ensure_installed" },
|
|
---@alias lazyvim.TSFeat { enable?: boolean, disable?: string[] }
|
|
---@class lazyvim.TSConfig: TSConfig
|
|
opts = {
|
|
-- LazyVim config for treesitter
|
|
indent = { enable = true }, ---@type lazyvim.TSFeat
|
|
highlight = { enable = true }, ---@type lazyvim.TSFeat
|
|
folds = { enable = true }, ---@type lazyvim.TSFeat
|
|
ensure_installed = {
|
|
"bash",
|
|
"c",
|
|
"diff",
|
|
"html",
|
|
"javascript",
|
|
"jsdoc",
|
|
"json",
|
|
"jsonc",
|
|
"lua",
|
|
"luadoc",
|
|
"luap",
|
|
"markdown",
|
|
"markdown_inline",
|
|
"printf",
|
|
"python",
|
|
"query",
|
|
"regex",
|
|
"toml",
|
|
"tsx",
|
|
"typescript",
|
|
"vim",
|
|
"vimdoc",
|
|
"xml",
|
|
"yaml",
|
|
},
|
|
},
|
|
---@param opts lazyvim.TSConfig
|
|
config = function(_, opts)
|
|
local TS = require("nvim-treesitter")
|
|
|
|
setmetatable(require("nvim-treesitter.install"), {
|
|
__newindex = function(_, k)
|
|
if k == "compilers" then
|
|
vim.schedule(function()
|
|
LazyVim.error({
|
|
"Setting custom compilers for `nvim-treesitter` is no longer supported.",
|
|
"",
|
|
"For more info, see:",
|
|
"- [compilers](https://docs.rs/cc/latest/cc/#compile-time-requirements)",
|
|
})
|
|
end)
|
|
end
|
|
end,
|
|
})
|
|
|
|
-- some quick sanity checks
|
|
if not TS.get_installed then
|
|
return LazyVim.error("Please use `:Lazy` and update `nvim-treesitter`")
|
|
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
|
|
local install = vim.tbl_filter(function(lang)
|
|
return not LazyVim.treesitter.have(lang)
|
|
end, opts.ensure_installed or {})
|
|
if #install > 0 then
|
|
LazyVim.treesitter.build(function()
|
|
TS.install(install, { summary = true }):await(function()
|
|
LazyVim.treesitter.get_installed(true) -- refresh the installed langs
|
|
end)
|
|
end)
|
|
end
|
|
|
|
vim.api.nvim_create_autocmd("FileType", {
|
|
group = vim.api.nvim_create_augroup("lazyvim_treesitter", { clear = true }),
|
|
callback = function(ev)
|
|
local ft, lang = ev.match, vim.treesitter.language.get_lang(ev.match)
|
|
if not LazyVim.treesitter.have(ft) then
|
|
return
|
|
end
|
|
|
|
---@param feat string
|
|
---@param query string
|
|
local function enabled(feat, query)
|
|
local f = opts[feat] or {} ---@type lazyvim.TSFeat
|
|
return f.enable ~= false
|
|
and not (type(f.disable) == "table" and vim.tbl_contains(f.disable, lang))
|
|
and LazyVim.treesitter.have(ft, query)
|
|
end
|
|
|
|
-- highlighting
|
|
if enabled("highlight", "highlights") then
|
|
pcall(vim.treesitter.start, ev.buf)
|
|
end
|
|
|
|
-- indents
|
|
if enabled("indent", "indents") then
|
|
LazyVim.set_default("indentexpr", "v:lua.LazyVim.treesitter.indentexpr()")
|
|
end
|
|
|
|
-- folds
|
|
if enabled("folds", "folds") then
|
|
if LazyVim.set_default("foldmethod", "expr") then
|
|
LazyVim.set_default("foldexpr", "v:lua.LazyVim.treesitter.foldexpr()")
|
|
end
|
|
end
|
|
end,
|
|
})
|
|
end,
|
|
},
|
|
|
|
{
|
|
"nvim-treesitter/nvim-treesitter-textobjects",
|
|
branch = "main",
|
|
event = "VeryLazy",
|
|
opts = {
|
|
move = {
|
|
enable = true,
|
|
set_jumps = true, -- whether to set jumps in the jumplist
|
|
-- LazyVim extention to create buffer-local keymaps
|
|
keys = {
|
|
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" },
|
|
},
|
|
},
|
|
},
|
|
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)
|
|
|
|
local function attach(buf)
|
|
local ft = vim.bo[buf].filetype
|
|
if not (vim.tbl_get(opts, "move", "enable") and LazyVim.treesitter.have(ft, "textobjects")) then
|
|
return
|
|
end
|
|
---@type table<string, table<string, string>>
|
|
local moves = vim.tbl_get(opts, "move", "keys") or {}
|
|
|
|
for method, keymaps in pairs(moves) do
|
|
for key, query in pairs(keymaps) do
|
|
local queries = type(query) == "table" and query or { query }
|
|
local parts = {}
|
|
for _, q in ipairs(queries) do
|
|
local part = q:gsub("@", ""):gsub("%..*", "")
|
|
part = part:sub(1, 1):upper() .. part:sub(2)
|
|
table.insert(parts, part)
|
|
end
|
|
local desc = table.concat(parts, " or ")
|
|
desc = (key:sub(1, 1) == "[" and "Prev " or "Next ") .. desc
|
|
desc = 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
|
|
end
|
|
end
|
|
end
|
|
|
|
vim.api.nvim_create_autocmd("FileType", {
|
|
group = vim.api.nvim_create_augroup("lazyvim_treesitter_textobjects", { clear = true }),
|
|
callback = function(ev)
|
|
attach(ev.buf)
|
|
end,
|
|
})
|
|
vim.tbl_map(attach, vim.api.nvim_list_bufs())
|
|
end,
|
|
},
|
|
|
|
-- Automatically add closing tags for HTML and JSX
|
|
{
|
|
"windwp/nvim-ts-autotag",
|
|
event = "LazyFile",
|
|
opts = {},
|
|
},
|
|
}
|