mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
treesitter: add predicate "any-of?" (#14344)
For the case of Clojure and other Lisp syntax highlighting, it is necessary to create huge regexps consisting of hundreds of symbols with the pipe (|) character. To make things more difficult, these Lisp symbols sometimes consists of special characters that are themselves part of special regexp characters like '*'. In addition to being difficult to maintain, it's performance is suboptimal. This patch introduces a new predicate to perform 'source' matching in amortized constant time. This is accomplished by compiling a hash table on the first use.
This commit is contained in:
parent
61aefaf299
commit
7c95697026
@ -211,6 +211,11 @@ Here is a list of built-in predicates :
|
|||||||
text corresponding to the node : >
|
text corresponding to the 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?*
|
||||||
|
Will check if the text is the same as any of the following
|
||||||
|
arguments : >
|
||||||
|
((identifier) @foo (#any-of? @foo "foo" "bar"))
|
||||||
<
|
<
|
||||||
*lua-treesitter-not-predicate*
|
*lua-treesitter-not-predicate*
|
||||||
Each predicate has a `not-` prefixed predicate that is just the negation of
|
Each predicate has a `not-` prefixed predicate that is just the negation of
|
||||||
|
@ -260,7 +260,25 @@ local predicate_handlers = {
|
|||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
end,
|
||||||
|
|
||||||
|
["any-of?"] = function(match, _, source, predicate)
|
||||||
|
local node = match[predicate[2]]
|
||||||
|
local node_text = M.get_node_text(node, source)
|
||||||
|
|
||||||
|
-- Since 'predicate' will not be used by callers of this function, use it
|
||||||
|
-- to store a string set built from the list of words to check against.
|
||||||
|
local string_set = predicate["string_set"]
|
||||||
|
if not string_set then
|
||||||
|
string_set = {}
|
||||||
|
for i=3,#predicate do
|
||||||
|
string_set[predicate[i]] = true
|
||||||
end
|
end
|
||||||
|
predicate["string_set"] = string_set
|
||||||
|
end
|
||||||
|
|
||||||
|
return string_set[node_text]
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- As we provide lua-match? also expose vim-match?
|
-- As we provide lua-match? also expose vim-match?
|
||||||
|
@ -270,6 +270,65 @@ void ui_refresh(void)
|
|||||||
}, res)
|
}, res)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('supports builtin query predicate any-of?', function()
|
||||||
|
if pending_c_parser(pending) then return end
|
||||||
|
|
||||||
|
insert([[
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
int i;
|
||||||
|
for(i=1; i<=100; i++) {
|
||||||
|
if(((i%3)||(i%5))== 0)
|
||||||
|
printf("number= %d FizzBuzz\n", i);
|
||||||
|
else if((i%3)==0)
|
||||||
|
printf("number= %d Fizz\n", i);
|
||||||
|
else if((i%5)==0)
|
||||||
|
printf("number= %d Buzz\n", i);
|
||||||
|
else
|
||||||
|
printf("number= %d\n",i);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
]])
|
||||||
|
exec_lua([[
|
||||||
|
function get_query_result(query_text)
|
||||||
|
cquery = vim.treesitter.parse_query("c", query_text)
|
||||||
|
parser = vim.treesitter.get_parser(0, "c")
|
||||||
|
tree = parser:parse()[1]
|
||||||
|
res = {}
|
||||||
|
for cid, node in cquery:iter_captures(tree:root(), 0) do
|
||||||
|
-- can't transmit node over RPC. just check the name, range, and text
|
||||||
|
local text = vim.treesitter.get_node_text(node, 0)
|
||||||
|
local range = {node:range()}
|
||||||
|
table.insert(res, {cquery.captures[cid], node:type(), range, text})
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
]])
|
||||||
|
|
||||||
|
local res0 = exec_lua([[return get_query_result(...)]],
|
||||||
|
[[((primitive_type) @c-keyword (#any-of? @c-keyword "int" "float"))]])
|
||||||
|
eq({
|
||||||
|
{ "c-keyword", "primitive_type", { 2, 2, 2, 5 }, "int" },
|
||||||
|
{ "c-keyword", "primitive_type", { 3, 4, 3, 7 }, "int" },
|
||||||
|
}, res0)
|
||||||
|
|
||||||
|
local res1 = exec_lua([[return get_query_result(...)]],
|
||||||
|
[[
|
||||||
|
((string_literal) @fizzbuzz-strings (#any-of? @fizzbuzz-strings
|
||||||
|
"\"number= %d FizzBuzz\\n\""
|
||||||
|
"\"number= %d Fizz\\n\""
|
||||||
|
"\"number= %d Buzz\\n\""
|
||||||
|
))
|
||||||
|
]])
|
||||||
|
eq({
|
||||||
|
{ "fizzbuzz-strings", "string_literal", { 6, 15, 6, 38 }, "\"number= %d FizzBuzz\\n\""},
|
||||||
|
{ "fizzbuzz-strings", "string_literal", { 8, 15, 8, 34 }, "\"number= %d Fizz\\n\""},
|
||||||
|
{ "fizzbuzz-strings", "string_literal", { 10, 15, 10, 34 }, "\"number= %d Buzz\\n\""},
|
||||||
|
}, res1)
|
||||||
|
end)
|
||||||
|
|
||||||
it('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function()
|
it('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function()
|
||||||
if pending_c_parser(pending) then return end
|
if pending_c_parser(pending) then return end
|
||||||
|
|
||||||
@ -343,7 +402,7 @@ void ui_refresh(void)
|
|||||||
return list
|
return list
|
||||||
]]
|
]]
|
||||||
|
|
||||||
eq({ 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list)
|
eq({ 'any-of?', 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user