From 267c7525f738cdd6024c39da758e885c026ffaaa Mon Sep 17 00:00:00 2001 From: Riley Bruins Date: Wed, 2 Oct 2024 10:34:14 -0700 Subject: feat(treesitter): introduce child_with_descendant() This commit also marks `child_containing_descendant()` as deprecated (per upstream's documentation), and uses `child_with_descendant()` in its place. Minimum required tree-sitter version will now be `0.24`. --- runtime/lua/vim/treesitter/_meta/tsnode.lua | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/_meta/tsnode.lua b/runtime/lua/vim/treesitter/_meta/tsnode.lua index acc9f8d24e..d982b6a505 100644 --- a/runtime/lua/vim/treesitter/_meta/tsnode.lua +++ b/runtime/lua/vim/treesitter/_meta/tsnode.lua @@ -15,7 +15,7 @@ error('Cannot require a meta file') local TSNode = {} -- luacheck: no unused --- Get the node's immediate parent. ---- Prefer |TSNode:child_containing_descendant()| +--- Prefer |TSNode:child_with_descendant()| --- for iterating over the node's ancestors. --- @return TSNode? function TSNode:parent() end @@ -71,8 +71,24 @@ function TSNode:named_child(index) end --- Get the node's child that contains {descendant}. --- @param descendant TSNode --- @return TSNode? +--- @deprecated function TSNode:child_containing_descendant(descendant) end +--- Get the node's child that contains {descendant} (includes {descendant}). +--- +--- For example, with the following node hierarchy: +--- +--- ``` +--- a -> b -> c +--- +--- a:child_with_descendant(c) == b +--- a:child_with_descendant(b) == b +--- a:child_with_descendant(a) == nil +--- ``` +--- @param descendant TSNode +--- @return TSNode? +function TSNode:child_with_descendant(descendant) end + --- Get the node's start position. Return three values: the row, column and --- total byte count (all zero-based). --- @return integer, integer, integer -- cgit From d3193afc2559e7d84ed2d76664a650dc03b4c6ef Mon Sep 17 00:00:00 2001 From: Riley Bruins Date: Thu, 19 Sep 2024 13:08:22 -0700 Subject: fix(treesitter): remove duplicate symbol names in language.inspect() **Problems:** - `vim.treesitter.language.inspect()` returns duplicate symbol names, sometimes up to 6 of one kind in the case of `markdown` - The list-like `symbols` table can have holes and is thus not even a valid msgpack table anyway, mentioned in a test **Solution:** Return symbols as a map, rather than a list, where field names are the names of the symbol. The boolean value associated with the field encodes whether or not the symbol is named. Note that anonymous nodes are surrounded with double quotes (`"`) to prevent potential collisions with named counterparts that have the same identifier. --- runtime/lua/vim/treesitter/_query_linter.lua | 8 ++++++-- runtime/lua/vim/treesitter/language.lua | 7 ++++++- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index c5e4b86e1e..a825505378 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -240,8 +240,12 @@ function M.omnifunc(findstart, base) table.insert(items, text) end end - for _, s in pairs(parser_info.symbols) do - local text = s[2] and s[1] or string.format('%q', s[1]):gsub('\n', 'n') ---@type string + for text, named in + pairs(parser_info.symbols --[[@as table]]) + do + if not named then + text = string.format('%q', text:sub(2, -2)):gsub('\n', 'n') ---@type string + end if text:find(base, 1, true) then table.insert(items, text) end diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 9f7807e036..aa1d38df97 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -170,7 +170,12 @@ end --- Inspects the provided language. --- ---- Inspecting provides some useful information on the language like node names, ... +--- Inspecting provides some useful information on the language like node and field names, ABI +--- version, and whether the language came from a WASM module. +--- +--- Node names are returned in a table mapping each node name to a `boolean` indicating whether or +--- not the node is named (i.e., not anonymous). Anonymous nodes are surrounded with double quotes +--- (`"`). --- ---@param lang string Language ---@return table -- cgit From 3f3e4837d5f7d2d9cb1c89bd3a5b2ee8a730772a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 16 Oct 2024 17:03:48 +0100 Subject: perf(validate): use lighter version - Also fix `vim.validate()` for PUC Lua when showing errors for values that aren't string or number. --- runtime/lua/vim/treesitter/dev.lua | 4 +--- runtime/lua/vim/treesitter/language.lua | 8 +++----- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 90c3720b80..7b522ca92b 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -330,9 +330,7 @@ end --- --- @param opts vim.treesitter.dev.inspect_tree.Opts? function M.inspect_tree(opts) - vim.validate({ - opts = { opts, 't', true }, - }) + vim.validate('opts', opts, 'table', true) opts = opts or {} diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index aa1d38df97..ce12ca433a 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -108,11 +108,9 @@ function M.add(lang, opts) local path = opts.path local symbol_name = opts.symbol_name - vim.validate({ - lang = { lang, 'string' }, - path = { path, 'string', true }, - symbol_name = { symbol_name, 'string', true }, - }) + vim.validate('lang', lang, 'string') + vim.validate('path', path, 'string', true) + vim.validate('symbol_name', symbol_name, 'string', true) -- parser names are assumed to be lowercase (consistent behavior on case-insensitive file systems) lang = lang:lower() -- cgit From 18b43c331d8a0ed87d7cbefe2a18543b8e4ad360 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 17 Oct 2024 11:16:16 +0200 Subject: refactor: rename vim.highlight => vim.hl Problem: - `vim.highlight` module does not follow `:help dev-name-common`, which documents the name for "highlight" as "hl". - Shorter names are usually preferred. Solution: Rename `vim.highlight` to `vim.hl`. This is not a breaking change until 2.0 (or maybe never). --- runtime/lua/vim/treesitter/highlighter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index a94c408f4e..7bdcdc774a 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -328,7 +328,7 @@ local function on_line_impl(self, buf, line, is_spell_nav) -- The "priority" attribute can be set at the pattern level or on a particular capture local priority = ( tonumber(metadata.priority or metadata[capture] and metadata[capture].priority) - or vim.highlight.priorities.treesitter + or vim.hl.priorities.treesitter ) + spell_pri_offset -- The "conceal" attribute can be set at the pattern level or on a particular capture -- cgit From 3572319b4cb1a4163624a5fe328886f1928dbc4a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 18 Oct 2024 11:33:12 +0100 Subject: feat(vim.validate): improve fast form and deprecate spec form Problem: `vim.validate()` takes two forms when it only needs one. Solution: - Teach the fast form all the features of the spec form. - Deprecate the spec form. - General optimizations for both forms. - Add a `message` argument which can be used alongside or in place of the `optional` argument. --- runtime/lua/vim/treesitter/language.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index ce12ca433a..446051dfd7 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -154,10 +154,8 @@ end --- @param lang string Name of parser --- @param filetype string|string[] Filetype(s) to associate with lang function M.register(lang, filetype) - vim.validate({ - lang = { lang, 'string' }, - filetype = { filetype, { 'string', 'table' } }, - }) + vim.validate('lang', lang, 'string') + vim.validate('filetype', filetype, { 'string', 'table' }) for _, f in ipairs(ensure_list(filetype)) do if f ~= '' then -- cgit From f60a1f90599df0b773a107232f4005d6dea194b0 Mon Sep 17 00:00:00 2001 From: Riley Bruins Date: Fri, 25 Oct 2024 14:09:29 -0700 Subject: docs(treesitter): specify predicate boolean return value --- runtime/lua/vim/treesitter/query.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 4614967799..1677e8d364 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -626,7 +626,7 @@ local directive_handlers = { --- Adds a new predicate to be used in queries --- ---@param name string Name of the predicate, without leading # ----@param handler fun(match: table, pattern: integer, source: integer|string, predicate: any[], metadata: vim.treesitter.query.TSMetadata) +---@param handler fun(match: table, pattern: integer, source: integer|string, predicate: any[], metadata: vim.treesitter.query.TSMetadata): boolean? --- - see |vim.treesitter.query.add_directive()| for argument meanings ---@param opts? vim.treesitter.query.add_predicate.Opts function M.add_predicate(name, handler, opts) -- cgit From 2e3f1069f4991d80bb9fa8f712720fe7500bbd9b Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 2 Nov 2024 10:40:44 +0100 Subject: fix(health): better layout of vim.treesitter health check Problem: Long lists of available parsers make it hard to see WASM status. Solution: Add separate headings for "treesitter features" (ABI, WASM) and "treesitter parsers". Also add minimum supported ABI version. --- runtime/lua/vim/treesitter/health.lua | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua index 637f9ea543..53b64d1dec 100644 --- a/runtime/lua/vim/treesitter/health.lua +++ b/runtime/lua/vim/treesitter/health.lua @@ -4,10 +4,21 @@ local health = vim.health --- Performs a healthcheck for treesitter integration function M.check() - local parsers = vim.api.nvim_get_runtime_file('parser/*', true) + health.start('Treesitter features') + + health.info( + string.format( + 'Treesitter ABI support: min %d, max %d', + vim.treesitter.minimum_language_version, + ts.language_version + ) + ) - health.info(string.format('Nvim runtime ABI version: %d', ts.language_version)) + local can_wasm = vim._ts_add_language_from_wasm ~= nil + health.info(string.format('WASM parser support: %s', tostring(can_wasm))) + health.start('Treesitter parsers') + local parsers = vim.api.nvim_get_runtime_file('parser/*', true) for _, parser in pairs(parsers) do local parsername = vim.fn.fnamemodify(parser, ':t:r') local is_loadable, err_or_nil = pcall(ts.language.add, parsername) @@ -28,9 +39,6 @@ function M.check() ) end end - - local can_wasm = vim._ts_add_language_from_wasm ~= nil - health.info(string.format('Can load WASM parsers: %s', tostring(can_wasm))) end return M -- cgit From 99acc9de559a2ea3b9de2b418dbcae774d1d9a75 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 3 Nov 2024 11:28:31 +0800 Subject: fix(treesitter): close InspectTree/EditQuery window on BufUnload (#31036) Problem: The window opened :InspectTree or :EditQuery isn't closed when the source buffer is unloaded, even though it is closed when the buffer is hidden. Solution: Also close the window on BufUnload. --- runtime/lua/vim/treesitter/dev.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 7b522ca92b..d68a30cc11 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -527,7 +527,7 @@ function M.inspect_tree(opts) end, }) - api.nvim_create_autocmd('BufHidden', { + api.nvim_create_autocmd({ 'BufHidden', 'BufUnload' }, { group = group, buffer = buf, once = true, @@ -665,10 +665,10 @@ function M.edit_query(lang) api.nvim_buf_clear_namespace(query_buf, edit_ns, 0, -1) end, }) - api.nvim_create_autocmd('BufHidden', { + api.nvim_create_autocmd({ 'BufHidden', 'BufUnload' }, { group = group, buffer = buf, - desc = 'Close the editor window when the source buffer is hidden', + desc = 'Close the editor window when the source buffer is hidden or unloaded', once = true, callback = function() close_win(query_win) -- cgit From 86b737649bb8c51649a21033c0e365f53f2bc04a Mon Sep 17 00:00:00 2001 From: hykerr Date: Tue, 12 Nov 2024 12:26:07 +0100 Subject: fix(treesitter): add 'QuitPre' event to autocommands in inspect_tree Problem: Quitting source buffer for ```:InspectTree``` command raises ```E855``` when source buffer and tree views are the only open buffers. Solution: Add ```QuitPre``` event to autocmd handling closing/hiding the source buffer to close all open tree views. This allows nvim to quit when source and tree buffers are the only open windows. --- runtime/lua/vim/treesitter/dev.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index d68a30cc11..74d796f7fa 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -527,7 +527,7 @@ function M.inspect_tree(opts) end, }) - api.nvim_create_autocmd({ 'BufHidden', 'BufUnload' }, { + api.nvim_create_autocmd({ 'BufHidden', 'BufUnload', 'QuitPre' }, { group = group, buffer = buf, once = true, -- cgit From 6ef80eb42c730e66e5a769f619e05b353c08c118 Mon Sep 17 00:00:00 2001 From: Hyker Date: Fri, 15 Nov 2024 04:00:18 +0100 Subject: fix(treesitter): keep treeview open if source window is still open #31198 Problem: When there is a tree view opened by :InspectTree and the source buffer is open in multiple windows, closing one of the source windows will lead to the tree view being closed as well. Regression by #31181. Solution: Check how many source windows are open when trying to quit one. If there are more than one, keep the tree view(s) open. If the only source window is closed, also close the tree view(s). fix #31196 --- runtime/lua/vim/treesitter/dev.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 74d796f7fa..26817cdba5 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -530,12 +530,19 @@ function M.inspect_tree(opts) api.nvim_create_autocmd({ 'BufHidden', 'BufUnload', 'QuitPre' }, { group = group, buffer = buf, - once = true, callback = function() + -- don't close inpector window if source buffer + -- has more than one open window + if #vim.fn.win_findbuf(buf) > 1 then + return + end + -- close all tree windows for _, window in pairs(vim.fn.win_findbuf(b)) do close_win(window) end + + return true end, }) end -- cgit From cdc9baeaf89eb09f08427a09e3a0f86d56dcc812 Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Sun, 17 Nov 2024 01:25:10 +0100 Subject: fix(treesitter): remove redundant on_bytes callback #31041 Problem: Treesitter highlighter implements an on_bytes callback that just re-marks a buffer range for redraw. The edit that prompted the callback will already have done that. Solution: Remove redundant on_bytes callback from the treesitter highlighter module. --- runtime/lua/vim/treesitter/highlighter.lua | 10 ---------- runtime/lua/vim/treesitter/languagetree.lua | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 7bdcdc774a..4ad62f4816 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -93,9 +93,6 @@ function TSHighlighter.new(tree, opts) opts = opts or {} ---@type { queries: table } self.tree = tree tree:register_cbs({ - on_bytes = function(...) - self:on_bytes(...) - end, on_detach = function() self:on_detach() end, @@ -214,13 +211,6 @@ function TSHighlighter:for_each_highlight_state(fn) end end ----@package ----@param start_row integer ----@param new_end integer -function TSHighlighter:on_bytes(_, _, start_row, _, _, _, _, _, new_end) - api.nvim__redraw({ buf = self.bufnr, range = { start_row, start_row + new_end + 1 } }) -end - ---@package function TSHighlighter:on_detach() self:destroy() diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index fd68c2b910..4b42164dc8 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -1037,7 +1037,7 @@ end --- Registers callbacks for the [LanguageTree]. ---@param cbs table An [nvim_buf_attach()]-like table argument with the following handlers: ---- - `on_bytes` : see [nvim_buf_attach()], but this will be called _after_ the parsers callback. +--- - `on_bytes` : see [nvim_buf_attach()]. --- - `on_changedtree` : a callback that will be called every time the tree has syntactical changes. --- It will be passed two arguments: a table of the ranges (as node ranges) that --- changed and the changed tree. -- cgit From 235cb5bc5f2553f5a46807267b8705e53f7a14af Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Sun, 17 Nov 2024 20:43:36 +0100 Subject: fix(api): update "range" windows in nvim__redraw #31042 Problem: nvim__redraw's "range" marks a buffer range for redraw, and subsequently flushes the UI without updating the windows containing that buffer. Solution: Implicitly update the screen, unless specified otherwise. Only update the screen with the last call of the treesitter on_changedtree() callback. --- runtime/lua/vim/treesitter/highlighter.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 4ad62f4816..05124c29f0 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -219,8 +219,8 @@ end ---@package ---@param changes Range6[] function TSHighlighter:on_changedtree(changes) - for _, ch in ipairs(changes) do - api.nvim__redraw({ buf = self.bufnr, range = { ch[1], ch[4] + 1 } }) + for i, ch in ipairs(changes) do + api.nvim__redraw({ buf = self.bufnr, range = { ch[1], ch[4] + 1 }, flush = i == #changes }) end end -- cgit From 40347f6e27f1594797ecb0b268076a94630e4c1b Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Mon, 18 Nov 2024 15:35:21 +0100 Subject: fix(api): only flush nvim__redraw when necessary #31250 Problem: Not possible to only set a "redraw later" type with nvim__redraw, which seems to be desired for the treesitter highlighter. Solution: Do not update the screen when "flush" is explicitly set to false and only redraw later types are present. In that case, do not call ui_flush() either. --- runtime/lua/vim/treesitter/highlighter.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim/treesitter') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 05124c29f0..8ce8652f7d 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -219,8 +219,8 @@ end ---@package ---@param changes Range6[] function TSHighlighter:on_changedtree(changes) - for i, ch in ipairs(changes) do - api.nvim__redraw({ buf = self.bufnr, range = { ch[1], ch[4] + 1 }, flush = i == #changes }) + for _, ch in ipairs(changes) do + api.nvim__redraw({ buf = self.bufnr, range = { ch[1], ch[4] + 1 }, flush = false }) end end -- cgit