From 9a5678463c96baf3b39cb3083ddf0da87d39aa23 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 4 Feb 2023 14:58:38 +0000 Subject: fix(treesitter): fix most diagnostics --- runtime/lua/vim/treesitter.lua | 73 ++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 31 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 582922ecb6..96b1e24ba9 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -3,8 +3,11 @@ local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') local LanguageTree = require('vim.treesitter.languagetree') +---@type table local parsers = setmetatable({}, { __mode = 'v' }) +---@class TreesitterModule +---@field highlighter TSHighlighter local M = vim.tbl_extend('error', query, language) M.language_version = vim._ts_get_language_version() @@ -12,6 +15,7 @@ M.minimum_language_version = vim._ts_get_minimum_language_version() setmetatable(M, { __index = function(t, k) + ---@diagnostic disable:no-unknown if k == 'highlighter' then t[k] = require('vim.treesitter.highlighter') return t[k] @@ -29,21 +33,23 @@ setmetatable(M, { --- --- 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 bufnr integer 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 --- ----@return LanguageTree |LanguageTree| object to use for parsing +---@return LanguageTree object to use for parsing function M._create_parser(bufnr, lang, opts) language.require_language(lang) if bufnr == 0 then - bufnr = a.nvim_get_current_buf() + bufnr = vim.api.nvim_get_current_buf() end vim.fn.bufload(bufnr) local self = LanguageTree.new(bufnr, lang, opts) + ---@diagnostic disable:invisible + ---@private local function bytes_cb(_, ...) self:_on_bytes(...) @@ -58,12 +64,14 @@ function M._create_parser(bufnr, lang, opts) end ---@private - local function reload_cb(_, ...) - self:_on_reload(...) + local function reload_cb(_) + self:_on_reload() end + local source = self:source() --[[@as integer]] + a.nvim_buf_attach( - self:source(), + source, false, { on_bytes = bytes_cb, on_detach = detach_cb, on_reload = reload_cb, preview = true } ) @@ -77,11 +85,11 @@ end --- --- If needed, this will create the parser. --- ----@param bufnr (number|nil) Buffer the parser should be tied to (default: current buffer) +---@param bufnr (integer|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 --- ----@return LanguageTree |LanguageTree| object to use for parsing +---@return LanguageTree object to use for parsing function M.get_parser(bufnr, lang, opts) opts = opts or {} @@ -107,7 +115,7 @@ end ---@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 +---@return LanguageTree object to use for parsing function M.get_string_parser(str, lang, opts) vim.validate({ str = { str, 'string' }, @@ -120,8 +128,8 @@ end --- Determines whether a node is the ancestor of another --- ----@param dest userdata Possible ancestor |tsnode| ----@param source userdata Possible descendant |tsnode| +---@param dest TSNode Possible ancestor +---@param source TSNode Possible descendant --- ---@return boolean True if {dest} is an ancestor of {source} function M.is_ancestor(dest, source) @@ -143,9 +151,12 @@ end --- Returns the node's range or an unpacked range table --- ----@param node_or_range (userdata|table) |tsnode| or table of positions +---@param node_or_range (TSNode|table) Node or table of positions --- ----@return table `{ start_row, start_col, end_row, end_col }` +---@return integer start_row +---@return integer start_col +---@return integer end_row +---@return integer end_col function M.get_node_range(node_or_range) if type(node_or_range) == 'table' then return unpack(node_or_range) @@ -156,9 +167,9 @@ end --- Determines whether (line, col) position is in node range --- ----@param node userdata |tsnode| defining the range ----@param line number Line (0-based) ----@param col number Column (0-based) +---@param node TSNode defining the range +---@param line integer Line (0-based) +---@param col integer Column (0-based) --- ---@return boolean True if the position is in node range function M.is_in_node_range(node, line, col) @@ -180,7 +191,7 @@ end --- Determines if a node contains a range --- ----@param node userdata |tsnode| +---@param node TSNode ---@param range table --- ---@return boolean True if the {node} contains the {range} @@ -197,9 +208,9 @@ end --- 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 +---@param bufnr integer Buffer number (0 for current buffer) +---@param row integer Position row +---@param col integer Position column --- ---@return table[] List of captures `{ capture = "capture name", metadata = { ... } }` function M.get_captures_at_pos(bufnr, row, col) @@ -250,7 +261,7 @@ end --- Returns a list of highlight capture names under the cursor --- ----@param winnr (number|nil) Window handle or 0 for current window (default) +---@param winnr (integer|nil) Window handle or 0 for current window (default) --- ---@return string[] List of capture names function M.get_captures_at_cursor(winnr) @@ -271,14 +282,14 @@ end --- Returns the smallest named node at the given position --- ----@param bufnr number Buffer number (0 for current buffer) ----@param row number Position row ----@param col number Position column +---@param bufnr integer Buffer number (0 for current buffer) +---@param row integer Position row +---@param col integer 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 +---@return TSNode|nil under the cursor function M.get_node_at_pos(bufnr, row, col, opts) if bufnr == 0 then bufnr = a.nvim_get_current_buf() @@ -295,7 +306,7 @@ end --- Returns the smallest named node under the cursor --- ----@param winnr (number|nil) Window handle or 0 for current window (default) +---@param winnr (integer|nil) Window handle or 0 for current window (default) --- ---@return string Name of node under the cursor function M.get_node_at_cursor(winnr) @@ -323,7 +334,7 @@ end --- }) --- --- ----@param bufnr (number|nil) Buffer to be highlighted (default: current buffer) +---@param bufnr (integer|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() @@ -333,7 +344,7 @@ end --- Stops treesitter highlighting for a buffer --- ----@param bufnr (number|nil) Buffer to stop highlighting (default: current buffer) +---@param bufnr (integer|nil) Buffer to stop highlighting (default: current buffer) function M.stop(bufnr) bufnr = bufnr or a.nvim_get_current_buf() @@ -351,13 +362,13 @@ end ---@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 +--- - bufnr (integer|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, +--- - winid (integer|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 +--- - title (string|fun(bufnr:integer):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) -- cgit From f5bad01869df449cb1e4ae7f264bcd5c8150f606 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 9 Feb 2023 15:20:47 +0000 Subject: feat(treesitter): playground improvements - Render node ranges as virtual text - Set filettype=query. The virtual text is to avoid parsing errors. - Make sure highlights text is always in view. --- runtime/lua/vim/treesitter.lua | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 96b1e24ba9..a15d3ec23c 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -411,6 +411,7 @@ function M.show_tree(opts) vim.bo[b].buflisted = false vim.bo[b].buftype = 'nofile' vim.bo[b].bufhidden = 'wipe' + vim.bo[b].filetype = 'query' local title = opts.title if not title then @@ -425,9 +426,6 @@ function M.show_tree(opts) 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', @@ -467,6 +465,15 @@ function M.show_tree(opts) end_col = math.max(0, pos.end_col), hl_group = 'Visual', }) + + local topline, botline = vim.fn.line('w0', win), vim.fn.line('w$', win) + + -- Move the cursor if highlighted range is completely out of view + if pos.lnum < topline and pos.end_lnum < topline then + a.nvim_win_set_cursor(win, { pos.end_lnum + 1, 0 }) + elseif pos.lnum > botline and pos.end_lnum > botline then + a.nvim_win_set_cursor(win, { pos.lnum + 1, 0 }) + end end, }) -- cgit From 8a985d12dd6b4a5a4ba825939f36b7b1a324d849 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 9 Feb 2023 16:08:22 +0000 Subject: fix(treesitter): don't trample parsers when filetype!=lang This allows vim.treesitter.show_tree() to work on buffers where the filetype does not match the parser language name e.g, bash/sh. --- runtime/lua/vim/treesitter.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index a15d3ec23c..4127198576 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -96,11 +96,13 @@ function M.get_parser(bufnr, lang, opts) if bufnr == nil or bufnr == 0 then bufnr = a.nvim_get_current_buf() end - if lang == nil then - lang = a.nvim_buf_get_option(bufnr, 'filetype') - end - if parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then + if parsers[bufnr] == nil then + lang = lang or a.nvim_buf_get_option(bufnr, 'filetype') + parsers[bufnr] = M._create_parser(bufnr, lang, opts) + elseif lang and parsers[bufnr]:lang() ~= lang then + -- Only try to create a new parser if lang is provided + -- and it doesn't match the stored parser parsers[bufnr] = M._create_parser(bufnr, lang, opts) end -- cgit From 8714a4009c0f0be0bb27a6b3eb486eeb3d9f3049 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 21 Feb 2023 17:09:18 +0000 Subject: feat(treesitter): add filetype -> lang API Problem: vim.treesitter does not know how to map a specific filetype to a parser. This creates problems since in a few places (including in vim.treesitter itself), the filetype is incorrectly used in place of lang. Solution: Add an API to enable this: - Add vim.treesitter.language.add() as a replacement for vim.treesitter.language.require_language(). - Optional arguments are now passed via an opts table. - Also takes a filetype (or list of filetypes) so we can keep track of what filetypes are associated with which langs. - Deprecated vim.treesitter.language.require_language(). - Add vim.treesitter.language.get_lang() which returns the associated lang for a given filetype. - Add vim.treesitter.language.register() to associate filetypes to a lang without loading the parser. --- runtime/lua/vim/treesitter.lua | 24 ++++++++++++++---------- 1 file changed, 14 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 4127198576..c524b20bc2 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -29,6 +29,8 @@ setmetatable(M, { end, }) +---@diagnostic disable:invisible + --- Creates a new parser --- --- It is not recommended to use this; use |get_parser()| instead. @@ -39,16 +41,15 @@ setmetatable(M, { --- ---@return LanguageTree object to use for parsing function M._create_parser(bufnr, lang, opts) - language.require_language(lang) if bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end vim.fn.bufload(bufnr) - local self = LanguageTree.new(bufnr, lang, opts) + language.add(lang, { filetype = vim.bo[bufnr].filetype }) - ---@diagnostic disable:invisible + local self = LanguageTree.new(bufnr, lang, opts) ---@private local function bytes_cb(_, ...) @@ -96,13 +97,16 @@ function M.get_parser(bufnr, lang, opts) if bufnr == nil or bufnr == 0 then bufnr = a.nvim_get_current_buf() end + if lang == nil then + local ft = vim.bo[bufnr].filetype + lang = language.get_lang(ft) or ft + -- TODO(lewis6991): we should error here and not default to ft + -- if not lang then + -- error(string.format('filetype %s of buffer %d is not associated with any lang', ft, bufnr)) + -- end + end - if parsers[bufnr] == nil then - lang = lang or a.nvim_buf_get_option(bufnr, 'filetype') - parsers[bufnr] = M._create_parser(bufnr, lang, opts) - elseif lang and parsers[bufnr]:lang() ~= lang then - -- Only try to create a new parser if lang is provided - -- and it doesn't match the stored parser + if parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then parsers[bufnr] = M._create_parser(bufnr, lang, opts) end @@ -123,7 +127,7 @@ function M.get_string_parser(str, lang, opts) str = { str, 'string' }, lang = { lang, 'string' }, }) - language.require_language(lang) + language.add(lang) return LanguageTree.new(str, lang, opts) end -- cgit From 675826da63e879efa97c0998fea192ed5c79d56e Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Wed, 22 Feb 2023 08:01:08 -0700 Subject: refactor(treesitter): Add vim.treesitter.get_node() (#22360) This function replaces both vim.treesitter.get_node_at_pos() and vim.treesitter.get_node_at_cursor(). These two functions are similar enough that they don't need separate interfaces. Even worse, get_node_at_pos() returns a TSNode while get_node_at_cursor() returns a string, so the two functions behave slightly differently. vim.treesitter.get_node() combines these two into a more streamlined interface. With no arguments, it returns the node under the cursor in the current buffer. Optionally, it can accept a buffer number or a position to get the node at a given position in a given buffer. --- runtime/lua/vim/treesitter.lua | 57 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index c524b20bc2..c1e5325519 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -286,6 +286,50 @@ function M.get_captures_at_cursor(winnr) return captures end +--- Returns the smallest named node at the given position +--- +---@param opts table|nil Optional keyword arguments: +--- - bufnr integer|nil Buffer number (nil or 0 for current buffer) +--- - pos table|nil 0-indexed (row, col) tuple. Defaults to cursor position in the +--- current window. Required if {bufnr} is not the current buffer +--- - ignore_injections boolean Ignore injected languages (default true) +--- +---@return TSNode | nil Node at the given position +function M.get_node(opts) + opts = opts or {} + + local bufnr = opts.bufnr + + if not bufnr or bufnr == 0 then + bufnr = a.nvim_get_current_buf() + end + + local row, col + if opts.pos then + assert(#opts.pos == 2, 'Position must be a (row, col) tuple') + row, col = opts.pos[1], opts.pos[2] + else + assert( + bufnr == a.nvim_get_current_buf(), + 'Position must be explicitly provided when not using the current buffer' + ) + local pos = a.nvim_win_get_cursor(0) + -- Subtract one to account for 1-based row indexing in nvim_win_get_cursor + row, col = pos[1] - 1, pos[2] + end + + assert(row >= 0 and col >= 0, 'Invalid position: row and col must be non-negative') + + 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_range, opts) +end + --- Returns the smallest named node at the given position --- ---@param bufnr integer Buffer number (0 for current buffer) @@ -296,12 +340,16 @@ end --- - ignore_injections boolean Ignore injected languages (default true) --- ---@return TSNode|nil under the cursor +---@deprecated function M.get_node_at_pos(bufnr, row, col, opts) + vim.deprecate('vim.treesitter.get_node_at_pos()', 'vim.treesitter.get_node()', '0.10') if bufnr == 0 then bufnr = a.nvim_get_current_buf() end local ts_range = { row, col, row, col } + opts = opts or {} + local root_lang_tree = M.get_parser(bufnr, opts.lang) if not root_lang_tree then return @@ -315,12 +363,13 @@ end ---@param winnr (integer|nil) Window handle or 0 for current window (default) --- ---@return string Name of node under the cursor +---@deprecated function M.get_node_at_cursor(winnr) + vim.deprecate('vim.treesitter.get_node_at_cursor()', 'vim.treesitter.get_node():type()', '0.10') 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_pos(bufnr, cursor[1] - 1, cursor[2], { ignore_injections = false }):type() + return M.get_node({ bufnr = bufnr, ignore_injections = false }):type() end --- Starts treesitter highlighting for a buffer @@ -493,8 +542,8 @@ 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], { + local cursor_node = M.get_node({ + bufnr = buf, lang = opts.lang, ignore_injections = false, }) -- cgit From 05de0f4fea237132ff3a9a5a35e9c711c4ece579 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 21 Feb 2023 17:03:04 +0100 Subject: docs(treesitter): fix parse errors --- runtime/lua/vim/treesitter.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index c1e5325519..c4df5b2d24 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -157,7 +157,7 @@ end --- Returns the node's range or an unpacked range table --- ----@param node_or_range (TSNode|table) Node or table of positions +---@param node_or_range (TSNode | table) Node or table of positions --- ---@return integer start_row ---@return integer start_col @@ -339,7 +339,7 @@ end --- - lang string|nil Parser language --- - ignore_injections boolean Ignore injected languages (default true) --- ----@return TSNode|nil under the cursor +---@return TSNode | nil Node at the given position ---@deprecated function M.get_node_at_pos(bufnr, row, col, opts) vim.deprecate('vim.treesitter.get_node_at_pos()', 'vim.treesitter.get_node()', '0.10') -- cgit From 6dfbeb0d990d24657754463c6ab155c19e7f5f56 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 21 Feb 2023 17:39:29 +0100 Subject: docs: fix more treesitter parsing errors --- 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 c4df5b2d24..44922bbc4d 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -218,7 +218,7 @@ end ---@param row integer Position row ---@param col integer Position column --- ----@return table[] List of captures `{ capture = "capture name", metadata = { ... } }` +---@return table[] List of captures `{ capture = "name", metadata = { ... } }` function M.get_captures_at_pos(bufnr, row, col) if bufnr == 0 then bufnr = a.nvim_get_current_buf() -- cgit From 1df3f5ec6aca24cbe7b78ead5c37ad06a65c84e8 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Feb 2023 17:05:20 +0000 Subject: feat(treesitter): upstream foldexpr from nvim-treesitter --- runtime/lua/vim/treesitter.lua | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 44922bbc4d..fead7b7b1b 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -115,6 +115,16 @@ function M.get_parser(bufnr, lang, opts) return parsers[bufnr] end +---@private +---@param bufnr (integer|nil) Buffer number +---@return boolean +function M._has_parser(bufnr) + if bufnr == nil or bufnr == 0 then + bufnr = a.nvim_get_current_buf() + end + return parsers[bufnr] ~= nil +end + --- Returns a string parser --- ---@param str string Text to parse @@ -612,4 +622,14 @@ function M.show_tree(opts) }) end +--- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr': +---
lua
+--- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
+--- 
+---@param lnum integer|nil Line number to calculate fold level for +---@return string +function M.foldexpr(lnum) + return require('vim.treesitter._fold').foldexpr(lnum) +end + return M -- cgit From b0b4c310973c2b419350e3c05c772596b1c334e9 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 2 Mar 2023 10:01:42 -0500 Subject: refactor: rename show_tree => inspect_tree #22474 Problem: "show" is potentially a new verb that we can avoid (there is already "open" and "echo"). Even if we can't avoid it, the behavior of `show_tree` fits well in the "inspect" family of functions: a way for users to introspect/reflect on the state of Nvim. Existing "inspect" functions: vim.inspect() vim.inspect_pos() vim.treesitter.inspect_language() nvim__inspect_cell Solution: Rename `show_tree` to `inspect_tree`. --- runtime/lua/vim/treesitter.lua | 8 +++++++- 1 file changed, 7 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 fead7b7b1b..412140b757 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -436,7 +436,7 @@ end --- - title (string|fun(bufnr:integer):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) +function M.inspect_tree(opts) vim.validate({ opts = { opts, 't', true }, }) @@ -622,6 +622,12 @@ function M.show_tree(opts) }) end +---@deprecated +---@private +function M.show_tree() + vim.deprecate('show_tree', 'inspect_tree', '0.9', nil, false) +end + --- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr': ---
lua
 --- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
-- 
cgit 


From f449121764c19cebda7b8b2c970b76bc8121bae7 Mon Sep 17 00:00:00 2001
From: Christian Clason 
Date: Thu, 2 Mar 2023 18:03:11 +0100
Subject: feat(treesitter): add :InspectTree command (#22477)

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

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 412140b757..09e3814a17 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -424,6 +424,8 @@ end
 --- display of the source language of each node, and press  to jump to the node under the
 --- cursor in the source buffer.
 ---
+--- Can also be shown with `:InspectTree`. *:InspectTree*
+---
 ---@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.
-- 
cgit 


From 2eeafc43c43697d18d5634f8f81bf9e60a880e17 Mon Sep 17 00:00:00 2001
From: Gregory Anders 
Date: Thu, 2 Mar 2023 14:06:11 -0700
Subject: fix(treesitter): maintain cursor position when toggling anonymous
 nodes

When toggling anonymous nodes in the :InspectTree window, keep the
cursor fixed relative to the node within the tree. This prevents the
cursor from jumping.
---
 runtime/lua/vim/treesitter.lua | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 09e3814a17..b2909f2154 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -506,8 +506,26 @@ function M.inspect_tree(opts)
   a.nvim_buf_set_keymap(b, 'n', 'a', '', {
     desc = 'Toggle anonymous nodes',
     callback = function()
+      local row, col = unpack(a.nvim_win_get_cursor(w))
+      local curnode = pg:get(row)
+      while curnode and not curnode.named do
+        row = row - 1
+        curnode = pg:get(row)
+      end
+
       pg.opts.anon = not pg.opts.anon
       pg:draw(b)
+
+      if not curnode then
+        return
+      end
+
+      local id = curnode.id
+      for i, node in pg:iter() do
+        if node.id == id then
+          a.nvim_win_set_cursor(w, { i, col })
+        end
+      end
     end,
   })
   a.nvim_buf_set_keymap(b, 'n', 'I', '', {
-- 
cgit 


From 6d4f48182131c36d57589eefd4cefe3c70256d04 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Fri, 3 Mar 2023 09:44:02 +0000
Subject: fix(treesitter): disallow empty filetypes

Fixes #22473
---
 runtime/lua/vim/treesitter.lua | 3 ++-
 1 file changed, 2 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 09e3814a17..f80da433b1 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -47,7 +47,8 @@ function M._create_parser(bufnr, lang, opts)
 
   vim.fn.bufload(bufnr)
 
-  language.add(lang, { filetype = vim.bo[bufnr].filetype })
+  local ft = vim.bo[bufnr].filetype
+  language.add(lang, { filetype = ft ~= '' and ft or nil })
 
   local self = LanguageTree.new(bufnr, lang, opts)
 
-- 
cgit 


From bf90ceb5488ea2b41eb53335984f017785aefea9 Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Fri, 3 Mar 2023 07:52:57 -0700
Subject: fix(treesitter): break early from loop when match is found (#22499)

Fixup to #22484.
---
 runtime/lua/vim/treesitter.lua | 1 +
 1 file changed, 1 insertion(+)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index b63247aa2c..ee66ba9f9b 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -525,6 +525,7 @@ function M.inspect_tree(opts)
       for i, node in pg:iter() do
         if node.id == id then
           a.nvim_win_set_cursor(w, { i, col })
+          break
         end
       end
     end,
-- 
cgit 


From f9a46391ab5961fe6c6b7d1efdc96befdd495c11 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Mon, 6 Mar 2023 10:57:14 +0000
Subject: refactor(treesitter): simplify some range functions

---
 runtime/lua/vim/treesitter.lua | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index ee66ba9f9b..d13824076e 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 Range = require('vim.treesitter._range')
 
 ---@type table
 local parsers = setmetatable({}, { __mode = 'v' })
@@ -190,20 +191,7 @@ end
 ---
 ---@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
-    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
+  return M.node_contains(node, { line, col, line, col })
 end
 
 --- Determines if a node contains a range
@@ -213,11 +201,11 @@ end
 ---
 ---@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])
-  local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4])
-
-  return start_fits and end_fits
+  vim.validate({
+    node = { node, 'userdata' },
+    range = { range, Range.validate, 'integer list with 4 or 6 elements' },
+  })
+  return Range.contains({ node:range() }, range)
 end
 
 --- Returns a list of highlight captures at the given position
-- 
cgit 


From be0461e3c216c2e4e2c3397c739b7727a5bf6df8 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Wed, 8 Mar 2023 23:45:43 +0000
Subject: fix(treesitter): is_in_node_range (#22582)

TS ranges are end column exclusive, so fix is_in_node_range
to account for that.
---
 runtime/lua/vim/treesitter.lua | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index d13824076e..ab9f8968c8 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -191,7 +191,7 @@ end
 ---
 ---@return boolean True if the position is in node range
 function M.is_in_node_range(node, line, col)
-  return M.node_contains(node, { line, col, line, col })
+  return M.node_contains(node, { line, col, line, col + 1 })
 end
 
 --- Determines if a node contains a range
@@ -202,7 +202,8 @@ end
 ---@return boolean True if the {node} contains the {range}
 function M.node_contains(node, range)
   vim.validate({
-    node = { node, 'userdata' },
+    -- allow a table so nodes can be mocked
+    node = { node, { 'userdata', 'table' } },
     range = { range, Range.validate, 'integer list with 4 or 6 elements' },
   })
   return Range.contains({ node:range() }, range)
-- 
cgit 


From c5b9643bf1b0f6d5166b4abf6a7c3f29532aefeb Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Fri, 10 Mar 2023 10:25:10 +0000
Subject: fix(treesitter): better lang handling of get_parser()

---
 runtime/lua/vim/treesitter.lua | 25 ++++++++++++++++++++-----
 1 file changed, 20 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 ab9f8968c8..5723cce563 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -99,13 +99,28 @@ function M.get_parser(bufnr, lang, opts)
   if bufnr == nil or bufnr == 0 then
     bufnr = a.nvim_get_current_buf()
   end
+
   if lang == nil then
     local ft = vim.bo[bufnr].filetype
-    lang = language.get_lang(ft) or ft
-    -- TODO(lewis6991): we should error here and not default to ft
-    -- if not lang then
-    --   error(string.format('filetype %s of buffer %d is not associated with any lang', ft, bufnr))
-    -- end
+    if ft ~= '' then
+      lang = language.get_lang(ft) or ft
+      -- TODO(lewis6991): we should error here and not default to ft
+      -- if not lang then
+      --   error(string.format('filetype %s of buffer %d is not associated with any lang', ft, bufnr))
+      -- end
+    else
+      if parsers[bufnr] then
+        return parsers[bufnr]
+      end
+      error(
+        string.format(
+          'There is no parser available for buffer %d and one could not be'
+            .. ' created because lang could not be determined. Either pass lang'
+            .. ' or set the buffer filetype',
+          bufnr
+        )
+      )
+    end
   end
 
   if parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
-- 
cgit 


From 71eebd28d1da487fbbb3c162c6b909940f76883d Mon Sep 17 00:00:00 2001
From: nullchilly 
Date: Sat, 11 Mar 2023 17:24:48 +0700
Subject: refactor(treesitter)!: remove deprecated show_tree func

---
 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 5723cce563..56000f99a8 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -648,12 +648,6 @@ function M.inspect_tree(opts)
   })
 end
 
----@deprecated
----@private
-function M.show_tree()
-  vim.deprecate('show_tree', 'inspect_tree', '0.9', nil, false)
-end
-
 --- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr':
 --- 
lua
 --- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
-- 
cgit 


From 2720d2c793b22e6c0c8719e5592922619fffdf7a Mon Sep 17 00:00:00 2001
From: Yochem van Rosmalen 
Date: Fri, 17 Mar 2023 12:41:57 +0100
Subject: fix(treesitter): InspectTree does not respect 'splitright' #22692

Problem:
vim.treesitter.inspect_tree() and :InspectTree does not respect 'splitright'.

Solution:
- Change the default `command` from `topleft 60vnew` to `60vnew`.
- Change :InspectTree to respect command mods (`:vertical`, count, etc.).

Closes #22656
---
 runtime/lua/vim/treesitter.lua | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 56000f99a8..43b8c11b80 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -439,7 +439,7 @@ end
 ---                      - winid (integer|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.
+---                        value is "60vnew". Only used when {winid} is nil.
 ---                      - title (string|fun(bufnr:integer):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.
@@ -465,7 +465,7 @@ function M.inspect_tree(opts)
 
   local w = opts.winid
   if not w then
-    vim.cmd(opts.command or 'topleft 60vnew')
+    vim.cmd(opts.command or '60vnew')
     w = a.nvim_get_current_win()
   end
 
-- 
cgit 


From 4e4203f71b0b9bb2ca4ad9abd2fbf4ea1deaf9a6 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Thu, 23 Mar 2023 11:23:51 +0000
Subject: fix(treesitter): annotations

- Begin using `@package` in place of `@private` for functions
that are accessed internally but outside their defined class.

- Rename Node -> TSP.Node
---
 runtime/lua/vim/treesitter.lua | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 43b8c11b80..685b1d8830 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -30,8 +30,6 @@ setmetatable(M, {
   end,
 })
 
----@diagnostic disable:invisible
-
 --- Creates a new parser
 ---
 --- It is not recommended to use this; use |get_parser()| instead.
@@ -132,7 +130,7 @@ function M.get_parser(bufnr, lang, opts)
   return parsers[bufnr]
 end
 
----@private
+---@package
 ---@param bufnr (integer|nil) Buffer number
 ---@return boolean
 function M._has_parser(bufnr)
@@ -276,7 +274,7 @@ function M.get_captures_at_pos(bufnr, row, col)
         end
       end
     end
-  end, true)
+  end)
   return matches
 end
 
-- 
cgit 


From cbbf8bd666c8419fdab80a0887948c8a36279c19 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Fri, 24 Mar 2023 14:43:14 +0000
Subject: feat(treesitter)!: deprecate top level indexes to modules (#22761)

The following top level Treesitter functions have been moved:
  - vim.treesitter.inspect_language() -> vim.treesitter.language.inspect()
  - vim.treesitter.get_query_files() -> vim.treesitter.query.get_files()
  - vim.treesitter.set_query() -> vim.treesitter.query.set()
  - vim.treesitter.query.set_query() -> vim.treesitter.query.set()
  - vim.treesitter.get_query() -> vim.treesitter.query.get()
  - vim.treesitter.query.get_query() -> vim.treesitter.query.get()
  - vim.treesitter.parse_query() -> vim.treesitter.query.parse()
  - vim.treesitter.query.parse_query() -> vim.treesitter.query.parse()
  - vim.treesitter.add_predicate() -> vim.treesitter.query.add_predicate()
  - vim.treesitter.add_directive() -> vim.treesitter.query.add_directive()
  - vim.treesitter.list_predicates() -> vim.treesitter.query.list_predicates()
  - vim.treesitter.list_directives() -> vim.treesitter.query.list_directives()
  - vim.treesitter.query.get_range() -> vim.treesitter.get_range()
  - vim.treesitter.query.get_node_text() -> vim.treesitter.get_node_text()
---
 runtime/lua/vim/treesitter.lua | 89 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 78 insertions(+), 11 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 685b1d8830..4c3b17daa4 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -1,6 +1,4 @@
 local a = vim.api
-local query = require('vim.treesitter.query')
-local language = require('vim.treesitter.language')
 local LanguageTree = require('vim.treesitter.languagetree')
 local Range = require('vim.treesitter._range')
 
@@ -9,12 +7,9 @@ local parsers = setmetatable({}, { __mode = 'v' })
 
 ---@class TreesitterModule
 ---@field highlighter TSHighlighter
-local M = vim.tbl_extend('error', query, language)
-
-M.language_version = vim._ts_get_language_version()
-M.minimum_language_version = vim._ts_get_minimum_language_version()
-
-setmetatable(M, {
+---@field query TSQueryModule
+---@field language TSLanguageModule
+local M = setmetatable({}, {
   __index = function(t, k)
     ---@diagnostic disable:no-unknown
     if k == 'highlighter' then
@@ -27,9 +22,26 @@ setmetatable(M, {
       t[k] = require('vim.treesitter.query')
       return t[k]
     end
+
+    local query = require('vim.treesitter.query')
+    if query[k] then
+      vim.deprecate('vim.treesitter.' .. k .. '()', 'vim.treesitter.query.' .. k .. '()', '0.10')
+      t[k] = query[k]
+      return t[k]
+    end
+
+    local language = require('vim.treesitter.language')
+    if language[k] then
+      vim.deprecate('vim.treesitter.' .. k .. '()', 'vim.treesitter.language.' .. k .. '()', '0.10')
+      t[k] = language[k]
+      return t[k]
+    end
   end,
 })
 
+M.language_version = vim._ts_get_language_version()
+M.minimum_language_version = vim._ts_get_minimum_language_version()
+
 --- Creates a new parser
 ---
 --- It is not recommended to use this; use |get_parser()| instead.
@@ -47,7 +59,7 @@ function M._create_parser(bufnr, lang, opts)
   vim.fn.bufload(bufnr)
 
   local ft = vim.bo[bufnr].filetype
-  language.add(lang, { filetype = ft ~= '' and ft or nil })
+  M.language.add(lang, { filetype = ft ~= '' and ft or nil })
 
   local self = LanguageTree.new(bufnr, lang, opts)
 
@@ -101,7 +113,7 @@ function M.get_parser(bufnr, lang, opts)
   if lang == nil then
     local ft = vim.bo[bufnr].filetype
     if ft ~= '' then
-      lang = language.get_lang(ft) or ft
+      lang = M.language.get_lang(ft) or ft
       -- TODO(lewis6991): we should error here and not default to ft
       -- if not lang then
       --   error(string.format('filetype %s of buffer %d is not associated with any lang', ft, bufnr))
@@ -152,7 +164,7 @@ function M.get_string_parser(str, lang, opts)
     str = { str, 'string' },
     lang = { lang, 'string' },
   })
-  language.add(lang)
+  M.language.add(lang)
 
   return LanguageTree.new(str, lang, opts)
 end
@@ -196,6 +208,61 @@ function M.get_node_range(node_or_range)
   end
 end
 
+---Get the range of a |TSNode|. Can also supply {source} and {metadata}
+---to get the range with directives applied.
+---@param node TSNode
+---@param source integer|string|nil Buffer or string from which the {node} is extracted
+---@param metadata TSMetadata|nil
+---@return Range6
+function M.get_range(node, source, metadata)
+  if metadata and metadata.range then
+    assert(source)
+    return Range.add_bytes(source, metadata.range)
+  end
+  return { node:range(true) }
+end
+
+---@private
+---@param buf integer
+---@param range Range
+---@returns string
+local function buf_range_get_text(buf, range)
+  local start_row, start_col, end_row, end_col = Range.unpack4(range)
+  if end_col == 0 then
+    if start_row == end_row then
+      start_col = -1
+      start_row = start_row - 1
+    end
+    end_col = -1
+    end_row = end_row - 1
+  end
+  local lines = a.nvim_buf_get_text(buf, start_row, start_col, end_row, end_col, {})
+  return table.concat(lines, '\n')
+end
+
+--- Gets the text corresponding to a given node
+---
+---@param node TSNode
+---@param source (integer|string) Buffer or string from which the {node} is extracted
+---@param opts (table|nil) Optional parameters.
+---          - metadata (table) Metadata of a specific capture. This would be
+---            set to `metadata[capture_id]` when using |vim.treesitter.query.add_directive()|.
+---@return string
+function M.get_node_text(node, source, opts)
+  opts = opts or {}
+  local metadata = opts.metadata or {}
+
+  if metadata.text then
+    return metadata.text
+  elseif type(source) == 'number' then
+    local range = vim.treesitter.get_range(node, source, metadata)
+    return buf_range_get_text(source, range)
+  end
+
+  ---@cast source string
+  return source:sub(select(3, node:start()) + 1, select(3, node:end_()))
+end
+
 --- Determines whether (line, col) position is in node range
 ---
 ---@param node TSNode defining the range
-- 
cgit 


From 61e54f26361b2e7d08eabde9a4cbf42aaa41683b Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Thu, 30 Mar 2023 10:26:28 +0100
Subject: feat: add `vim.treesitter.language.get_filetypes()` (#22643)

---
 runtime/lua/vim/treesitter.lua | 33 +++++++++++++--------------------
 1 file changed, 13 insertions(+), 20 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 4c3b17daa4..2594c1672d 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -58,9 +58,6 @@ function M._create_parser(bufnr, lang, opts)
 
   vim.fn.bufload(bufnr)
 
-  local ft = vim.bo[bufnr].filetype
-  M.language.add(lang, { filetype = ft ~= '' and ft or nil })
-
   local self = LanguageTree.new(bufnr, lang, opts)
 
   ---@private
@@ -94,7 +91,12 @@ function M._create_parser(bufnr, lang, opts)
   return self
 end
 
---- Returns the parser for a specific buffer and filetype and attaches it to the buffer
+--- @private
+local function valid_lang(lang)
+  return lang and lang ~= ''
+end
+
+--- Returns the parser for a specific buffer and attaches it to the buffer
 ---
 --- If needed, this will create the parser.
 ---
@@ -110,18 +112,12 @@ function M.get_parser(bufnr, lang, opts)
     bufnr = a.nvim_get_current_buf()
   end
 
-  if lang == nil then
-    local ft = vim.bo[bufnr].filetype
-    if ft ~= '' then
-      lang = M.language.get_lang(ft) or ft
-      -- TODO(lewis6991): we should error here and not default to ft
-      -- if not lang then
-      --   error(string.format('filetype %s of buffer %d is not associated with any lang', ft, bufnr))
-      -- end
-    else
-      if parsers[bufnr] then
-        return parsers[bufnr]
-      end
+  if not valid_lang(lang) then
+    lang = M.language.get_lang(vim.bo[bufnr].filetype) or vim.bo[bufnr].filetype
+  end
+
+  if not valid_lang(lang) then
+    if not parsers[bufnr] then
       error(
         string.format(
           'There is no parser available for buffer %d and one could not be'
@@ -131,9 +127,7 @@ function M.get_parser(bufnr, lang, opts)
         )
       )
     end
-  end
-
-  if parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
+  elseif parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
     parsers[bufnr] = M._create_parser(bufnr, lang, opts)
   end
 
@@ -164,7 +158,6 @@ function M.get_string_parser(str, lang, opts)
     str = { str, 'string' },
     lang = { lang, 'string' },
   })
-  M.language.add(lang)
 
   return LanguageTree.new(str, lang, opts)
 end
-- 
cgit 


From b75acd2f94feac5b55eaa219e7beb2af93f15cf0 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Tue, 4 Apr 2023 13:07:27 +0100
Subject: fix(treesitter): disable folding in inspect_tree() (#22885)

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

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 2594c1672d..44bf4c9e20 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -538,6 +538,7 @@ function M.inspect_tree(opts)
 
   vim.wo[w].scrolloff = 5
   vim.wo[w].wrap = false
+  vim.wo[w].foldmethod = 'manual' -- disable folding
   vim.bo[b].buflisted = false
   vim.bo[b].buftype = 'nofile'
   vim.bo[b].bufhidden = 'wipe'
-- 
cgit 


From b1de4820b7b1a527f4d0cf9a20192d92bea1d9c4 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Sat, 1 Apr 2023 12:55:04 +0100
Subject: refactor(treesitter): move inspect_tree impl

---
 runtime/lua/vim/treesitter.lua | 205 +----------------------------------------
 1 file changed, 2 insertions(+), 203 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 44bf4c9e20..092fdf0ae2 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -502,209 +502,8 @@ end
 ---                        function, it accepts the buffer number of the source buffer as its only
 ---                        argument and should return a string.
 function M.inspect_tree(opts)
-  vim.validate({
-    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.lang))
-
-  -- 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 '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.wo[w].foldmethod = 'manual' -- disable folding
-  vim.bo[b].buflisted = false
-  vim.bo[b].buftype = 'nofile'
-  vim.bo[b].bufhidden = 'wipe'
-  vim.bo[b].filetype = 'query'
-
-  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)
-
-  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()
-      local row, col = unpack(a.nvim_win_get_cursor(w))
-      local curnode = pg:get(row)
-      while curnode and not curnode.named do
-        row = row - 1
-        curnode = pg:get(row)
-      end
-
-      pg.opts.anon = not pg.opts.anon
-      pg:draw(b)
-
-      if not curnode then
-        return
-      end
-
-      local id = curnode.id
-      for i, node in pg:iter() do
-        if node.id == id then
-          a.nvim_win_set_cursor(w, { i, col })
-          break
-        end
-      end
-    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',
-      })
-
-      local topline, botline = vim.fn.line('w0', win), vim.fn.line('w$', win)
-
-      -- Move the cursor if highlighted range is completely out of view
-      if pos.lnum < topline and pos.end_lnum < topline then
-        a.nvim_win_set_cursor(win, { pos.end_lnum + 1, 0 })
-      elseif pos.lnum > botline and pos.end_lnum > botline then
-        a.nvim_win_set_cursor(win, { pos.lnum + 1, 0 })
-      end
-    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_node = M.get_node({
-        bufnr = buf,
-        lang = opts.lang,
-        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, opts.lang))
-      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,
-  })
+  ---@cast opts InspectTreeOpts
+  require('vim.treesitter.playground').inspect_tree(opts)
 end
 
 --- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr':
-- 
cgit 


From 34ac75b32927328a0c691c5bda987c0fdb5ce9eb Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Wed, 5 Apr 2023 17:19:53 +0100
Subject: refactor: rename local API alias from a to api

Problem:
  Codebase inconsistently binds vim.api onto a or api.

Solution:
  Use api everywhere. a as an identifier is too short to have at the
  module level.
---
 runtime/lua/vim/treesitter.lua | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 092fdf0ae2..d1f5996768 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -1,4 +1,4 @@
-local a = vim.api
+local api = vim.api
 local LanguageTree = require('vim.treesitter.languagetree')
 local Range = require('vim.treesitter._range')
 
@@ -80,7 +80,7 @@ function M._create_parser(bufnr, lang, opts)
 
   local source = self:source() --[[@as integer]]
 
-  a.nvim_buf_attach(
+  api.nvim_buf_attach(
     source,
     false,
     { on_bytes = bytes_cb, on_detach = detach_cb, on_reload = reload_cb, preview = true }
@@ -109,7 +109,7 @@ function M.get_parser(bufnr, lang, opts)
   opts = opts or {}
 
   if bufnr == nil or bufnr == 0 then
-    bufnr = a.nvim_get_current_buf()
+    bufnr = api.nvim_get_current_buf()
   end
 
   if not valid_lang(lang) then
@@ -141,7 +141,7 @@ end
 ---@return boolean
 function M._has_parser(bufnr)
   if bufnr == nil or bufnr == 0 then
-    bufnr = a.nvim_get_current_buf()
+    bufnr = api.nvim_get_current_buf()
   end
   return parsers[bufnr] ~= nil
 end
@@ -229,7 +229,7 @@ local function buf_range_get_text(buf, range)
     end_col = -1
     end_row = end_row - 1
   end
-  local lines = a.nvim_buf_get_text(buf, start_row, start_col, end_row, end_col, {})
+  local lines = api.nvim_buf_get_text(buf, start_row, start_col, end_row, end_col, {})
   return table.concat(lines, '\n')
 end
 
@@ -294,7 +294,7 @@ end
 ---@return table[] List of captures `{ capture = "name", metadata = { ... } }`
 function M.get_captures_at_pos(bufnr, row, col)
   if bufnr == 0 then
-    bufnr = a.nvim_get_current_buf()
+    bufnr = api.nvim_get_current_buf()
   end
   local buf_highlighter = M.highlighter.active[bufnr]
 
@@ -345,8 +345,8 @@ end
 ---@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)
-  local cursor = a.nvim_win_get_cursor(winnr)
+  local bufnr = api.nvim_win_get_buf(winnr)
+  local cursor = api.nvim_win_get_cursor(winnr)
 
   local data = M.get_captures_at_pos(bufnr, cursor[1] - 1, cursor[2])
 
@@ -374,7 +374,7 @@ function M.get_node(opts)
   local bufnr = opts.bufnr
 
   if not bufnr or bufnr == 0 then
-    bufnr = a.nvim_get_current_buf()
+    bufnr = api.nvim_get_current_buf()
   end
 
   local row, col
@@ -383,10 +383,10 @@ function M.get_node(opts)
     row, col = opts.pos[1], opts.pos[2]
   else
     assert(
-      bufnr == a.nvim_get_current_buf(),
+      bufnr == api.nvim_get_current_buf(),
       'Position must be explicitly provided when not using the current buffer'
     )
-    local pos = a.nvim_win_get_cursor(0)
+    local pos = api.nvim_win_get_cursor(0)
     -- Subtract one to account for 1-based row indexing in nvim_win_get_cursor
     row, col = pos[1] - 1, pos[2]
   end
@@ -417,7 +417,7 @@ end
 function M.get_node_at_pos(bufnr, row, col, opts)
   vim.deprecate('vim.treesitter.get_node_at_pos()', 'vim.treesitter.get_node()', '0.10')
   if bufnr == 0 then
-    bufnr = a.nvim_get_current_buf()
+    bufnr = api.nvim_get_current_buf()
   end
   local ts_range = { row, col, row, col }
 
@@ -440,7 +440,7 @@ end
 function M.get_node_at_cursor(winnr)
   vim.deprecate('vim.treesitter.get_node_at_cursor()', 'vim.treesitter.get_node():type()', '0.10')
   winnr = winnr or 0
-  local bufnr = a.nvim_win_get_buf(winnr)
+  local bufnr = api.nvim_win_get_buf(winnr)
 
   return M.get_node({ bufnr = bufnr, ignore_injections = false }):type()
 end
@@ -465,7 +465,7 @@ end
 ---@param bufnr (integer|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()
+  bufnr = bufnr or api.nvim_get_current_buf()
   local parser = M.get_parser(bufnr, lang)
   M.highlighter.new(parser)
 end
@@ -474,7 +474,7 @@ end
 ---
 ---@param bufnr (integer|nil) Buffer to stop highlighting (default: current buffer)
 function M.stop(bufnr)
-  bufnr = bufnr or a.nvim_get_current_buf()
+  bufnr = bufnr or api.nvim_get_current_buf()
 
   if M.highlighter.active[bufnr] then
     M.highlighter.active[bufnr]:destroy()
-- 
cgit 


From ef64e225f6f6c01280aa8472bebe812016f357bf Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Thu, 18 May 2023 10:52:01 +0100
Subject: fix(treesitter): allow foldexpr without highlights (#23672)

Ref nvim-treesitter/nvim-treesitter#4748
---
 runtime/lua/vim/treesitter.lua | 10 ----------
 1 file changed, 10 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index d1f5996768..12fbe1654f 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -136,16 +136,6 @@ function M.get_parser(bufnr, lang, opts)
   return parsers[bufnr]
 end
 
----@package
----@param bufnr (integer|nil) Buffer number
----@return boolean
-function M._has_parser(bufnr)
-  if bufnr == nil or bufnr == 0 then
-    bufnr = api.nvim_get_current_buf()
-  end
-  return parsers[bufnr] ~= nil
-end
-
 --- Returns a string parser
 ---
 ---@param str string Text to parse
-- 
cgit 


From c48b1421af28d0317c807bca00c7e2fff97d9ad0 Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Tue, 6 Jun 2023 08:23:20 -0700
Subject: refactor!: rename "playground" => "dev" #23919

Problem:
"playground" is new jargon that overlaps with existing concepts:
"dev" (`:help dev`) and "view" (also "scratch" `:help scratch-buffer`) .

Solution:
We should consistently use "dev" as the namespace for where "developer
tools" live. For purposes of a "throwaway sandbox object", we can use
the name "view".
- Rename `TSPlayground` => `TSView`
- Rename `playground.lua` => `dev.lua`
---
 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 12fbe1654f..5526c9858c 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -493,7 +493,7 @@ end
 ---                        argument and should return a string.
 function M.inspect_tree(opts)
   ---@cast opts InspectTreeOpts
-  require('vim.treesitter.playground').inspect_tree(opts)
+  require('vim.treesitter.dev').inspect_tree(opts)
 end
 
 --- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr':
-- 
cgit 


From be74807eef13ff8c90d55cf8b22b01d6d33b1641 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Tue, 18 Jul 2023 15:42:30 +0100
Subject: docs(lua): more improvements (#24387)

* docs(lua): teach lua2dox how to table

* docs(lua): teach gen_vimdoc.py about local functions

No more need to mark local functions with @private

* docs(lua): mention @nodoc and @meta in dev-lua-doc

* fixup!

Co-authored-by: Justin M. Keyes 

---------

Co-authored-by: Justin M. Keyes 
---
 runtime/lua/vim/treesitter.lua | 8 +++-----
 1 file changed, 3 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 5526c9858c..8bd85d3734 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -39,7 +39,10 @@ local M = setmetatable({}, {
   end,
 })
 
+--- @nodoc
 M.language_version = vim._ts_get_language_version()
+
+--- @nodoc
 M.minimum_language_version = vim._ts_get_minimum_language_version()
 
 --- Creates a new parser
@@ -60,12 +63,10 @@ function M._create_parser(bufnr, lang, opts)
 
   local self = LanguageTree.new(bufnr, lang, opts)
 
-  ---@private
   local function bytes_cb(_, ...)
     self:_on_bytes(...)
   end
 
-  ---@private
   local function detach_cb(_, ...)
     if parsers[bufnr] == self then
       parsers[bufnr] = nil
@@ -73,7 +74,6 @@ function M._create_parser(bufnr, lang, opts)
     self:_on_detach(...)
   end
 
-  ---@private
   local function reload_cb(_)
     self:_on_reload()
   end
@@ -91,7 +91,6 @@ function M._create_parser(bufnr, lang, opts)
   return self
 end
 
---- @private
 local function valid_lang(lang)
   return lang and lang ~= ''
 end
@@ -205,7 +204,6 @@ function M.get_range(node, source, metadata)
   return { node:range(true) }
 end
 
----@private
 ---@param buf integer
 ---@param range Range
 ---@returns string
-- 
cgit 


From 48085e40bb0e4435ddb2eb7f14b4531b943e0c89 Mon Sep 17 00:00:00 2001
From: Micah Halter 
Date: Mon, 24 Jul 2023 10:26:38 -0400
Subject: fix(treesitter): stop() should treat 0 as current buffer #24450

---
 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 8bd85d3734..04420c81e3 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -462,7 +462,7 @@ end
 ---
 ---@param bufnr (integer|nil) Buffer to stop highlighting (default: current buffer)
 function M.stop(bufnr)
-  bufnr = bufnr or api.nvim_get_current_buf()
+  bufnr = (bufnr and bufnr ~= 0) and bufnr or api.nvim_get_current_buf()
 
   if M.highlighter.active[bufnr] then
     M.highlighter.active[bufnr]:destroy()
-- 
cgit 


From 5d8ab32f3871b0232972cac1116ac7cba98389e5 Mon Sep 17 00:00:00 2001
From: Maria José Solano 
Date: Fri, 25 Aug 2023 11:17:36 -0700
Subject: feat(treesitter): add a query editor (#24703)

---
 runtime/lua/vim/treesitter.lua | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 04420c81e3..4f84fc2e0f 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -472,8 +472,8 @@ 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.
+--- display of the source language of each node, "o" to toggle the query previewer, and press
+---  to jump to the node under the cursor in the source buffer.
 ---
 --- Can also be shown with `:InspectTree`. *:InspectTree*
 ---
@@ -494,6 +494,13 @@ function M.inspect_tree(opts)
   require('vim.treesitter.dev').inspect_tree(opts)
 end
 
+--- Open a window for live editing of a treesitter query.
+---
+--- Can also be shown with `:PreviewQuery`. *:PreviewQuery*
+function M.preview_query()
+  require('vim.treesitter.dev').preview_query()
+end
+
 --- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr':
 --- 
lua
 --- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
-- 
cgit 


From 2e92065686f62851318150a315591c30b8306a4b Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Thu, 14 Sep 2023 08:23:01 -0500
Subject: docs: replace 
 with ``` (#25136)

---
 runtime/lua/vim/treesitter.lua | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

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

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 4f84fc2e0f..169aa6c269 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -441,14 +441,15 @@ end
 --- In this case, add ``vim.bo.syntax = 'on'`` after the call to `start`.
 ---
 --- Example:
---- 
lua
+---
+--- ```lua
 --- vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex',
 ---     callback = function(args)
 ---         vim.treesitter.start(args.buf, 'latex')
 ---         vim.bo[args.buf].syntax = 'on'  -- only if additional legacy syntax is needed
 ---     end
 --- })
---- 
+--- ``` --- ---@param bufnr (integer|nil) Buffer to be highlighted (default: current buffer) ---@param lang (string|nil) Language of the parser (default: buffer filetype) @@ -502,9 +503,11 @@ function M.preview_query() end --- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr': ----
lua
+---
+--- ```lua
 --- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
---- 
+--- ``` +--- ---@param lnum integer|nil Line number to calculate fold level for ---@return string function M.foldexpr(lnum) -- cgit From 28233bcb49067aaa70fa6e5fec14e2cc4bcaa315 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Fri, 15 Sep 2023 03:10:55 -0700 Subject: refactor(treesitter): rename "preview" => "edit" #25161 "Edit" more closely describes the generic application than "Preview", though the buffer contents don't (yet) map to an actual file on disk. https://github.com/neovim/neovim/pull/24703#discussion_r1321719133 --- runtime/lua/vim/treesitter.lua | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 169aa6c269..cc8be72670 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -473,7 +473,7 @@ 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, "o" to toggle the query previewer, and press +--- display of the source language of each node, "o" to toggle the query editor, and press --- to jump to the node under the cursor in the source buffer. --- --- Can also be shown with `:InspectTree`. *:InspectTree* @@ -495,13 +495,6 @@ function M.inspect_tree(opts) require('vim.treesitter.dev').inspect_tree(opts) end ---- Open a window for live editing of a treesitter query. ---- ---- Can also be shown with `:PreviewQuery`. *:PreviewQuery* -function M.preview_query() - require('vim.treesitter.dev').preview_query() -end - --- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr': --- --- ```lua -- cgit From bc0bf9d030bbcb01db69c44cf88b95ca41dd3065 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Wed, 20 Sep 2023 19:03:40 -0700 Subject: docs: fix type warnings --- runtime/lua/vim/treesitter.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index cc8be72670..0e34cbcbcc 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -127,6 +127,7 @@ function M.get_parser(bufnr, lang, opts) ) end elseif parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then + assert(lang, 'lang should be valid') parsers[bufnr] = M._create_parser(bufnr, lang, opts) end @@ -162,7 +163,7 @@ function M.is_ancestor(dest, source) return false end - local current = source + local current = source ---@type TSNode? while current ~= nil do if current == dest then return true @@ -491,7 +492,7 @@ end --- function, it accepts the buffer number of the source buffer as its only --- argument and should return a string. function M.inspect_tree(opts) - ---@cast opts InspectTreeOpts + ---@diagnostic disable-next-line: invisible require('vim.treesitter.dev').inspect_tree(opts) end -- cgit From 9ce1623837a817c3f4f5deff9c8ba862578b6009 Mon Sep 17 00:00:00 2001 From: Till Bungert Date: Sun, 1 Oct 2023 21:10:51 +0200 Subject: feat(treesitter): add foldtext with treesitter highlighting (#25391) --- runtime/lua/vim/treesitter.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 0e34cbcbcc..f863942d3b 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -508,4 +508,16 @@ function M.foldexpr(lnum) return require('vim.treesitter._fold').foldexpr(lnum) end +--- Returns the highlighted content of the first line of the fold or falls back to |foldtext()| +--- if no treesitter parser is found. Can be set directly to 'foldtext': +--- +--- ```lua +--- vim.wo.foldtext = 'v:lua.vim.treesitter.foldtext()' +--- ``` +--- +---@return { [1]: string, [2]: string[] }[] | string +function M.foldtext() + return require('vim.treesitter._fold').foldtext() +end + return M -- cgit From 6c150e0b9312ece13f13b7ff2e9743592bc9d431 Mon Sep 17 00:00:00 2001 From: L Lllvvuu Date: Wed, 27 Sep 2023 02:51:42 -0700 Subject: docs(treesitter): add disclaimer about needing to parse before `get_node()` Problem: --- Misuse of `get_node()` is common: https://github.com/search?q=get_node_at_cursor+language%3Alua&type=code Solution: --- Add a note clarifying proper usage. --- runtime/lua/vim/treesitter.lua | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'runtime/lua/vim/treesitter.lua') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index f863942d3b..e7a66c00b2 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -350,6 +350,14 @@ end --- Returns the smallest named node at the given position --- +--- NOTE: Calling this on an unparsed tree can yield an invalid node. +--- If the tree is not known to be parsed by, e.g., an active highlighter, +--- parse the tree first via +--- +--- ```lua +--- vim.treesitter.get_parser(bufnr):parse(range) +--- ``` +--- ---@param opts table|nil Optional keyword arguments: --- - bufnr integer|nil Buffer number (nil or 0 for current buffer) --- - pos table|nil 0-indexed (row, col) tuple. Defaults to cursor position in the -- cgit