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.
This commit is contained in:
Christian Clason
2022-09-16 09:05:05 +02:00
committed by GitHub
parent 982fef6018
commit 9ec4b20be6
3 changed files with 32 additions and 26 deletions

View File

@@ -203,7 +203,7 @@ purpose, e.g., `queries/lua/highlights.scm` for highlighting Lua files.
By default, the first query on `runtimepath` is used (which usually implies By default, the first query on `runtimepath` is used (which usually implies
that user config takes precedence over plugins, which take precedence over that user config takes precedence over plugins, which take precedence over
queries bundled with Neovim). If a query should extend other queries instead queries bundled with Neovim). If a query should extend other queries instead
of replacing them, use |ts-query-modeline-extends|. of replacing them, use |treesitter-query-modeline-extends|.
See |lua-treesitter-query| for the list of available methods for working with See |lua-treesitter-query| for the list of available methods for working with
treesitter queries from Lua. treesitter queries from Lua.
@@ -220,28 +220,28 @@ to only match identifier corresponding to the `"foo"` text.
The following predicates are built in: The following predicates are built in:
`eq?` *ts-predicate-eq?* `eq?` *treesitter-predicate-eq?*
Match a string against the text corresponding to a node: > Match a string against the text corresponding to a node: >
((identifier) @foo (#eq? @foo "foo")) ((identifier) @foo (#eq? @foo "foo"))
((node1) @left (node2) @right (#eq? @left @right)) ((node1) @left (node2) @right (#eq? @left @right))
< <
`match?` *ts-predicate-match?* `match?` *treesitter-predicate-match?*
`vim-match?` *ts-predicate-vim-match?* `vim-match?` *treesitter-predicate-vim-match?*
Match a |regexp| against the text corresponding to a node: > Match a |regexp| against the text corresponding to a node: >
((identifier) @constant (#match? @constant "^[A-Z_]+$")) ((identifier) @constant (#match? @constant "^[A-Z_]+$"))
< Note: The `^` and `$` anchors will match the start and end of the < Note: The `^` and `$` anchors will match the start and end of the
node's text. node's text.
`lua-match?` *ts-predicate-lua-match?* `lua-match?` *treesitter-predicate-lua-match?*
Match a |lua-pattern| against the text corresponding to a node, Match a |lua-pattern| against the text corresponding to a node,
similar to `match?` similar to `match?`
`contains?` *ts-predicate-contains?* `contains?` *treesitter-predicate-contains?*
Match a string against parts of the text corresponding to a node: > Match a string against parts of the text corresponding to a node: >
((identifier) @foo (#contains? @foo "foo")) ((identifier) @foo (#contains? @foo "foo"))
((identifier) @foo-bar (#contains @foo-bar "foo" "bar")) ((identifier) @foo-bar (#contains @foo-bar "foo" "bar"))
< <
`any-of?` *ts-predicate-any-of?* `any-of?` *treesitter-predicate-any-of?*
Match any of the given strings against the text corresponding to Match any of the given strings against the text corresponding to
a node: > a node: >
((identifier) @foo (#any-of? @foo "foo" "bar")) ((identifier) @foo (#any-of? @foo "foo" "bar"))
@@ -267,7 +267,7 @@ effects. For example, the |set!| predicate sets metadata on the match or node: >
< <
The following directives are built in: The following directives are built in:
`set!` *ts-directive-set!* `set!` *treesitter-directive-set!*
Sets key/value metadata for a specific match or capture. Value is Sets key/value metadata for a specific match or capture. Value is
accessible as either `metadata[key]` (match specific) or accessible as either `metadata[key]` (match specific) or
`metadata[capture_id][key]` (capture specific). `metadata[capture_id][key]` (capture specific).
@@ -281,7 +281,7 @@ The following directives are built in:
((identifier) @foo (#set! @foo "kind" "parameter")) ((identifier) @foo (#set! @foo "kind" "parameter"))
((node1) @left (node2) @right (#set! "type" "pair")) ((node1) @left (node2) @right (#set! "type" "pair"))
< <
`offset!` *ts-directive-offset!* `offset!` *treesitter-directive-offset!*
Takes the range of the captured node and applies an offset. This will Takes the range of the captured node and applies an offset. This will
generate a new range object for the captured node as generate a new range object for the captured node as
`metadata[capture_id].range`. `metadata[capture_id].range`.
@@ -302,13 +302,13 @@ Use `vim.treesitter.query.`|list_directives()| to list all available
directives. directives.
TREESITTER QUERY MODELINES *ts-query-modeline* TREESITTER QUERY MODELINES *treesitter-query-modeline*
Neovim supports to customize the behavior of the queries using a set of Neovim supports to customize the behavior of the queries using a set of
"modelines", that is comments in the queries starting with `;`. Here are the "modelines", that is comments in the queries starting with `;`. Here are the
currently supported modeline alternatives: currently supported modeline alternatives:
`inherits: {lang}...` *ts-query-modeline-inherits* `inherits: {lang}...` *treesitter-query-modeline-inherits*
Specifies that this query should inherit the queries from {lang}. Specifies that this query should inherit the queries from {lang}.
This will recursively descend in the queries of {lang} unless wrapped This will recursively descend in the queries of {lang} unless wrapped
in parentheses: `({lang})`. in parentheses: `({lang})`.
@@ -316,7 +316,7 @@ currently supported modeline alternatives:
language. If you want your query to extend the queries of the same language. If you want your query to extend the queries of the same
language, use `extends`. language, use `extends`.
`extends` *ts-query-modeline-extends* `extends` *treesitter-query-modeline-extends*
Specifies that this query should be used as an extension for the Specifies that this query should be used as an extension for the
query, i.e. that it should be merged with the others. query, i.e. that it should be merged with the others.
Note: The order of the extensions, and the query that will be used as Note: The order of the extensions, and the query that will be used as
@@ -436,14 +436,20 @@ get_captures_at_cursor({winnr}) *get_captures_at_cursor()*
*get_captures_at_position()* *get_captures_at_position()*
get_captures_at_position({bufnr}, {row}, {col}) get_captures_at_position({bufnr}, {row}, {col})
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).
Parameters: ~ Parameters: ~
{bufnr} (number) Buffer number (0 for current buffer) {bufnr} (number) Buffer number (0 for current buffer)
{row} (number) Position row {row} (number) Position row
{col} (number) Position column {col} (number) Position column
Return: ~ Return: ~
table[] Captures of the form `{ capture = "capture name", priority = table[] List of captures `{ capture = "capture name", metadata = { ...
capture priority }` } }`
get_node_at_cursor({winnr}) *get_node_at_cursor()* get_node_at_cursor({winnr}) *get_node_at_cursor()*
Returns the smallest named node under the cursor Returns the smallest named node under the cursor

View File

@@ -179,6 +179,7 @@ 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 node userdata |tsnode|
---@param range table ---@param range table
--- ---
@@ -192,16 +193,15 @@ function M.node_contains(node, range)
end end
--- Returns a list of highlight captures at the given position --- Returns a list of highlight captures at the given position
-- ---
---@param bufnr number Buffer number (0 for current buffer) --- Each capture is represented by a table containing the capture name as a string as
---@param row number Position row --- well as a table of metadata (`priority`, `conceal`, ...; empty if none are defined).
---@param col number Position column
--- ---
---@param bufnr number Buffer number (0 for current buffer) ---@param bufnr number Buffer number (0 for current buffer)
---@param row number Position row ---@param row number Position row
---@param col number Position column ---@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) function M.get_captures_at_position(bufnr, row, col)
if bufnr == 0 then if bufnr == 0 then
bufnr = a.nvim_get_current_buf() 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 if M.is_in_node_range(node, row, col) then
local c = q._query.captures[capture] -- name of the capture in the query local c = q._query.captures[capture] -- name of the capture in the query
if c ~= nil then if c ~= nil then
table.insert(matches, { capture = c, priority = metadata.priority }) table.insert(matches, { capture = c, metadata = metadata })
end end
end end
end end

View File

@@ -605,8 +605,8 @@ describe('treesitter highlighting', function()
}} }}
eq({ eq({
{capture='Error', priority='101'}; {capture='Error', metadata = { priority='101' }};
{capture='type'}; {capture='type', metadata = { } };
}, exec_lua [[ return vim.treesitter.get_captures_at_position(0, 0, 2) ]]) }, exec_lua [[ return vim.treesitter.get_captures_at_position(0, 0, 2) ]])
end) end)