From 3aba4ba37859e4407eff2bb3f4d99c44b108ed79 Mon Sep 17 00:00:00 2001 From: Quentin Rasmont Date: Fri, 22 Apr 2022 21:50:52 +0200 Subject: feat(treesitter): upstream is_parent() Util from the nvim-treesitter project. Renamed is_parent to is_ancestor for clarity. --- runtime/lua/vim/treesitter.lua | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 70f2c425ed..37ab59b259 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -118,4 +118,27 @@ function M.get_string_parser(str, lang, opts) return LanguageTree.new(str, lang, opts) end +--- Determines whether a node is the ancestor of another +--- +---@param dest table the possible ancestor +---@param source table the possible descendant node +--- +---@returns (boolean) True if dest is an ancestor of source +function M.is_ancestor(dest, source) + if not (dest and source) then + return false + end + + local current = source + while current ~= nil do + if current == dest then + return true + end + + current = current:parent() + end + + return false +end + return M -- cgit From 133ff6e11ea862c7425d9c6a2827b20c97cf297f Mon Sep 17 00:00:00 2001 From: Quentin Rasmont Date: Thu, 2 Jun 2022 18:13:05 +0200 Subject: feat(treesitter): upstream node_contains() Util from the nvim-treesitter project. --- runtime/lua/vim/treesitter.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 37ab59b259..0936d62296 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -141,4 +141,17 @@ function M.is_ancestor(dest, source) return false end +---Determines if a node contains a range +---@param node table The node +---@param range table The range +--- +---@returns (boolean) True if the node contains the range +function M.node_contains(node, range) + local start_row, start_col, end_row, end_col = node:range() + local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) + local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4]) + + return start_fits and end_fits +end + return M -- cgit From 244a115e494bce8e8205c04a6e5f3ab74ec4ed65 Mon Sep 17 00:00:00 2001 From: Quentin Rasmont Date: Sun, 24 Jul 2022 20:49:33 +0200 Subject: feat(treesitter): clarify similar 'get_node_range' functions The private 'get_node_range' function from the languagetree module has been renamed and remains private as it serve a purpose that is only relevant inside the languagetree module. The 'get_node_range' upstreamed from nvim-treesitter in the treesitter module has been made public as it is in itself a utlity function. --- runtime/lua/vim/treesitter.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 0936d62296..82d41070ee 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -141,6 +141,19 @@ function M.is_ancestor(dest, source) return false end +--- Get the node's range or unpack a range table +--- +---@param node_or_range table +--- +---@returns start_row, start_col, end_row, end_col +function M.get_node_range(node_or_range) + if type(node_or_range) == 'table' then + return unpack(node_or_range) + else + return node_or_range:range() + end +end + ---Determines if a node contains a range ---@param node table The node ---@param range table The range -- cgit From 064ecb9ec581ec68f1376cde5ad7f960419b0324 Mon Sep 17 00:00:00 2001 From: Quentin Rasmont Date: Thu, 2 Jun 2022 20:07:08 +0200 Subject: feat(treesitter): upstream get_hl_groups_at_position() Util from the nvim-treesitter project. --- runtime/lua/vim/treesitter.lua | 57 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 82d41070ee..8ba4525003 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -2,6 +2,7 @@ local a = vim.api local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') local LanguageTree = require('vim.treesitter.languagetree') +local highlighter = require('vim.treesitter.highlighter') -- TODO(bfredl): currently we retain parsers for the lifetime of the buffer. -- Consider use weak references to release parser if all plugins are done with @@ -167,4 +168,60 @@ function M.node_contains(node, range) return start_fits and end_fits end +---Gets a list of highlight group for a given cursor position +---@param bufnr number The buffer number +---@param row number The position row +---@param col number The position column +--- +---@returns (table) A table of highlight groups +function M.get_hl_groups_at_position(bufnr, row, col) + local buf_highlighter = highlighter.active[bufnr] + + if not buf_highlighter then + return {} + end + + local matches = {} + + buf_highlighter.tree:for_each_tree(function(tstree, tree) + if not tstree then + return + end + + local root = tstree:root() + local root_start_row, _, root_end_row, _ = root:range() + + -- Only worry about trees within the line range + if root_start_row > row or root_end_row < row then + return + end + + local q = buf_highlighter:get_query(tree:lang()) + + -- Some injected languages may not have highlight queries. + if not q:query() then + return + end + + local iter = q:query():iter_captures(root, buf_highlighter.bufnr, row, row + 1) + + for capture, node, metadata in iter do + local hl = q.hl_cache[capture] + + if hl and M.is_in_node_range(node, row, col) then + local c = q._query.captures[capture] -- name of the capture in the query + if c ~= nil then + local general_hl, is_vim_hl = q:_get_hl_from_capture(capture) + local local_hl = not is_vim_hl and (tree:lang() .. general_hl) + table.insert( + matches, + { capture = c, specific = local_hl, general = general_hl, priority = metadata.priority } + ) + end + end + end + end, true) + return matches +end + return M -- cgit From b04ef7f6b966c44b12dbc65b17a761ae9313d6c4 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 25 Aug 2022 21:41:52 +0200 Subject: fix(treesitter): make it get_captures_at_position --- runtime/lua/vim/treesitter.lua | 45 +++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 14 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 8ba4525003..6431162799 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -2,7 +2,6 @@ local a = vim.api local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') local LanguageTree = require('vim.treesitter.languagetree') -local highlighter = require('vim.treesitter.highlighter') -- TODO(bfredl): currently we retain parsers for the lifetime of the buffer. -- Consider use weak references to release parser if all plugins are done with @@ -155,6 +154,28 @@ function M.get_node_range(node_or_range) end end +---Determines whether (line, col) position is in node range +--- +---@param node Node defining the range +---@param line A line (0-based) +---@param col A column (0-based) +function M.is_in_node_range(node, line, col) + local start_line, start_col, end_line, end_col = M.get_node_range(node) + if line >= start_line and line <= end_line then + if line == start_line and line == end_line then + return col >= start_col and col < end_col + elseif line == start_line then + return col >= start_col + elseif line == end_line then + return col < end_col + else + return true + end + else + return false + end +end + ---Determines if a node contains a range ---@param node table The node ---@param range table The range @@ -168,14 +189,17 @@ function M.node_contains(node, range) return start_fits and end_fits end ----Gets a list of highlight group for a given cursor position +---Gets a list of captures for a given cursor position ---@param bufnr number The buffer number ---@param row number The position row ---@param col number The position column --- ----@returns (table) A table of highlight groups -function M.get_hl_groups_at_position(bufnr, row, col) - local buf_highlighter = highlighter.active[bufnr] +---@returns (table) A table of captures +function M.get_captures_at_position(bufnr, row, col) + if bufnr == 0 then + bufnr = a.nvim_get_current_buf() + end + local buf_highlighter = M.highlighter.active[bufnr] if not buf_highlighter then return {} @@ -206,17 +230,10 @@ function M.get_hl_groups_at_position(bufnr, row, col) local iter = q:query():iter_captures(root, buf_highlighter.bufnr, row, row + 1) for capture, node, metadata in iter do - local hl = q.hl_cache[capture] - - if hl and M.is_in_node_range(node, row, col) then + if M.is_in_node_range(node, row, col) then local c = q._query.captures[capture] -- name of the capture in the query if c ~= nil then - local general_hl, is_vim_hl = q:_get_hl_from_capture(capture) - local local_hl = not is_vim_hl and (tree:lang() .. general_hl) - table.insert( - matches, - { capture = c, specific = local_hl, general = general_hl, priority = metadata.priority } - ) + table.insert(matches, { capture = c, priority = metadata.priority }) end end end -- cgit From 0822896efcf0da7002e323369fdc1e4a15ad1d57 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Mon, 5 Sep 2022 15:52:27 +0200 Subject: feat(treesitter): add vim.treesitter.start(), enable for Lua * Add vim.treesitter.start() for starting treesitter highlighting via ftplugin or autocommand (can be extended later for fold, indent, matchpairs, ...) * Add vim.treesitter.stop() for manually stopping treesitter highlighting * Enable treesitter highlighting for Lua if `vim.g.ts_highlight_lua = true` is set in `init.lua` --- runtime/lua/vim/treesitter.lua | 86 +++++++++++++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 17 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 6431162799..9c43811e03 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -32,9 +32,11 @@ setmetatable(M, { --- --- It is not recommended to use this, use vim.treesitter.get_parser() instead. --- ----@param bufnr The buffer the parser will be tied to ----@param lang The language of the parser ----@param opts Options to pass to the created language tree +---@param bufnr string Buffer the parser will be tied to (0 for current buffer) +---@param lang string Language of the parser +---@param opts table|nil Options to pass to the created language tree +--- +---@returns table Created parser object function M._create_parser(bufnr, lang, opts) language.require_language(lang) if bufnr == 0 then @@ -79,11 +81,11 @@ end --- If needed this will create the parser. --- Unconditionally attach the provided callback --- ----@param bufnr The buffer the parser should be tied to ----@param lang The filetype of this parser ----@param opts Options object to pass to the created language tree +---@param bufnr number|nil Buffer the parser should be tied to: (default current buffer) +---@param lang string |nil Filetype of this parser (default: buffer filetype) +---@param opts table|nil Options to pass to the created language tree --- ----@returns The parser +---@returns table Parser object function M.get_parser(bufnr, lang, opts) opts = opts or {} @@ -120,8 +122,8 @@ end --- Determines whether a node is the ancestor of another --- ----@param dest table the possible ancestor ----@param source table the possible descendant node +---@param dest table Possible ancestor +---@param source table Possible descendant node --- ---@returns (boolean) True if dest is an ancestor of source function M.is_ancestor(dest, source) @@ -156,9 +158,11 @@ end ---Determines whether (line, col) position is in node range --- ----@param node Node defining the range ----@param line A line (0-based) ----@param col A column (0-based) +---@param node table Node defining the range +---@param line number Line (0-based) +---@param col number Column (0-based) +--- +---@returns (boolean) True if the position is in node range function M.is_in_node_range(node, line, col) local start_line, start_col, end_line, end_col = M.get_node_range(node) if line >= start_line and line <= end_line then @@ -177,8 +181,8 @@ function M.is_in_node_range(node, line, col) end ---Determines if a node contains a range ----@param node table The node ----@param range table The range +---@param node table +---@param range table --- ---@returns (boolean) True if the node contains the range function M.node_contains(node, range) @@ -190,9 +194,9 @@ function M.node_contains(node, range) end ---Gets a list of captures for a given cursor position ----@param bufnr number The buffer number ----@param row number The position row ----@param col number The position column +---@param bufnr number Buffer number (0 for current buffer) +---@param row number Position row +---@param col number Position column --- ---@returns (table) A table of captures function M.get_captures_at_position(bufnr, row, col) @@ -241,4 +245,52 @@ function M.get_captures_at_position(bufnr, row, col) return matches end +--- Start treesitter highlighting for a buffer +--- +--- Can be used in an ftplugin or FileType autocommand +--- +--- Note: By default, disables regex syntax highlighting, which may be required for some plugins. +--- In this case, add `{ syntax = true }`. +--- +--- Example: +--- +---
+--- vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex',
+---     callback = function(args)
+---         vim.treesitter.start(args.buf, 'latex', { syntax = true })
+---     end
+--- })
+--- 
+--- +---@param bufnr number|nil Buffer to be highlighted (default: current buffer) +---@param lang string|nil Language of the parser (default: buffer filetype) +---@param opts table|nil Optional keyword arguments: +--- - `syntax` boolean Run regex syntax highlighting (default false) +function M.start(bufnr, lang, opts) + bufnr = bufnr or a.nvim_get_current_buf() + + local parser = M.get_parser(bufnr, lang) + + M.highlighter.new(parser) + + vim.b[bufnr].ts_highlight = true + + if opts and opts.syntax then + vim.bo[bufnr].syntax = 'on' + end +end + +---Stop treesitter highlighting for a buffer +--- +---@param bufnr number|nil Buffer to stop highlighting (default: current buffer) +function M.stop(bufnr) + bufnr = bufnr or a.nvim_get_current_buf() + + if M.highlighter.active[bufnr] then + M.highlighter.active[bufnr]:destroy() + end + + vim.bo[bufnr].syntax = 'on' +end + return M -- cgit From ffe98531b9a6a90a7f4a7ae2105b3c50ad9332fd Mon Sep 17 00:00:00 2001 From: Quentin Rasmont Date: Sat, 30 Apr 2022 11:51:14 +0200 Subject: feat(treesitter): upstream get_node_at_cursor() Util from the nvim-treesitter project. --- runtime/lua/vim/treesitter.lua | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 9c43811e03..d71f8611c1 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -81,7 +81,7 @@ end --- If needed this will create the parser. --- Unconditionally attach the provided callback --- ----@param bufnr number|nil Buffer the parser should be tied to: (default current buffer) +---@param bufnr number|nil Buffer the parser should be tied to (default: current buffer) ---@param lang string |nil Filetype of this parser (default: buffer filetype) ---@param opts table|nil Options to pass to the created language tree --- @@ -245,6 +245,27 @@ function M.get_captures_at_position(bufnr, row, col) return matches end +--- Gets the smallest named node under the cursor +--- +---@param winnr number Window handle or 0 for current window +---@param opts table Options table +---@param opts.ignore_injections boolean (default true) Ignore injected languages. +--- +---@returns (table) The named node under the cursor +function M.get_node_at_cursor(winnr, opts) + winnr = winnr or 0 + local cursor = a.nvim_win_get_cursor(winnr) + local ts_cursor_range = { cursor[1] - 1, cursor[2], cursor[1] - 1, cursor[2] } + + local buf = a.nvim_win_get_buf(winnr) + local root_lang_tree = M.get_parser(buf) + if not root_lang_tree then + return + end + + return root_lang_tree:named_node_for_range(ts_cursor_range, opts) +end + --- Start treesitter highlighting for a buffer --- --- Can be used in an ftplugin or FileType autocommand -- cgit From 95fd1ad83e24bbb14cc084fb001251939de6c0a9 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 6 Sep 2022 08:50:06 +0200 Subject: refactor(treesitter): get_{nodes,captures}_at_{position,cursor} --- runtime/lua/vim/treesitter.lua | 65 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 12 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index d71f8611c1..8a540b9012 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -147,7 +147,7 @@ end --- ---@param node_or_range table --- ----@returns start_row, start_col, end_row, end_col +---@returns table start_row, start_col, end_row, end_col function M.get_node_range(node_or_range) if type(node_or_range) == 'table' then return unpack(node_or_range) @@ -198,7 +198,11 @@ end ---@param row number Position row ---@param col number Position column --- ----@returns (table) A table of captures +---@param bufnr number Buffer number (0 for current buffer) +---@param row number Position row +---@param col number Position column +--- +---@returns (table) Table of captures function M.get_captures_at_position(bufnr, row, col) if bufnr == 0 then bufnr = a.nvim_get_current_buf() @@ -245,25 +249,62 @@ function M.get_captures_at_position(bufnr, row, col) return matches end ---- Gets the smallest named node under the cursor +---Gets a list of captures under the cursor --- ----@param winnr number Window handle or 0 for current window ----@param opts table Options table ----@param opts.ignore_injections boolean (default true) Ignore injected languages. +---@param winnr number|nil Window handle or 0 for current window (default) --- ----@returns (table) The named node under the cursor -function M.get_node_at_cursor(winnr, opts) +---@returns (table) Named node under the cursor +function M.get_captures_at_cursor(winnr) winnr = winnr or 0 + local bufnr = a.nvim_win_get_buf(winnr) local cursor = a.nvim_win_get_cursor(winnr) - local ts_cursor_range = { cursor[1] - 1, cursor[2], cursor[1] - 1, cursor[2] } - local buf = a.nvim_win_get_buf(winnr) - local root_lang_tree = M.get_parser(buf) + local data = M.get_captures_at_position(bufnr, cursor[1] - 1, cursor[2]) + + local captures = {} + + for _, capture in ipairs(data) do + table.insert(captures, capture.capture) + end + + return captures +end + +--- Gets the smallest named node at position +--- +---@param bufnr number Buffer number (0 for current buffer) +---@param row number Position row +---@param col number Position column +---@param opts table Optional keyword arguments: +--- - ignore_injections boolean Ignore injected languages (default true) +--- +---@returns (table) Named node under the cursor +function M.get_node_at_position(bufnr, row, col, opts) + if bufnr == 0 then + bufnr = a.nvim_get_current_buf() + end + local ts_range = { row, col, row, col } + + local root_lang_tree = M.get_parser(bufnr) if not root_lang_tree then return end - return root_lang_tree:named_node_for_range(ts_cursor_range, opts) + return root_lang_tree:named_node_for_range(ts_range, opts) +end + +--- Gets the smallest named node under the cursor +--- +---@param winnr number|nil Window handle or 0 for current window (default) +--- +---@returns (string) Named node under the cursor +function M.get_node_at_cursor(winnr) + winnr = winnr or 0 + local bufnr = a.nvim_win_get_buf(winnr) + local cursor = a.nvim_win_get_cursor(winnr) + + return M.get_node_at_position(bufnr, cursor[1] - 1, cursor[2], { ignore_injections = false }) + :type() end --- Start treesitter highlighting for a buffer -- cgit From d01cadd82fc74baf7d292c5cbbcf223e0aa2c097 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 6 Sep 2022 17:33:44 +0200 Subject: fix(treesitter): don't support legacy syntax in start() --- runtime/lua/vim/treesitter.lua | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 9c43811e03..5ebccff8f7 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -250,23 +250,22 @@ end --- Can be used in an ftplugin or FileType autocommand --- --- Note: By default, disables regex syntax highlighting, which may be required for some plugins. ---- In this case, add `{ syntax = true }`. +--- In this case, add `vim.bo.syntax = 'on'` after the call to `start`. --- --- Example: --- ---
 --- vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex',
 ---     callback = function(args)
----         vim.treesitter.start(args.buf, 'latex', { syntax = true })
+---         vim.treesitter.start(args.buf, 'latex')
+---         vim.bo[args.buf].syntax = 'on'  -- only if additional legacy syntax is needed
 ---     end
 --- })
 --- 
--- ---@param bufnr number|nil Buffer to be highlighted (default: current buffer) ---@param lang string|nil Language of the parser (default: buffer filetype) ----@param opts table|nil Optional keyword arguments: ---- - `syntax` boolean Run regex syntax highlighting (default false) -function M.start(bufnr, lang, opts) +function M.start(bufnr, lang) bufnr = bufnr or a.nvim_get_current_buf() local parser = M.get_parser(bufnr, lang) @@ -274,10 +273,6 @@ function M.start(bufnr, lang, opts) M.highlighter.new(parser) vim.b[bufnr].ts_highlight = true - - if opts and opts.syntax then - vim.bo[bufnr].syntax = 'on' - end end ---Stop treesitter highlighting for a buffer -- cgit From fd1595514b747d8b083f78007579d869ccfbe89c Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Wed, 7 Sep 2022 08:39:56 +0200 Subject: Use weak tables in tree-sitter code (#17117) feat(treesitter): use weak tables when possible Also add the defaulttable function to create a table whose values are created when a key is missing. --- runtime/lua/vim/treesitter.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 5ebccff8f7..cde0491b12 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -3,10 +3,7 @@ local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') local LanguageTree = require('vim.treesitter.languagetree') --- TODO(bfredl): currently we retain parsers for the lifetime of the buffer. --- Consider use weak references to release parser if all plugins are done with --- it. -local parsers = {} +local parsers = setmetatable({}, { __mode = 'v' }) local M = vim.tbl_extend('error', query, language) -- cgit From 99e6e0f221ccdb7aa983121359aedb7791e870dd Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 8 Sep 2022 12:54:41 +0800 Subject: docs(treesitter): fix doxygen --- runtime/lua/vim/treesitter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index cde0491b12..69faea7edc 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -247,7 +247,7 @@ end --- Can be used in an ftplugin or FileType autocommand --- --- Note: By default, disables regex syntax highlighting, which may be required for some plugins. ---- In this case, add `vim.bo.syntax = 'on'` after the call to `start`. +--- In this case, add ``vim.bo.syntax = 'on'`` after the call to `start`. --- --- Example: --- -- cgit From ddb762f4013ac2532ad45704466058d867e3a6ed Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 14 Sep 2022 11:08:31 +0200 Subject: docs(treesitter): clean up and update treesitter.txt (#20142) * add type annotations to code * clean up and expand static documentation * consistent use of tags for static and generated docs --- runtime/lua/vim/treesitter.lua | 85 +++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 42 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index d93c485dfe..89aa611acd 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -25,15 +25,15 @@ setmetatable(M, { end, }) ---- Creates a new parser. +--- Creates a new parser --- ---- It is not recommended to use this, use vim.treesitter.get_parser() instead. +--- It is not recommended to use this; use |get_parser()| instead. --- ---@param bufnr string Buffer the parser will be tied to (0 for current buffer) ---@param lang string Language of the parser ----@param opts table|nil Options to pass to the created language tree +---@param opts (table|nil) Options to pass to the created language tree --- ----@returns table Created parser object +---@return LanguageTree |LanguageTree| object to use for parsing function M._create_parser(bufnr, lang, opts) language.require_language(lang) if bufnr == 0 then @@ -73,16 +73,15 @@ function M._create_parser(bufnr, lang, opts) return self end ---- Gets the parser for this bufnr / ft combination. +--- Returns the parser for a specific buffer and filetype and attaches it to the buffer --- ---- If needed this will create the parser. ---- Unconditionally attach the provided callback +--- If needed, this will create the parser. --- ----@param bufnr number|nil Buffer the parser should be tied to (default: current buffer) ----@param lang string |nil Filetype of this parser (default: buffer filetype) ----@param opts table|nil Options to pass to the created language tree +---@param bufnr (number|nil) Buffer the parser should be tied to (default: current buffer) +---@param lang (string|nil) Filetype of this parser (default: buffer filetype) +---@param opts (table|nil) Options to pass to the created language tree --- ----@returns table Parser object +---@return LanguageTree |LanguageTree| object to use for parsing function M.get_parser(bufnr, lang, opts) opts = opts or {} @@ -102,11 +101,13 @@ function M.get_parser(bufnr, lang, opts) return parsers[bufnr] end ---- Gets a string parser +--- Returns a string parser --- ----@param str The string to parse ----@param lang The language of this string ----@param opts Options to pass to the created language tree +---@param str string Text to parse +---@param lang string Language of this string +---@param opts (table|nil) Options to pass to the created language tree +--- +---@return LanguageTree |LanguageTree| object to use for parsing function M.get_string_parser(str, lang, opts) vim.validate({ str = { str, 'string' }, @@ -119,10 +120,10 @@ end --- Determines whether a node is the ancestor of another --- ----@param dest table Possible ancestor ----@param source table Possible descendant node +---@param dest userdata Possible ancestor |tsnode| +---@param source userdata Possible descendant |tsnode| --- ----@returns (boolean) True if dest is an ancestor of source +---@return boolean True if {dest} is an ancestor of {source} function M.is_ancestor(dest, source) if not (dest and source) then return false @@ -140,11 +141,11 @@ function M.is_ancestor(dest, source) return false end ---- Get the node's range or unpack a range table +--- Returns the node's range or an unpacked range table --- ----@param node_or_range table +---@param node_or_range (userdata|table) |tsnode| or table of positions --- ----@returns table start_row, start_col, end_row, end_col +---@return table `{ start_row, start_col, end_row, end_col }` function M.get_node_range(node_or_range) if type(node_or_range) == 'table' then return unpack(node_or_range) @@ -155,11 +156,11 @@ end ---Determines whether (line, col) position is in node range --- ----@param node table Node defining the range +---@param node userdata |tsnode| defining the range ---@param line number Line (0-based) ---@param col number Column (0-based) --- ----@returns (boolean) True if the position is in node range +---@return boolean True if the position is in node range function M.is_in_node_range(node, line, col) local start_line, start_col, end_line, end_col = M.get_node_range(node) if line >= start_line and line <= end_line then @@ -178,10 +179,10 @@ function M.is_in_node_range(node, line, col) end ---Determines if a node contains a range ----@param node table +---@param node userdata |tsnode| ---@param range table --- ----@returns (boolean) True if the node contains the range +---@return boolean True if the {node} contains the {range} function M.node_contains(node, range) local start_row, start_col, end_row, end_col = node:range() local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) @@ -190,7 +191,8 @@ function M.node_contains(node, range) return start_fits and end_fits end ----Gets a list of captures for a given cursor position +---Returns a list of highlight captures at the given position +-- ---@param bufnr number Buffer number (0 for current buffer) ---@param row number Position row ---@param col number Position column @@ -199,7 +201,7 @@ end ---@param row number Position row ---@param col number Position column --- ----@returns (table) Table of captures +---@return table[] Captures of the form `{ capture = "capture name", priority = capture priority }` function M.get_captures_at_position(bufnr, row, col) if bufnr == 0 then bufnr = a.nvim_get_current_buf() @@ -246,11 +248,11 @@ function M.get_captures_at_position(bufnr, row, col) return matches end ----Gets a list of captures under the cursor +---Returns a list of highlight capture names under the cursor --- ----@param winnr number|nil Window handle or 0 for current window (default) +---@param winnr (number|nil) Window handle or 0 for current window (default) --- ----@returns (table) Named node under the cursor +---@return string[] List of capture names function M.get_captures_at_cursor(winnr) winnr = winnr or 0 local bufnr = a.nvim_win_get_buf(winnr) @@ -267,7 +269,7 @@ function M.get_captures_at_cursor(winnr) return captures end ---- Gets the smallest named node at position +--- Returns the smallest named node at the given position --- ---@param bufnr number Buffer number (0 for current buffer) ---@param row number Position row @@ -275,7 +277,7 @@ end ---@param opts table Optional keyword arguments: --- - ignore_injections boolean Ignore injected languages (default true) --- ----@returns (table) Named node under the cursor +---@return userdata |tsnode| under the cursor function M.get_node_at_position(bufnr, row, col, opts) if bufnr == 0 then bufnr = a.nvim_get_current_buf() @@ -290,11 +292,11 @@ function M.get_node_at_position(bufnr, row, col, opts) return root_lang_tree:named_node_for_range(ts_range, opts) end ---- Gets the smallest named node under the cursor +--- Returns the smallest named node under the cursor --- ----@param winnr number|nil Window handle or 0 for current window (default) +---@param winnr (number|nil) Window handle or 0 for current window (default) --- ----@returns (string) Named node under the cursor +---@return string Name of node under the cursor function M.get_node_at_cursor(winnr) winnr = winnr or 0 local bufnr = a.nvim_win_get_buf(winnr) @@ -304,15 +306,14 @@ function M.get_node_at_cursor(winnr) :type() end ---- Start treesitter highlighting for a buffer +--- Starts treesitter highlighting for a buffer --- ---- Can be used in an ftplugin or FileType autocommand +--- Can be used in an ftplugin or FileType autocommand. --- --- Note: By default, disables regex syntax highlighting, which may be required for some plugins. --- In this case, add ``vim.bo.syntax = 'on'`` after the call to `start`. --- --- Example: ---- ---
 --- vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex',
 ---     callback = function(args)
@@ -322,8 +323,8 @@ end
 --- })
 --- 
--- ----@param bufnr number|nil Buffer to be highlighted (default: current buffer) ----@param lang string|nil Language of the parser (default: buffer filetype) +---@param bufnr (number|nil) Buffer to be highlighted (default: current buffer) +---@param lang (string|nil) Language of the parser (default: buffer filetype) function M.start(bufnr, lang) bufnr = bufnr or a.nvim_get_current_buf() @@ -334,9 +335,9 @@ function M.start(bufnr, lang) vim.b[bufnr].ts_highlight = true end ----Stop treesitter highlighting for a buffer +--- Stops treesitter highlighting for a buffer --- ----@param bufnr number|nil Buffer to stop highlighting (default: current buffer) +---@param bufnr (number|nil) Buffer to stop highlighting (default: current buffer) function M.stop(bufnr) bufnr = bufnr or a.nvim_get_current_buf() -- cgit From 9ec4b20be695501ba166f31dec39ef9e30cc7dd8 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 16 Sep 2022 09:05:05 +0200 Subject: fix(treesitter): return full metadata for get_captures_at_position (#20203) fix(treesitter): get_captures_at_position returns metadata Return the full `metadata` table for the capture instead of just the priority. Further cleanup of related docs. --- runtime/lua/vim/treesitter.lua | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 89aa611acd..04e12cbe0b 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -154,7 +154,7 @@ function M.get_node_range(node_or_range) end end ----Determines whether (line, col) position is in node range +--- Determines whether (line, col) position is in node range --- ---@param node userdata |tsnode| defining the range ---@param line number Line (0-based) @@ -178,7 +178,8 @@ function M.is_in_node_range(node, line, col) end end ----Determines if a node contains a range +--- Determines if a node contains a range +--- ---@param node userdata |tsnode| ---@param range table --- @@ -191,17 +192,16 @@ function M.node_contains(node, range) return start_fits and end_fits end ----Returns a list of highlight captures at the given position --- ----@param bufnr number Buffer number (0 for current buffer) ----@param row number Position row ----@param col number Position column +--- Returns a list of highlight captures at the given position +--- +--- Each capture is represented by a table containing the capture name as a string as +--- well as a table of metadata (`priority`, `conceal`, ...; empty if none are defined). --- ---@param bufnr number Buffer number (0 for current buffer) ---@param row number Position row ---@param col number Position column --- ----@return table[] Captures of the form `{ capture = "capture name", priority = capture priority }` +---@return table[] List of captures `{ capture = "capture name", metadata = { ... } }` function M.get_captures_at_position(bufnr, row, col) if bufnr == 0 then bufnr = a.nvim_get_current_buf() @@ -240,7 +240,7 @@ function M.get_captures_at_position(bufnr, row, col) if M.is_in_node_range(node, row, col) then local c = q._query.captures[capture] -- name of the capture in the query if c ~= nil then - table.insert(matches, { capture = c, priority = metadata.priority }) + table.insert(matches, { capture = c, metadata = metadata }) end end end @@ -248,7 +248,7 @@ function M.get_captures_at_position(bufnr, row, col) return matches end ----Returns a list of highlight capture names under the cursor +--- Returns a list of highlight capture names under the cursor --- ---@param winnr (number|nil) Window handle or 0 for current window (default) --- -- cgit From 3169fc54a129f6dd1c0baf2d404e50381cf48e8f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 25 Sep 2022 00:45:15 +0200 Subject: refactor(treesitter): rename x_position => x_pos "pos" has a long precedent as "position" in vim, and there is no reason to use a verbose name here. --- runtime/lua/vim/treesitter.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 04e12cbe0b..6cd00516bf 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -202,7 +202,7 @@ end ---@param col number Position column --- ---@return table[] List of captures `{ capture = "capture name", metadata = { ... } }` -function M.get_captures_at_position(bufnr, row, col) +function M.get_captures_at_pos(bufnr, row, col) if bufnr == 0 then bufnr = a.nvim_get_current_buf() end @@ -258,7 +258,7 @@ function M.get_captures_at_cursor(winnr) local bufnr = a.nvim_win_get_buf(winnr) local cursor = a.nvim_win_get_cursor(winnr) - local data = M.get_captures_at_position(bufnr, cursor[1] - 1, cursor[2]) + local data = M.get_captures_at_pos(bufnr, cursor[1] - 1, cursor[2]) local captures = {} @@ -278,7 +278,7 @@ end --- - ignore_injections boolean Ignore injected languages (default true) --- ---@return userdata |tsnode| under the cursor -function M.get_node_at_position(bufnr, row, col, opts) +function M.get_node_at_pos(bufnr, row, col, opts) if bufnr == 0 then bufnr = a.nvim_get_current_buf() end @@ -302,8 +302,7 @@ function M.get_node_at_cursor(winnr) local bufnr = a.nvim_win_get_buf(winnr) local cursor = a.nvim_win_get_cursor(winnr) - return M.get_node_at_position(bufnr, cursor[1] - 1, cursor[2], { ignore_injections = false }) - :type() + return M.get_node_at_pos(bufnr, cursor[1] - 1, cursor[2], { ignore_injections = false }):type() end --- Starts treesitter highlighting for a buffer -- cgit From 0b05bd87c04f9cde5c84a062453619349e370795 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 23 Nov 2022 12:31:49 +0100 Subject: docs(gen): support language annotation in docstrings --- runtime/lua/vim/treesitter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 6cd00516bf..0603ddb421 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -313,7 +313,7 @@ end --- In this case, add ``vim.bo.syntax = 'on'`` after the call to `start`. --- --- Example: ----
+--- 
lua
 --- vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex',
 ---     callback = function(args)
 ---         vim.treesitter.start(args.buf, 'latex')
-- 
cgit 


From d44699800cd0dbf14fb45476c13b6cc3c993b5c7 Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Thu, 8 Dec 2022 09:22:57 -0700
Subject: feat(treesitter): add vim.treesitter.show_tree() (#21322)

Add a "show_tree" function to view a textual representation of the
nodes in a language tree in a window. Moving the cursor in the
window highlights the corresponding text in the source buffer, and
moving the cursor in the source buffer highlights the corresponding
nodes in the window.
---
 runtime/lua/vim/treesitter.lua | 195 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 194 insertions(+), 1 deletion(-)

(limited to 'runtime/lua/vim/treesitter.lua')

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 0603ddb421..5c9210cc2d 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -277,7 +277,7 @@ end
 ---@param opts table Optional keyword arguments:
 ---             - ignore_injections boolean Ignore injected languages (default true)
 ---
----@return userdata |tsnode| under the cursor
+---@return userdata|nil |tsnode| under the cursor
 function M.get_node_at_pos(bufnr, row, col, opts)
   if bufnr == 0 then
     bufnr = a.nvim_get_current_buf()
@@ -347,4 +347,197 @@ function M.stop(bufnr)
   vim.bo[bufnr].syntax = 'on'
 end
 
+--- Open a window that displays a textual representation of the nodes in the language tree.
+---
+--- While in the window, press "a" to toggle display of anonymous nodes, "I" to toggle the
+--- display of the source language of each node, and press  to jump to the node under the
+--- cursor in the source buffer.
+---
+---@param opts table|nil Optional options table with the following possible keys:
+---                      - bufnr (number|nil): Buffer to draw the tree into. If omitted, a new
+---                        buffer is created.
+---                      - winid (number|nil): Window id to display the tree buffer in. If omitted,
+---                        a new window is created with {command}.
+---                      - command (string|nil): Vimscript command to create the window. Default
+---                        value is "topleft 60vnew". Only used when {winid} is nil.
+---                      - title (string|fun(bufnr:number):string|nil): Title of the window. If a
+---                        function, it accepts the buffer number of the source buffer as its only
+---                        argument and should return a string.
+function M.show_tree(opts)
+  vim.validate({
+    opts = { opts, 't', true },
+  })
+
+  local Playground = require('vim.treesitter.playground')
+  local buf = a.nvim_get_current_buf()
+  local win = a.nvim_get_current_win()
+  local pg = assert(Playground:new(buf))
+
+  opts = opts or {}
+
+  -- Close any existing playground window
+  if vim.b[buf].playground then
+    local w = vim.b[buf].playground
+    if a.nvim_win_is_valid(w) then
+      a.nvim_win_close(w, true)
+    end
+  end
+
+  local w = opts.winid
+  if not w then
+    vim.cmd(opts.command or 'topleft 60vnew')
+    w = a.nvim_get_current_win()
+  end
+
+  local b = opts.bufnr
+  if b then
+    a.nvim_win_set_buf(w, b)
+  else
+    b = a.nvim_win_get_buf(w)
+  end
+
+  vim.b[buf].playground = w
+
+  vim.wo[w].scrolloff = 5
+  vim.wo[w].wrap = false
+  vim.bo[b].buflisted = false
+  vim.bo[b].buftype = 'nofile'
+  vim.bo[b].bufhidden = 'wipe'
+
+  local title = opts.title
+  if not title then
+    local bufname = a.nvim_buf_get_name(buf)
+    title = string.format('Syntax tree for %s', vim.fn.fnamemodify(bufname, ':.'))
+  elseif type(title) == 'function' then
+    title = title(buf)
+  end
+
+  assert(type(title) == 'string', 'Window title must be a string')
+  a.nvim_buf_set_name(b, title)
+
+  pg:draw(b)
+
+  vim.fn.matchadd('Comment', '\\[[0-9:-]\\+\\]')
+  vim.fn.matchadd('String', '".*"')
+
+  a.nvim_buf_clear_namespace(buf, pg.ns, 0, -1)
+  a.nvim_buf_set_keymap(b, 'n', '', '', {
+    desc = 'Jump to the node under the cursor in the source buffer',
+    callback = function()
+      local row = a.nvim_win_get_cursor(w)[1]
+      local pos = pg:get(row)
+      a.nvim_set_current_win(win)
+      a.nvim_win_set_cursor(win, { pos.lnum + 1, pos.col })
+    end,
+  })
+  a.nvim_buf_set_keymap(b, 'n', 'a', '', {
+    desc = 'Toggle anonymous nodes',
+    callback = function()
+      pg.opts.anon = not pg.opts.anon
+      pg:draw(b)
+    end,
+  })
+  a.nvim_buf_set_keymap(b, 'n', 'I', '', {
+    desc = 'Toggle language display',
+    callback = function()
+      pg.opts.lang = not pg.opts.lang
+      pg:draw(b)
+    end,
+  })
+
+  local group = a.nvim_create_augroup('treesitter/playground', {})
+
+  a.nvim_create_autocmd('CursorMoved', {
+    group = group,
+    buffer = b,
+    callback = function()
+      a.nvim_buf_clear_namespace(buf, pg.ns, 0, -1)
+      local row = a.nvim_win_get_cursor(w)[1]
+      local pos = pg:get(row)
+      a.nvim_buf_set_extmark(buf, pg.ns, pos.lnum, pos.col, {
+        end_row = pos.end_lnum,
+        end_col = math.max(0, pos.end_col),
+        hl_group = 'Visual',
+      })
+    end,
+  })
+
+  a.nvim_create_autocmd('CursorMoved', {
+    group = group,
+    buffer = buf,
+    callback = function()
+      if not a.nvim_buf_is_loaded(b) then
+        return true
+      end
+
+      a.nvim_buf_clear_namespace(b, pg.ns, 0, -1)
+
+      local cursor = a.nvim_win_get_cursor(win)
+      local cursor_node =
+        M.get_node_at_pos(buf, cursor[1] - 1, cursor[2], { ignore_injections = false })
+      if not cursor_node then
+        return
+      end
+
+      local cursor_node_id = cursor_node:id()
+      for i, v in pg:iter() do
+        if v.id == cursor_node_id then
+          local start = v.depth
+          local end_col = start + #v.text
+          a.nvim_buf_set_extmark(b, pg.ns, i - 1, start, {
+            end_col = end_col,
+            hl_group = 'Visual',
+          })
+          a.nvim_win_set_cursor(w, { i, 0 })
+          break
+        end
+      end
+    end,
+  })
+
+  a.nvim_create_autocmd({ 'TextChanged', 'InsertLeave' }, {
+    group = group,
+    buffer = buf,
+    callback = function()
+      if not a.nvim_buf_is_loaded(b) then
+        return true
+      end
+
+      pg = assert(Playground:new(buf))
+      pg:draw(b)
+    end,
+  })
+
+  a.nvim_create_autocmd('BufLeave', {
+    group = group,
+    buffer = b,
+    callback = function()
+      a.nvim_buf_clear_namespace(buf, pg.ns, 0, -1)
+    end,
+  })
+
+  a.nvim_create_autocmd('BufLeave', {
+    group = group,
+    buffer = buf,
+    callback = function()
+      if not a.nvim_buf_is_loaded(b) then
+        return true
+      end
+
+      a.nvim_buf_clear_namespace(b, pg.ns, 0, -1)
+    end,
+  })
+
+  a.nvim_create_autocmd('BufHidden', {
+    group = group,
+    buffer = buf,
+    once = true,
+    callback = function()
+      if a.nvim_win_is_valid(w) then
+        a.nvim_win_close(w, true)
+      end
+    end,
+  })
+end
+
 return M
-- 
cgit 


From 42009ac7df88bfffeea49a83e642fdc6cf9f9447 Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Thu, 8 Dec 2022 09:51:46 -0700
Subject: feat(treesitter): add 'lang' option to show_tree() (#21341)

This is necessary for now to support filetypes that use a parser with a
different name (e.g. the "terraform" filetype uses the "hcl" parser).
---
 runtime/lua/vim/treesitter.lua | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

(limited to 'runtime/lua/vim/treesitter.lua')

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 5c9210cc2d..7813c2edb2 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -275,6 +275,7 @@ end
 ---@param row number Position row
 ---@param col number Position column
 ---@param opts table Optional keyword arguments:
+---             - lang string|nil Parser language
 ---             - ignore_injections boolean Ignore injected languages (default true)
 ---
 ---@return userdata|nil |tsnode| under the cursor
@@ -284,7 +285,7 @@ function M.get_node_at_pos(bufnr, row, col, opts)
   end
   local ts_range = { row, col, row, col }
 
-  local root_lang_tree = M.get_parser(bufnr)
+  local root_lang_tree = M.get_parser(bufnr, opts.lang)
   if not root_lang_tree then
     return
   end
@@ -354,6 +355,8 @@ end
 --- cursor in the source buffer.
 ---
 ---@param opts table|nil Optional options table with the following possible keys:
+---                      - lang (string|nil): The language of the source buffer. If omitted, the
+---                        filetype of the source buffer is used.
 ---                      - bufnr (number|nil): Buffer to draw the tree into. If omitted, a new
 ---                        buffer is created.
 ---                      - winid (number|nil): Window id to display the tree buffer in. If omitted,
@@ -368,12 +371,12 @@ function M.show_tree(opts)
     opts = { opts, 't', true },
   })
 
+  opts = opts or {}
+
   local Playground = require('vim.treesitter.playground')
   local buf = a.nvim_get_current_buf()
   local win = a.nvim_get_current_win()
-  local pg = assert(Playground:new(buf))
-
-  opts = opts or {}
+  local pg = assert(Playground:new(buf, opts.lang))
 
   -- Close any existing playground window
   if vim.b[buf].playground then
@@ -473,8 +476,10 @@ function M.show_tree(opts)
       a.nvim_buf_clear_namespace(b, pg.ns, 0, -1)
 
       local cursor = a.nvim_win_get_cursor(win)
-      local cursor_node =
-        M.get_node_at_pos(buf, cursor[1] - 1, cursor[2], { ignore_injections = false })
+      local cursor_node = M.get_node_at_pos(buf, cursor[1] - 1, cursor[2], {
+        lang = opts.lang,
+        ignore_injections = false,
+      })
       if not cursor_node then
         return
       end
@@ -503,7 +508,7 @@ function M.show_tree(opts)
         return true
       end
 
-      pg = assert(Playground:new(buf))
+      pg = assert(Playground:new(buf, opts.lang))
       pg:draw(b)
     end,
   })
-- 
cgit 


From d127c684faa9a112575798a81c87babb1c83a7ea Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Wed, 14 Dec 2022 15:00:48 +0000
Subject: fix(treesitter): properly restore `'syntax'` (#21358)

---
 runtime/lua/vim/treesitter.lua | 6 ------
 1 file changed, 6 deletions(-)

(limited to 'runtime/lua/vim/treesitter.lua')

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 7813c2edb2..25f0e7dc5e 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -327,12 +327,8 @@ end
 ---@param lang (string|nil) Language of the parser (default: buffer filetype)
 function M.start(bufnr, lang)
   bufnr = bufnr or a.nvim_get_current_buf()
-
   local parser = M.get_parser(bufnr, lang)
-
   M.highlighter.new(parser)
-
-  vim.b[bufnr].ts_highlight = true
 end
 
 --- Stops treesitter highlighting for a buffer
@@ -344,8 +340,6 @@ function M.stop(bufnr)
   if M.highlighter.active[bufnr] then
     M.highlighter.active[bufnr]:destroy()
   end
-
-  vim.bo[bufnr].syntax = 'on'
 end
 
 --- Open a window that displays a textual representation of the nodes in the language tree.
-- 
cgit 


From ef91146efcece1b6d97152251e7137d301146189 Mon Sep 17 00:00:00 2001
From: Folke Lemaitre 
Date: Wed, 14 Dec 2022 10:46:54 +0100
Subject: feat: `vim.inspect_pos`, `vim.show_pos`, `:Inspect`

---
 runtime/lua/vim/treesitter.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'runtime/lua/vim/treesitter.lua')

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 7813c2edb2..5031aca378 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -240,7 +240,7 @@ function M.get_captures_at_pos(bufnr, row, col)
       if M.is_in_node_range(node, row, col) then
         local c = q._query.captures[capture] -- name of the capture in the query
         if c ~= nil then
-          table.insert(matches, { capture = c, metadata = metadata })
+          table.insert(matches, { capture = c, metadata = metadata, lang = tree:lang() })
         end
       end
     end
-- 
cgit