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