aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/treesitter
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim/treesitter')
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua28
-rw-r--r--runtime/lua/vim/treesitter/query.lua51
2 files changed, 48 insertions, 31 deletions
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 681d2c6324..718088e0ad 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -60,14 +60,11 @@ function TSHighlighter.new(query, bufnr, ft)
ft,
{
on_changedtree = function(...) self:on_changedtree(...) end,
- on_lines = function() self.root = self.parser:parse():root() end
+ on_bytes = function() self.parser:parse() end
}
)
self.buf = self.parser.bufnr
-
- local tree = self.parser:parse()
- self.root = tree:root()
self:set_query(query)
self.edit_count = 0
self.redraw_count = 0
@@ -98,7 +95,8 @@ function TSHighlighter:get_hl_from_capture(capture)
return vim.split(name, '.', true)[1]
else
-- Default to false to avoid recomputing
- return TSHighlighter.hl_map[name]
+ local hl = TSHighlighter.hl_map[name]
+ return hl and a.nvim_get_hl_id_by_name(hl) or 0
end
end
@@ -125,27 +123,25 @@ function TSHighlighter:set_query(query)
end
})
- self:on_changedtree({{self.root:range()}})
+ self:on_changedtree({{self.parser:parse():root():range()}})
end
function TSHighlighter:on_changedtree(changes)
-- Get a fresh root
- self.root = self.parser.tree:root()
+ local root = self.parser:parse():root()
for _, ch in ipairs(changes or {}) do
- -- Try to be as exact as possible
- local changed_node = self.root:descendant_for_range(ch[1], ch[2], ch[3], ch[4])
-
- a.nvim_buf_clear_namespace(self.buf, ts_hs_ns, ch[1], ch[3])
+ a.nvim_buf_clear_namespace(self.buf, ts_hs_ns, ch[1], ch[3]+1)
- for capture, node in self.query:iter_captures(changed_node, self.buf, ch[1], ch[3] + 1) do
+ for capture, node in self.query:iter_captures(root, self.buf, ch[1], ch[3] + 1) do
local start_row, start_col, end_row, end_col = node:range()
local hl = self.hl_cache[capture]
if hl then
- a.nvim__buf_add_decoration(self.buf, ts_hs_ns, hl,
- start_row, start_col,
- end_row, end_col,
- {})
+ a.nvim_buf_set_extmark(self.buf, ts_hs_ns, start_row, start_col, {
+ end_col = end_col,
+ end_line = end_row,
+ hl_group = hl
+ })
end
end
end
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 17f61b24f1..ca27a50c6a 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -17,7 +17,7 @@ local M = {}
function M.parse_query(lang, query)
language.require_language(lang)
local self = setmetatable({}, Query)
- self.query = vim._ts_parse_query(lang, vim.fn.escape(query,'\\'))
+ self.query = vim._ts_parse_query(lang, query)
self.info = self.query:inspect()
self.captures = self.info.captures
return self
@@ -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
@@ -82,7 +82,7 @@ local predicate_handlers = {
local compiled_vim_regexes = setmetatable({}, {
__index = function(t, pattern)
- local res = vim.regex(check_magic(pattern))
+ local res = vim.regex(check_magic(vim.fn.escape(pattern, '\\')))
rawset(t, pattern, res)
return res
end
@@ -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 #
@@ -127,25 +130,43 @@ function M.add_predicate(name, handler, force)
predicate_handlers[name] = handler
end
+--- Returns the list of currently supported predicates
+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