jujutsu file annotations for neovim (like blame)
4

Configure Feed

Select the types of activity you want to include in your feed.

use ranges instead of line span

Signed-off-by: Ron Shavit <me@ronshavit.com>

Ron Shavit (May 27, 2026, 12:46 AM +0300) 643abab3 76c51c77

+20 -21
+20 -21
lua/jjannotate.lua
··· 15 15 ---@field lines jjannotate.Line[] 16 16 ---@field longest_timestamp integer 17 17 18 + ---@class jjannotate.Range 19 + ---@field start integer 0-indexed inclusive 20 + ---@field _end integer 0-indexed inclusive 21 + 18 22 ---@class jjannotate.Line 19 - ---@field span integer how many lines this line spans 23 + ---@field range jjannotate.Range 20 24 ---@field change_id string 21 25 ---@field author string 22 26 ---@field timestamp string ··· 80 84 local longest_timestamp = 0 81 85 local last_change_id ---@type string | nil 82 86 83 - for _, line in ipairs(vim.split(raw, "\n")) do 87 + for i, line in ipairs(vim.split(raw, "\n")) do 84 88 if #line > 0 then 89 + local row = i - 1 85 90 local components = vim.split(line, "|") 86 91 local parsed = { 87 - span = 1, 92 + range = { start = row, _end = row }, 88 93 change_id = components[1], 89 94 author = components[2], 90 95 timestamp = components[3], 91 96 } 92 97 93 98 if parsed.change_id == last_change_id then 94 - lines[#lines].span = lines[#lines].span + 1 99 + lines[#lines].range._end = row 95 100 else 96 101 table.insert(lines, parsed) 97 102 longest_timestamp = math.max(longest_timestamp, #parsed.timestamp) ··· 121 126 local rendered = render_line(line, parsed.longest_timestamp) 122 127 table.insert(lines, rendered) 123 128 longest_line = math.max(longest_line, vim.fn.strdisplaywidth(rendered)) 124 - if line.span > 1 then 125 - for _ = 1, line.span - 1 do 129 + if line.range._end > line.range.start then 130 + for _ = 1, line.range._end - line.range.start do 126 131 table.insert(lines, string.rep(" ", longest_line)) 127 132 end 128 133 end ··· 142 147 143 148 local hl_cache = {} 144 149 145 - local row = 0 146 150 for _, line in ipairs(parsed.lines) do 147 151 local change_id = line.change_id 148 152 149 - if change_id ~= "" then 150 - if not hl_cache[change_id] then 151 - local hl_name = "JJAnnotate" .. change_id 152 - vim.api.nvim_set_hl(0, hl_name, { fg = color.stable_from_string(change_id) }) 153 - hl_cache[change_id] = hl_name 154 - end 153 + if not hl_cache[change_id] then 154 + local hl_name = "JJAnnotate" .. change_id 155 + vim.api.nvim_set_hl(0, hl_name, { fg = color.stable_from_string(change_id) }) 156 + hl_cache[change_id] = hl_name 157 + end 155 158 156 - local hl = hl_cache[change_id] 159 + local hl = hl_cache[change_id] 157 160 158 - for _ = 1, line.span do 159 - vim.api.nvim_buf_set_extmark(buf, ns, row, 0, { end_col = #change_id, hl_group = "Comment", strict = false }) 160 - vim.api.nvim_buf_set_extmark(buf, ns, row, #change_id, { end_col = -1, hl_group = hl, strict = false }) 161 - row = row + 1 162 - end 163 - else 164 - row = row + line.span 161 + for row = line.range.start, line.range._end do 162 + vim.api.nvim_buf_set_extmark(buf, ns, row, 0, { end_col = #change_id, hl_group = "Comment", strict = false }) 163 + vim.api.nvim_buf_set_extmark(buf, ns, row, #change_id, { end_col = -1, hl_group = hl, strict = false }) 165 164 end 166 165 end 167 166 end