From 0d13c8299729aabd372f0d11997f43e885ac4181 Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Mon, 13 Apr 2026 20:43:33 -0600 Subject: [PATCH] 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. --- lua/tiny-jump/init.lua | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/lua/tiny-jump/init.lua b/lua/tiny-jump/init.lua index 90cbf03..8967cb6 100644 --- a/lua/tiny-jump/init.lua +++ b/lua/tiny-jump/init.lua @@ -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