diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 5e57124d63..fa8eea9467 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -131,6 +131,7 @@ function TSHighlighter.new(tree, opts) self.redraw_count = 0 self._conceal_checked = {} self._queries = {} + self._highlight_states = {} -- Queries for a specific language can be overridden by a custom -- string query... if one is not provided it will be looked up by file. @@ -460,19 +461,37 @@ end ---@param buf integer ---@param topline integer ---@param botline integer -function TSHighlighter._on_win(_, _, buf, topline, botline) +function TSHighlighter._on_win(_, win, buf, topline, botline) local self = TSHighlighter.active[buf] - if not self or self.parsing then + if not self then return false end - self.parsing = self.tree:parse({ topline, botline + 1 }, function(_, trees) - if trees and self.parsing then - self.parsing = false - api.nvim__redraw({ buf = buf, valid = false, flush = false }) - end - end) == nil - self.redraw_count = self.redraw_count + 1 - self:prepare_highlight_states(topline, botline) + self.parsing = self.parsing + or nil + == self.tree:parse({ topline, botline + 1 }, function(_, trees) + if trees and self.parsing then + self.parsing = false + api.nvim__redraw({ win = win, valid = false, flush = false }) + end + end) + if not self.parsing then + self.redraw_count = self.redraw_count + 1 + self:prepare_highlight_states(topline, botline) + else + self:for_each_highlight_state(function(state) + -- TODO(ribru17): Inefficient. Eventually all marks should be applied in on_buf, and all + -- non-folded ranges of each open window should be merged, and iterators should only be + -- created over those regions. This would also fix #31777. + -- + -- Currently this is not possible because the parser discards previously parsed injection + -- trees upon parsing a different region. + -- + -- It would also be nice if rather than re-querying extmarks for old trees, we could tell the + -- decoration provider to not clear previous ephemeral marks for this redraw cycle. + state.iter = nil + state.next_row = 0 + end) + end return #self._highlight_states > 0 end