diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 71ec84c2f2..07b1b8646a 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -289,6 +289,7 @@ TREESITTER false, which allows it to return anonymous nodes as well as named nodes. • |treesitter-directive-trim!| can trim all whitespace (not just empty lines) from both sides of a node. +• |vim.treesitter.get_captures_at_pos()| now returns the `id` of each capture TUI diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 877d90a3b7..a0860c60a6 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -902,8 +902,8 @@ get_captures_at_pos({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). + string, the capture's language, a table of metadata (`priority`, + `conceal`, ...; empty if none are defined), and the id of the capture. Parameters: ~ • {bufnr} (`integer`) Buffer number (0 for current buffer) @@ -911,7 +911,7 @@ get_captures_at_pos({bufnr}, {row}, {col}) • {col} (`integer`) Position column Return: ~ - (`{capture: string, lang: string, metadata: vim.treesitter.query.TSMetadata}[]`) + (`{capture: string, lang: string, metadata: vim.treesitter.query.TSMetadata, id: integer}[]`) get_node({opts}) *vim.treesitter.get_node()* Returns the smallest named node at the given position diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 5f4e796413..89dc4e289a 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -245,14 +245,15 @@ end --- 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). +--- Each capture is represented by a table containing the capture name as a string, the capture's +--- language, a table of metadata (`priority`, `conceal`, ...; empty if none are defined), and the +--- id of the capture. --- ---@param bufnr integer Buffer number (0 for current buffer) ---@param row integer Position row ---@param col integer Position column --- ----@return {capture: string, lang: string, metadata: vim.treesitter.query.TSMetadata}[] +---@return {capture: string, lang: string, metadata: vim.treesitter.query.TSMetadata, id: integer}[] function M.get_captures_at_pos(bufnr, row, col) bufnr = vim._resolve_bufnr(bufnr) local buf_highlighter = M.highlighter.active[bufnr] @@ -285,12 +286,15 @@ function M.get_captures_at_pos(bufnr, row, col) local iter = q:query():iter_captures(root, buf_highlighter.bufnr, row, row + 1) - for capture, node, metadata in iter do + for id, node, metadata in iter do if M.is_in_node_range(node, row, col) then ---@diagnostic disable-next-line: invisible - local c = q._query.captures[capture] -- name of the capture in the query - if c ~= nil then - table.insert(matches, { capture = c, metadata = metadata, lang = tree:lang() }) + local capture = q._query.captures[id] -- name of the capture in the query + if capture ~= nil then + table.insert( + matches, + { capture = capture, metadata = metadata, lang = tree:lang(), id = id } + ) end end end diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua index 028c01f14a..7f0a3cb342 100644 --- a/test/functional/treesitter/highlight_spec.lua +++ b/test/functional/treesitter/highlight_spec.lua @@ -12,6 +12,7 @@ local fn = n.fn local eq = t.eq local hl_query_c = [[ + ; query (ERROR) @error "if" @keyword @@ -639,8 +640,8 @@ describe('treesitter highlighting (C)', function() } eq({ - { capture = 'constant', metadata = { priority = '101' }, lang = 'c' }, - { capture = 'type', metadata = {}, lang = 'c' }, + { capture = 'constant', metadata = { priority = '101' }, lang = 'c', id = 14 }, + { capture = 'type', metadata = {}, lang = 'c', id = 3 }, }, exec_lua [[ return vim.treesitter.get_captures_at_pos(0, 0, 2) ]]) end)