fix: changedelete symbol with linematch enabled

Since linematch will report a changed line following deleted lines as
multiple hunks on a single line, it will only show the `changed` sign
and will drop the `deleted` sign.  To fix this check for overlapping
hunks and mark the change hunk as changedelete.
This commit is contained in:
Timur Celik 2024-03-11 10:34:57 +01:00 committed by Lewis Russell
parent 2c2463dbd8
commit 41dc075ef6
2 changed files with 23 additions and 6 deletions

View File

@ -164,11 +164,12 @@ end
--- Calculate signs needed to be applied from a hunk for a specified line range. --- Calculate signs needed to be applied from a hunk for a specified line range.
--- @param hunk Gitsigns.Hunk.Hunk --- @param hunk Gitsigns.Hunk.Hunk
--- @param next Gitsigns.Hunk.Hunk?
--- @param min_lnum integer --- @param min_lnum integer
--- @param max_lnum integer --- @param max_lnum integer
--- @param untracked boolean --- @param untracked boolean
--- @return Gitsigns.Sign[] --- @return Gitsigns.Sign[]
function M.calc_signs(hunk, min_lnum, max_lnum, untracked) function M.calc_signs(hunk, next, min_lnum, max_lnum, untracked)
assert( assert(
not untracked or hunk.type == 'add', not untracked or hunk.type == 'add',
string.format('Invalid hunk with untracked=%s hunk="%s"', untracked, hunk.head) string.format('Invalid hunk with untracked=%s hunk="%s"', untracked, hunk.head)
@ -191,11 +192,21 @@ function M.calc_signs(hunk, min_lnum, max_lnum, untracked)
local cend = change_end(hunk) local cend = change_end(hunk)
for lnum = max(start, min_lnum), min(cend, max_lnum) do -- if this is a change hunk, mark changedelete if lines were removed or if the
local changedelete = hunk.type == 'change' and removed > added and lnum == cend -- next hunk removes on this hunks last line
local changedelete = false
if hunk.type == 'change' then
changedelete = removed > added
if next ~= nil and next.type == 'delete' then
changedelete = changedelete or hunk.added.start + hunk.added.count - 1 == next.added.start
end
end
for lnum = max(start, min_lnum), min(cend, max_lnum) do
signs[#signs + 1] = { signs[#signs + 1] = {
type = changedelete and 'changedelete' or untracked and 'untracked' or hunk.type, type = (changedelete and lnum == cend) and 'changedelete'
or untracked and 'untracked'
or hunk.type,
count = lnum == start and (hunk.type == 'add' and added or removed) or nil, count = lnum == start and (hunk.type == 'add' and added or removed) or nil,
lnum = lnum, lnum = lnum,
} }

View File

@ -41,16 +41,22 @@ local function apply_win_signs0(bufnr, signs, hunks, top, bot, clear, untracked)
end end
for i, hunk in ipairs(hunks or {}) do for i, hunk in ipairs(hunks or {}) do
--- @type Gitsigns.Hunk.Hunk?
local next = hunks[i + 1]
-- To stop the sign column width changing too much, if there are signs to be -- To stop the sign column width changing too much, if there are signs to be
-- added but none of them are visible in the window, then make sure to add at -- added but none of them are visible in the window, then make sure to add at
-- least one sign. Only do this on the first call after an update when we all -- least one sign. Only do this on the first call after an update when we all
-- the signs have been cleared. -- the signs have been cleared.
if clear and i == 1 then if clear and i == 1 then
signs:add(bufnr, gs_hunks.calc_signs(hunk, hunk.added.start, hunk.added.start, untracked)) signs:add(
bufnr,
gs_hunks.calc_signs(hunk, next, hunk.added.start, hunk.added.start, untracked)
)
end end
if top <= hunk.vend and bot >= hunk.added.start then if top <= hunk.vend and bot >= hunk.added.start then
signs:add(bufnr, gs_hunks.calc_signs(hunk, top, bot, untracked)) signs:add(bufnr, gs_hunks.calc_signs(hunk, next, top, bot, untracked))
end end
if hunk.added.start > bot then if hunk.added.start > bot then
break break