fix(treesitter): eliminate flicker for single windows #33842

This commit will eliminate flicker while editing one open window. It
works by querying previously calculated trees for highlight marks, in
the case that we are still asynchronously parsing in `on_win`.

It will not fully solve the case of flicker when there are multiple open
windows, since the parser will drop previously parsed injection trees
whenever it receives a call to parse a different region of the buffer.
This will require a refactor of `languagetree.lua`.

(cherry picked from commit 8d75910ef9)
This commit is contained in:
Riley Bruins
2025-05-05 19:05:16 -07:00
committed by github-actions[bot]
parent 0db89468d7
commit 5c6ee251a6

View File

@ -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