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:
swaits committed 2026-04-13 21:26:37 -06:00
1 parent d9788571ec
commit 0d13c82997
1 file changed
+28 -14
+28 -14
View File
@@ -116,7 +116,7 @@ function M.start()
end)
local L = M.config.labels
local two = #matches > #L
local line_end = {}
local line_intervals = {}
local li = 1
for _, m in ipairs(matches) do
vim.hl.range(
@@ -129,7 +129,7 @@ function M.start()
)
local label
if two then
if li <= 2 * #L then
if li <= #L * #L then
local a = math.floor((li - 1) / #L) + 1
local b = (li - 1) % #L + 1
label = L:sub(a, a) .. L:sub(b, b)
@@ -142,19 +142,33 @@ function M.start()
label = L:sub(li, li)
end
end
local prev = line_end[m.line]
if label and (not prev or m.start_col >= prev) then
if two then
prefixes[label:sub(1, 1)] = true
if label then
local gap = two and 1 or 0
local ivs = line_intervals[m.line] or {}
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
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