Skip to content

Commit 3a2f509

Browse files
committed
wip: use invalidate signs
wip range signs
1 parent fa052c2 commit 3a2f509

File tree

4 files changed

+91
-9
lines changed

4 files changed

+91
-9
lines changed

lua/gitsigns/hunks.lua

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,84 @@ function M.calc_signs(hunk, next, min_lnum, max_lnum, untracked)
225225
return signs
226226
end
227227

228+
--- Calculate signs needed to be applied from a hunk for a specified line range.
229+
--- @param hunk Gitsigns.Hunk.Hunk
230+
--- @param next_hunk Gitsigns.Hunk.Hunk?
231+
--- @param untracked boolean
232+
--- @return Gitsigns.Sign[]
233+
function M.calc_sign_ranges(hunk, next_hunk, untracked)
234+
assert(
235+
not untracked or hunk.type == 'add',
236+
string.format('Invalid hunk with untracked=%s hunk="%s"', untracked, hunk.head)
237+
)
238+
239+
local start = hunk.added.start
240+
local added = hunk.added.count
241+
local removed = hunk.removed.count
242+
local end_lnum = change_end(hunk)
243+
244+
if hunk.type == 'delete' and start == 0 then
245+
-- topdelete signs get placed one row lower
246+
return { {
247+
type = 'topdelete',
248+
count = removed,
249+
lnum = 1
250+
} }
251+
elseif hunk.type == 'delete' then
252+
return { {
253+
type = 'delete',
254+
count = removed,
255+
lnum = start,
256+
end_lnum = start
257+
} }
258+
elseif untracked or hunk.type == 'add' then
259+
return { {
260+
type = untracked and 'untracked' or 'add',
261+
count = added,
262+
lnum = start,
263+
end_lnum = end_lnum
264+
} }
265+
end
266+
267+
--- @type Gitsigns.Sign[]
268+
local signs = {}
269+
270+
-- changedelete
271+
if removed > added then
272+
if end_lnum > start then
273+
signs[#signs + 1] = {
274+
type = 'change',
275+
lnum = start,
276+
end_lnum = end_lnum - 1
277+
}
278+
end
279+
280+
signs[#signs + 1] = {
281+
type = 'changedelete',
282+
count = removed,
283+
lnum = end_lnum
284+
}
285+
else -- change
286+
signs[#signs + 1] = {
287+
type = 'change',
288+
lnum = start,
289+
end_lnum = end_lnum
290+
}
291+
292+
-- Added lines of a 'change' hunk
293+
if added > removed then
294+
signs[#signs + 1] = {
295+
type = 'add',
296+
count = added - removed,
297+
lnum = end_lnum,
298+
end_lnum = hunk.vend,
299+
}
300+
end
301+
end
302+
303+
return signs
304+
end
305+
228306
--- @param relpath string
229307
--- @param hunks Gitsigns.Hunk.Hunk[]
230308
--- @param mode_bits string

lua/gitsigns/manager.lua

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,16 @@ local function apply_win_signs0(bufnr, signs, hunks, top, bot, clear, untracked)
4242

4343
for i, hunk in ipairs(hunks or {}) do
4444
--- @type Gitsigns.Hunk.Hunk?
45-
local next = hunks[i + 1]
45+
local next_hunk = hunks[i + 1]
4646

4747
-- To stop the sign column width changing too much, if there are signs to be
4848
-- added but none of them are visible in the window, then make sure to add at
4949
-- least one sign. Only do this on the first call after an update when we all
5050
-- the signs have been cleared.
51-
if clear and i == 1 then
52-
signs:add(
53-
bufnr,
54-
gs_hunks.calc_signs(hunk, next, hunk.added.start, hunk.added.start, untracked)
55-
)
51+
if (clear and i == 1) or (top <= hunk.vend and bot >= hunk.added.start) then
52+
signs:add(bufnr, gs_hunks.calc_sign_ranges(hunk, next_hunk, untracked))
5653
end
5754

58-
if top <= hunk.vend and bot >= hunk.added.start then
59-
signs:add(bufnr, gs_hunks.calc_signs(hunk, next, top, bot, untracked))
60-
end
6155
if hunk.added.start > bot then
6256
break
6357
end

lua/gitsigns/signs.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ local dprint = require('gitsigns.debug.log').dprint
66
--- @field type Gitsigns.SignType
77
--- @field count? integer
88
--- @field lnum integer
9+
--- @field end_lnum? integer
910

1011
--- @class Gitsigns.Signs
1112
--- @field hls table<Gitsigns.SignType,Gitsigns.SignConfig>

lua/gitsigns/signs/extmarks.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ local M = {}
77

88
local group_base = 'gitsigns_extmark_signs_'
99

10+
local use_invalidate_signs = vim.fn.has('nvim-0.10') > 0
11+
1012
--- @param cfg Gitsigns.SignConfig
1113
--- @param hls table<Gitsigns.SignType,Gitsigns.SignConfig>
1214
--- @param name string
@@ -24,6 +26,9 @@ end
2426
--- @param last_orig? integer
2527
--- @param last_new? integer
2628
function M:on_lines(buf, _, last_orig, last_new)
29+
if use_invalidate_signs then
30+
return
31+
end
2732
-- Remove extmarks on line deletions to mimic
2833
-- the behaviour of vim signs.
2934
if last_orig > last_new then
@@ -65,11 +70,15 @@ function M:add(bufnr, signs)
6570

6671
local ok, err = pcall(api.nvim_buf_set_extmark, bufnr, self.ns, s.lnum - 1, -1, {
6772
id = s.lnum,
73+
end_row = s.end_lnum and s.end_lnum - 1 or nil,
6874
sign_text = config.signcolumn and text or '',
6975
priority = config.sign_priority,
7076
sign_hl_group = hls.hl,
7177
number_hl_group = config.numhl and hls.numhl or nil,
7278
line_hl_group = config.linehl and hls.linehl or nil,
79+
80+
undo_restore = not use_invalidate_signs,
81+
invalidate = use_invalidate_signs,
7382
})
7483

7584
if not ok and config.debug_mode then

0 commit comments

Comments
 (0)