fix: proper multi-label-per-line overlap check + raise cap to |L|^2
Two changes folded into one commit since they were developed together: 1. Raise two-char label cap from 2*|L| to |L|^2. The cap was a conservative guess against visual density; the gap+overlap-skip logic makes density self-limiting regardless of pool size. Cost: all 26 letters land in prefixes[] in two-char mode, so single- char pattern extension doesn't work there. Acceptable since you're in two-char mode precisely because you want to jump, not extend further. 2. Fix: overlap check now compares a candidate label against ALL labels already placed on the same line, not just the most recent one. Previously line_end[line] tracked a single right edge, which assumed left-to-right commit order. With cursor-proximity sort, a right-of-cursor label can commit first and poison the tracker, wrongly rejecting a left-of-it match whose label wouldn't actually overlap. Now line_intervals[line] holds a list of [start, end) intervals and the candidate is tested against the whole list with a gap-aware interval-overlap check.
This commit is contained in:
1 file changed
+28
-14
+28
-14
@@ -116,7 +116,7 @@ function M.start()
|
|||||||
end)
|
end)
|
||||||
local L = M.config.labels
|
local L = M.config.labels
|
||||||
local two = #matches > #L
|
local two = #matches > #L
|
||||||
local line_end = {}
|
local line_intervals = {}
|
||||||
local li = 1
|
local li = 1
|
||||||
for _, m in ipairs(matches) do
|
for _, m in ipairs(matches) do
|
||||||
vim.hl.range(
|
vim.hl.range(
|
||||||
@@ -129,7 +129,7 @@ function M.start()
|
|||||||
)
|
)
|
||||||
local label
|
local label
|
||||||
if two then
|
if two then
|
||||||
if li <= 2 * #L then
|
if li <= #L * #L then
|
||||||
local a = math.floor((li - 1) / #L) + 1
|
local a = math.floor((li - 1) / #L) + 1
|
||||||
local b = (li - 1) % #L + 1
|
local b = (li - 1) % #L + 1
|
||||||
label = L:sub(a, a) .. L:sub(b, b)
|
label = L:sub(a, a) .. L:sub(b, b)
|
||||||
@@ -142,19 +142,33 @@ function M.start()
|
|||||||
label = L:sub(li, li)
|
label = L:sub(li, li)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local prev = line_end[m.line]
|
if label then
|
||||||
if label and (not prev or m.start_col >= prev) then
|
local gap = two and 1 or 0
|
||||||
if two then
|
local ivs = line_intervals[m.line] or {}
|
||||||
prefixes[label:sub(1, 1)] = true
|
local fits = true
|
||||||
|
for _, iv in ipairs(ivs) do
|
||||||
|
if
|
||||||
|
m.start_col < iv[2] + gap
|
||||||
|
and iv[1] < m.start_col + #label + gap
|
||||||
|
then
|
||||||
|
fits = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if fits then
|
||||||
|
if two then
|
||||||
|
prefixes[label:sub(1, 1)] = true
|
||||||
|
end
|
||||||
|
active[label] = { m.line + 1, m.start_col }
|
||||||
|
api.nvim_buf_set_extmark(buf, NS, m.line, m.start_col, {
|
||||||
|
virt_text = { { label, M.config.label } },
|
||||||
|
virt_text_pos = 'overlay',
|
||||||
|
priority = 201,
|
||||||
|
})
|
||||||
|
ivs[#ivs + 1] = { m.start_col, m.start_col + #label }
|
||||||
|
line_intervals[m.line] = ivs
|
||||||
|
li = li + 1
|
||||||
end
|
end
|
||||||
active[label] = { m.line + 1, m.start_col }
|
|
||||||
api.nvim_buf_set_extmark(buf, NS, m.line, m.start_col, {
|
|
||||||
virt_text = { { label, M.config.label } },
|
|
||||||
virt_text_pos = 'overlay',
|
|
||||||
priority = 201,
|
|
||||||
})
|
|
||||||
line_end[m.line] = m.start_col + #label + (two and 1 or 0)
|
|
||||||
li = li + 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in new issue
Block a user