aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/tshighlighter.lua
diff options
context:
space:
mode:
authorThomas Vigouroux <tomvig38@gmail.com>2020-07-03 19:16:40 +0200
committerThomas Vigouroux <tomvig38@gmail.com>2020-07-10 17:16:23 +0200
commitc5119dbad633752568ea53596d2f483ee63c1ce8 (patch)
tree9084058230ab8568079f9d710c15692251c31bae /runtime/lua/vim/tshighlighter.lua
parent529251d5e49ed869aa9b4b3a168e97c8e30211d6 (diff)
downloadrneovim-c5119dbad633752568ea53596d2f483ee63c1ce8.tar.gz
rneovim-c5119dbad633752568ea53596d2f483ee63c1ce8.tar.bz2
rneovim-c5119dbad633752568ea53596d2f483ee63c1ce8.zip
treesitter: use change calbacks on redraw
Diffstat (limited to 'runtime/lua/vim/tshighlighter.lua')
-rw-r--r--runtime/lua/vim/tshighlighter.lua87
1 files changed, 30 insertions, 57 deletions
diff --git a/runtime/lua/vim/tshighlighter.lua b/runtime/lua/vim/tshighlighter.lua
index 1440acf0d0..c1e77ea792 100644
--- a/runtime/lua/vim/tshighlighter.lua
+++ b/runtime/lua/vim/tshighlighter.lua
@@ -3,6 +3,7 @@ local a = vim.api
-- support reload for quick experimentation
local TSHighlighter = rawget(vim.treesitter, 'TSHighlighter') or {}
TSHighlighter.__index = TSHighlighter
+local ts_hs_ns = a.nvim_create_namespace("treesitter_hl")
-- These are conventions defined by tree-sitter, though it
-- needs to be user extensible also.
@@ -26,7 +27,7 @@ function TSHighlighter.new(query, bufnr, ft)
local self = setmetatable({}, TSHighlighter)
self.parser = vim.treesitter.get_parser(bufnr, ft, function(...) self:on_change(...) end)
self.buf = self.parser.bufnr
- -- TODO(bfredl): perhaps on_start should be called uncondionally, instead for only on mod?
+
local tree = self.parser:parse()
self.root = tree:root()
self:set_query(query)
@@ -34,10 +35,8 @@ function TSHighlighter.new(query, bufnr, ft)
self.redraw_count = 0
self.line_count = {}
a.nvim_buf_set_option(self.buf, "syntax", "")
- a.nvim__buf_set_luahl(self.buf, {
- on_start=function(...) return self:on_start(...) end,
- on_window=function(...) return self:on_window(...) end,
- on_line=function(...) return self:on_line(...) end,
+ a.nvim_buf_attach(self.buf, false, {
+ on_lines=function(_) self.root = self.parser:parse():root() end
})
-- Tricky: if syntax hasn't been enabled, we need to reload color scheme
@@ -47,6 +46,7 @@ function TSHighlighter.new(query, bufnr, ft)
if vim.g.syntax_on ~= 1 then
vim.api.nvim_command("runtime! syntax/synload.vim")
end
+
return self
end
@@ -56,67 +56,40 @@ function TSHighlighter:set_query(query)
end
self.query = query
- self.id_map = {}
- for i, capture in ipairs(self.query.captures) do
- local hl = 0
- local firstc = string.sub(capture, 1, 1)
- local hl_group = self.hl_map[capture]
- if firstc ~= string.lower(firstc) then
- hl_group = vim.split(capture, '.', true)[1]
- end
- if hl_group then
- hl = a.nvim_get_hl_id_by_name(hl_group)
- end
- self.id_map[i] = hl
- end
-
- a.nvim__buf_redraw_range(self.buf, 0, a.nvim_buf_line_count(self.buf))
+ self:on_change({{self.root:range()}})
end
function TSHighlighter:on_change(changes)
+ -- Get a fresh root
+ self.root = self.parser.tree:root()
+
for _, ch in ipairs(changes or {}) do
- a.nvim__buf_redraw_range(self.buf, ch[1], ch[3]+1)
- end
- self.edit_count = self.edit_count + 1
-end
+ -- Try to be as exact as possible
+ local changed_node = self.root:descendant_for_range(ch[1], ch[2], ch[3], ch[4])
-function TSHighlighter:on_start(_, _buf, _tick)
- local tree = self.parser:parse()
- self.root = tree:root()
-end
+ a.nvim_buf_clear_namespace(self.buf, ts_hs_ns, ch[1], ch[3])
-function TSHighlighter:on_window(_, _win, _buf, _topline, botline)
- self.iter = nil
- self.nextrow = 0
- self.botline = botline
- self.redraw_count = self.redraw_count + 1
-end
+ for capture, node in self.query:iter_captures(changed_node, self.buf, ch[1], ch[3] + 1) do
+ local start_row, start_col, end_row, end_col = node:range()
+ local capture_name = self.query.captures[capture]
-function TSHighlighter:on_line(_, _win, buf, line)
- if self.iter == nil then
- self.iter = self.query:iter_captures(self.root,buf,line,self.botline)
- end
- while line >= self.nextrow do
- local capture, node, match = self.iter()
- local active = true
- if capture == nil then
- break
- end
- if match ~= nil then
- active = self:run_pred(match)
- match.active = active
- end
- local start_row, start_col, end_row, end_col = node:range()
- local hl = self.id_map[capture]
- if hl > 0 and active and end_row >= line then
- a.nvim__put_attr(hl, start_row, start_col, end_row, end_col)
- end
- if start_row > line then
- self.nextrow = start_row
+ local firstc = string.sub(capture_name, 1, 1)
+ local hl
+ -- TODO(vigoux): maybe we want to cache the capture -> highlight relation
+ if firstc ~= string.lower(firstc) then
+ hl = vim.split(capture_name, '.', true)[1]
+ else
+ hl = TSHighlighter.hl_map[capture_name]
+ end
+
+ if hl then
+ a.nvim__buf_add_decoration(self.buf, ts_hs_ns, hl,
+ start_row, start_col,
+ end_row, end_col,
+ {})
+ end
end
end
- self.line_count[line] = (self.line_count[line] or 0) + 1
- --return tostring(self.line_count[line])
end
return TSHighlighter