1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
local L = {}
--- Finds the index of a value in an array.
---
--- This function iterates over the provided array and checks if the specified value
--- is present. If found, it returns the index of the value. If the value is not found,
--- the function returns `nil`.
---
--- @param array table The array to search through.
--- @param value any The value to find in the array.
--- @return number|nil The index of the value if found, or `nil` otherwise.
local function index_of(array, value)
for i, v in ipairs(array) do
if v == value then
return i
end
end
return nil -- si no se encuentra el valor
end
--- Retrieves matches from a parsed Treesitter query based on the specified parameters.
---
--- @param query_string string The Treesitter query string to be parsed.
--- @param lang string The language of the current buffer.
--- @param filter_func? fun(match: TSNode[], captures: string[]):boolean A
--- function to filter matches. Receives the match and captures as arguments.
--- @param map_func? fun(match: TSNode[], captures: string[]):any A function to
--- transform the captured node. Receives the match and captures as arguments.
--- @param max_results number|nil The maximum number of results to return.
---
--- @return table A list of captured nodes that match the query, filtered and
--- transformed as specified.
function L.get_matches(query_string, lang, filter_func, map_func, max_results)
local ts_utils = require("nvim-treesitter.ts_utils")
local ts_query = require("vim.treesitter.query")
local bufnr = vim.api.nvim_get_current_buf()
-- Parse the query
local query = ts_query.parse(lang, query_string)
-- Get the root syntax tree node
local root = ts_utils.get_root_for_position(unpack(vim.api.nvim_win_get_cursor(0)))
if not root then
return {}
end
local results = {}
local count = 0
-- Iterate over matches
for _, match, _ in query:iter_matches(root, bufnr, 0, -1) do
if not filter_func or filter_func(match, query.captures) then
local mapped_result = map_func and map_func(match, query.captures)
or match
if mapped_result then
table.insert(results, mapped_result)
count = count + 1
if max_results and count >= max_results then
break
end
end
end
end
return results
end
--- Gets the text of all captures that match the query
--- @param query_string string The treesitter query string
--- @param lang string The language of the current buffer
--- @param node_capture_name string The name of the capture that contains the
--- node to check
--- @param text_capture_name string|nil The name of the capture that contains
--- the text to return (if different from node_capture_name)
--- @param filter_func? fun(match: TSNode[], captures: string[]):boolean A
--- function to filter matches. Receives the match and captures as arguments.
--- @param max_results number|nil The maximum number of results to return.
--- @return string[] A list of texts of the captures that match the query
function L.get_match_texts(query_string, lang, node_capture_name,
text_capture_name, filter_func, max_results)
if not text_capture_name then
text_capture_name = node_capture_name
end
return L.get_matches(query_string, lang, filter_func, function(match, captures)
-- Return the text of the text capture
local text_capture_index = index_of(captures, text_capture_name)
if not text_capture_index then
return nil
end
local captured_node = match[text_capture_index][1]
local bufnr = vim.api.nvim_get_current_buf()
return vim.treesitter.get_node_text(captured_node, bufnr)
end, max_results)
end
--- Gets the text of the capture at the cursor position
--- @param query_string string The treesitter query string
--- @param lang string The language of the current buffer
--- @param node_capture_name string The name of the capture that contains the
--- node to check
--- @param text_capture_name string|nil The name of the capture that contains
--- the text to return (if different from node_capture_name)
--- @return string The text of the capture at the cursor position, or an empty
--- string if not found
function L.get_match_text_at_cursor(query_string, lang, node_capture_name, text_capture_name)
local node_at_cursor = vim.treesitter.get_node()
if not node_at_cursor then
return ""
end
local matches = L.get_match_texts(
query_string,
lang,
node_capture_name,
text_capture_name,
function(match, captures)
-- Check if the node at cursor is within the captured node
local capture_index = index_of(captures, node_capture_name)
if not capture_index then
return false
end
local captured_node = match[capture_index][1]
return captured_node == node_at_cursor
or vim.treesitter.is_ancestor(captured_node, node_at_cursor)
end,
1
)
return matches and matches[1] or ""
end
return L
|