fix: check columns in root bounds

This commit is contained in:
vanaigr 2024-11-30 19:06:36 -06:00
parent 260b4bb3a5
commit d43690d82a
2 changed files with 87 additions and 59 deletions

View File

@ -278,100 +278,128 @@ local function get_spell(capture_name)
return nil, 0
end
local function cmp_eq(rowa, cola, rowb, colb)
return rowa == rowb and cola == colb
end
local function cmp_lt(rowa, cola, rowb, colb)
return rowa < rowb or (rowa == rowb and cola < colb)
end
local function cmp_lte(rowa, cola, rowb, colb)
return rowa < rowb or (rowa == rowb and cola <= colb)
end
---@param self vim.treesitter.highlighter
---@param buf integer
---@param line integer
---@param range_br integer
---@param range_bc integer
---@param range_er integer
---@param range_ec integer
---@param is_spell_nav boolean
local function on_range_impl(self, buf, from_line, from_col, until_line, until_col, is_spell_nav)
local function on_range_impl(self, buf, range_br, range_bc, range_er, range_ec, is_spell_nav)
self:for_each_highlight_state(function(state)
local root_node = state.tstree:root()
local root_start_row, _, root_end_row, _ = root_node:range()
local root_br, root_bc, root_er, root_ec = root_node:range()
-- Only consider trees that contain this line
if root_start_row > until_line or root_end_row < from_line then
local root_intersects = false
local range_empty = cmp_eq(range_br, range_bc, range_er, range_ec)
local root_empty = cmp_eq(root_br, root_bc, root_er, root_ec)
if not range_empty and not root_empty then
root_intersects = cmp_lt(range_br, range_bc, root_er, root_ec)
and cmp_lt(root_br, root_bc, range_er, range_ec)
else
root_intersects = cmp_lte(range_br, range_bc, root_er, root_ec)
and cmp_lte(root_br, root_bc, range_er, range_ec)
end
-- Only consider trees within the visible range
if not root_intersects then
return
end
if
state.iter == nil
or state.next_row < from_line
or (state.next_row == from_line and state.next_col < from_col)
then
local next_row = state.next_row
local next_col = state.next_col
if state.iter == nil or cmp_lt(next_row, next_col, range_br, range_bc) then
-- Mainly used to skip over folds
-- TODO(lewis6991): Creating a new iterator loses the cached predicate results for query
-- matches. Move this logic inside iter_captures() so we can maintain the cache.
state.iter = state.highlighter_query
:query()
:iter_captures2(root_node, self.bufnr, from_line, from_col, root_end_row + 1, 0)
:iter_captures2(root_node, self.bufnr, range_br, range_bc, root_er + 1, 0)
end
while
until_line > state.next_row or (until_line == state.next_row and until_col > state.next_col)
do
local capture, node, metadata, match = state.iter(until_line, until_col)
local range = { root_end_row + 1, 0, root_end_row + 1, 0 }
if node then
range = vim.treesitter.get_range(node, buf, metadata and metadata[capture])
while cmp_lt(next_row, next_col, range_er, range_ec) do
local capture, node, metadata, match = state.iter(range_er, range_ec)
if not node then
next_row = math.huge
next_col = math.huge
break
end
local range = vim.treesitter.get_range(node, buf, metadata and metadata[capture])
local start_row, start_col, end_row, end_col = Range.unpack4(range)
if capture then
local hl = state.highlighter_query:get_hl_from_capture(capture)
local capture_name = state.highlighter_query:query().captures[capture]
local spell, spell_pri_offset = get_spell(capture_name)
-- The "priority" attribute can be set at the pattern level or on a particular capture
local priority = (
tonumber(metadata.priority or metadata[capture] and metadata[capture].priority)
or vim.hl.priorities.treesitter
) + spell_pri_offset
-- The "conceal" attribute can be set at the pattern level or on a particular capture
local conceal = metadata.conceal or metadata[capture] and metadata[capture].conceal
local url = get_url(match, buf, capture, metadata)
if hl and end_row >= from_line and (not is_spell_nav or spell ~= nil) then
api.nvim_buf_set_extmark(buf, ns, start_row, start_col, {
end_line = end_row,
end_col = end_col,
hl_group = hl,
ephemeral = true,
priority = priority,
conceal = conceal,
spell = spell,
url = url,
})
end
end
if start_row > until_line or (start_row == until_line and start_col >= until_col) then
state.next_row = start_row
state.next_col = start_col
if cmp_lt(next_row, next_col, start_row, start_col) then
next_row = start_row
next_col = start_col
end
if not capture then
break
end
local hl = state.highlighter_query:get_hl_from_capture(capture)
local capture_name = state.highlighter_query:query().captures[capture]
local spell, spell_pri_offset = get_spell(capture_name)
-- The "priority" attribute can be set at the pattern level or on a particular capture
local priority = (
tonumber(metadata.priority or metadata[capture] and metadata[capture].priority)
or vim.hl.priorities.treesitter
) + spell_pri_offset
-- The "conceal" attribute can be set at the pattern level or on a particular capture
local conceal = metadata.conceal or metadata[capture] and metadata[capture].conceal
local url = get_url(match, buf, capture, metadata)
if not is_spell_nav or spell ~= nil then
api.nvim_buf_set_extmark(buf, ns, start_row, start_col, {
end_line = end_row,
end_col = end_col,
ephemeral = true,
priority = priority,
hl_group = hl,
conceal = conceal,
spell = spell,
url = url,
})
end
end
state.next_row = next_row
state.next_col = next_col
end)
end
---@private
---@param _win integer
---@param buf integer
---@param line integer
function TSHighlighter._on_range(_, _win, buf, sr, sc, er, ec, _)
---@param br integer
---@param bc integer
---@param er integer
---@param ec integer
function TSHighlighter._on_range(_, _win, buf, br, bc, er, ec, _)
local self = TSHighlighter.active[buf]
if not self then
return
end
on_range_impl(self, buf, sr, sc, er, ec, false)
on_range_impl(self, buf, br, bc, er, ec, false)
end
---@private

View File

@ -2588,8 +2588,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
bool added_decor = false;
decor_providers_invoke_range(wp, lnum - 1, decor_provider_end_col,
lnum, 0, &added_decor);
decor_provider_end_col = INT_MAX;
has_decor |= added_decor;
// decor_provider_end_col = INT_MAX;
// has_decor |= added_decor;
}
if (has_decor) {
extra_check = true;