diff options
-rw-r--r-- | runtime/doc/lua.txt | 7 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/query.lua | 42 | ||||
-rw-r--r-- | test/functional/lua/treesitter_spec.lua | 8 |
3 files changed, 37 insertions, 20 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 67a1554aa5..050483fb5e 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -756,14 +756,15 @@ Here is a list of built-in predicates : ((node1) @left (node2) @right (#eq? @left @right)) < `match?` *ts-predicate-match?* - This will match if the provived lua regex matches the text + `vim-match?` *ts-predicate-vim-match?* + This will match if the provived vim regex matches the text corresponding to a node : > ((idenfitier) @constant (#match? @constant "^[A-Z_]+$")) < Note: the `^` and `$` anchors will respectively match the start and end of the node's text. - `vim-match?` *ts-predicate-vim-match?* - This will match the same way than |match?| but using vim + `lua-match?` *ts-predicate-lua-match?* + This will match the same way than |match?| but using lua regexes. `contains?` *ts-predicate-contains?* diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 55e69f177f..ca27a50c6a 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -60,7 +60,7 @@ local predicate_handlers = { return true end, - ["match?"] = function(match, _, bufnr, predicate) + ["lua-match?"] = function(match, _, bufnr, predicate) local node = match[predicate[2]] local regex = predicate[3] local start_row, _, end_row, _ = node:range() @@ -71,7 +71,7 @@ local predicate_handlers = { return string.find(M.get_node_text(node, bufnr), regex) end, - ["vim-match?"] = (function() + ["match?"] = (function() local magic_prefixes = {['\\v']=true, ['\\m']=true, ['\\M']=true, ['\\V']=true} local function check_magic(str) if string.len(str) < 2 or magic_prefixes[string.sub(str,1,2)] then @@ -114,6 +114,9 @@ local predicate_handlers = { end } +-- As we provide lua-match? also expose vim-match? +predicate_handlers["vim-match?"] = predicate_handlers["match?"] + --- Adds a new predicates to be used in queries -- -- @param name the name of the predicate, without leading # @@ -132,25 +135,38 @@ function M.list_predicates() return vim.tbl_keys(predicate_handlers) end +local function xor(x, y) + return (x or y) and not (x and y) +end + function Query:match_preds(match, pattern, bufnr) local preds = self.info.patterns[pattern] - if not preds then - return true - end - for _, pred in pairs(preds) do + + for _, pred in pairs(preds or {}) do -- Here we only want to return if a predicate DOES NOT match, and -- continue on the other case. This way unknown predicates will not be considered, -- which allows some testing and easier user extensibility (#12173). -- Also, tree-sitter strips the leading # from predicates for us. + local pred_name + local is_not if string.sub(pred[1], 1, 4) == "not-" then - local pred_name = string.sub(pred[1], 5) - if predicate_handlers[pred_name] and - predicate_handlers[pred_name](match, pattern, bufnr, pred) then - return false - end + pred_name = string.sub(pred[1], 5) + is_not = true + else + pred_name = pred[1] + is_not = false + end + + local handler = predicate_handlers[pred_name] + + if not handler then + a.nvim_err_writeln(string.format("No handler for %s", pred[1])) + return false + end + + local pred_matches = handler(match, pattern, bufnr, pred) - elseif predicate_handlers[pred[1]] and - not predicate_handlers[pred[1]](match, pattern, bufnr, pred) then + if not xor(is_not, pred_matches) then return false end end diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua index c041478af6..5bca42a4fc 100644 --- a/test/functional/lua/treesitter_spec.lua +++ b/test/functional/lua/treesitter_spec.lua @@ -250,13 +250,13 @@ void ui_refresh(void) }, res) end) - it('allow loading query with escaped quotes and capture them with `match?` and `vim-match?`', function() + it('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function() if not check_parser() then return end insert('char* astring = "Hello World!";') local res = exec_lua([[ - cquery = vim.treesitter.parse_query("c", '((_) @quote (vim-match? @quote "^\\"$")) ((_) @quote (match? @quote "^\\"$"))') + cquery = vim.treesitter.parse_query("c", '((_) @quote (vim-match? @quote "^\\"$")) ((_) @quote (lua-match? @quote "^\\"$"))') parser = vim.treesitter.get_parser(0, "c") tree = parser:parse() res = {} @@ -323,7 +323,7 @@ void ui_refresh(void) return list ]] - eq({ 'contains?', 'eq?', 'is-main?', 'match?', 'vim-match?' }, res_list) + eq({ 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list) end) it('supports highlighting', function() @@ -373,7 +373,7 @@ static int nlua_schedule(lua_State *const lstate) ; Use lua regexes ((identifier) @Identifier (#contains? @Identifier "lua_")) -((identifier) @Constant (#match? @Constant "^[A-Z_]+$")) +((identifier) @Constant (#lua-match? @Constant "^[A-Z_]+$")) ((identifier) @Normal (#vim-match? @Constant "^lstate$")) ((binary_expression left: (identifier) @WarningMsg.left right: (identifier) @WarningMsg.right) (#eq? @WarningMsg.left @WarningMsg.right)) |