diff --git a/lua/gitsigns/hunks.lua b/lua/gitsigns/hunks.lua index 6f4d57614..e9656f75e 100644 --- a/lua/gitsigns/hunks.lua +++ b/lua/gitsigns/hunks.lua @@ -164,11 +164,12 @@ end --- Calculate signs needed to be applied from a hunk for a specified line range. --- @param hunk Gitsigns.Hunk.Hunk +--- @param next Gitsigns.Hunk.Hunk? --- @param min_lnum integer --- @param max_lnum integer --- @param untracked boolean --- @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( not untracked or hunk.type == 'add', 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) - for lnum = max(start, min_lnum), min(cend, max_lnum) do - local changedelete = hunk.type == 'change' and removed > added and lnum == cend + -- if this is a change hunk, mark changedelete if lines were removed or if the + -- 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] = { - 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, lnum = lnum, } diff --git a/lua/gitsigns/manager.lua b/lua/gitsigns/manager.lua index b5531b978..ed8f277f9 100644 --- a/lua/gitsigns/manager.lua +++ b/lua/gitsigns/manager.lua @@ -41,16 +41,22 @@ local function apply_win_signs0(bufnr, signs, hunks, top, bot, clear, untracked) end 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 -- 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 -- the signs have been cleared. 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 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 if hunk.added.start > bot then break