feat(): show old version of hunks via virtual lines

Use virtual lines to show the old version of hunks inline in the buffer.

- Added config.show_deleted
- Added toggle_deleted()
This commit is contained in:
Lewis Russell 2022-01-14 16:44:32 +00:00 committed by Lewis Russell
parent 254e09dc59
commit 584e1abfb9
7 changed files with 172 additions and 0 deletions

View File

@ -388,6 +388,9 @@ stage_hunk({range}) *gitsigns.stage_hunk()*
{range} table|nil List-like table of two integers making
up the line range from which you want to stage the hunks.
toggle_deleted() *gitsigns.toggle_deleted()*
Toggle |gitsigns-config-show_deleted|
toggle_current_line_blame() *gitsigns.toggle_current_line_blame()*
Toggle |gitsigns-config-current_line_blame|
@ -558,6 +561,13 @@ linehl *gitsigns-config-linehl*
the highlight group does not exist, then it is automatically defined
and linked to the corresponding highlight group in `signs.*.hl`.
show_deleted *gitsigns-config-show_deleted*
Type: `boolean`, Default: `false`
Show the old version of hunks inline in the buffer (via virtual lines).
Note: Virtual lines currently use the highlight `GitSignsDeleteLn`.
diff_opts *gitsigns-config-diff_opts*
Type: `table[extended]`, Default: derived from 'diffopt'

View File

@ -69,6 +69,7 @@ local M = {QFListOpts = {}, }
M.toggle_signs = function()
@ -100,6 +101,12 @@ M.toggle_current_line_blame = function()
M.refresh()
end
M.toggle_deleted = function()
config.show_deleted = not config.show_deleted
M.refresh()
end
local function get_cursor_hunk(bufnr, hunks)
bufnr = bufnr or current_buf()
hunks = hunks or cache[bufnr].hunks

View File

@ -103,6 +103,7 @@ local M = {Config = {DiffOpts = {}, SignsConfig = {}, watch_gitdir = {}, current
M.config = {}
@ -272,6 +273,16 @@ M.schema = {
]],
},
show_deleted = {
type = 'boolean',
default = false,
description = [[
Show the old version of hunks inline in the buffer (via virtual lines).
Note: Virtual lines currently use the highlight `GitSignsDeleteLn`.
]],
},
diff_opts = {
type = 'table',
deep_extend = true,

View File

@ -212,6 +212,67 @@ M.apply_word_diff = function(bufnr, row)
end
end
local ns_rm = api.nvim_create_namespace('gitsigns_removed')
local VIRT_LINE_LEN = 300
local function clear_deleted(bufnr)
local marks = api.nvim_buf_get_extmarks(bufnr, ns_rm, 0, -1, {})
for _, mark in ipairs(marks) do
api.nvim_buf_del_extmark(bufnr, ns_rm, mark[1])
end
end
local function show_deleted(bufnr)
local bcache = cache[bufnr]
clear_deleted(bufnr)
if not config.show_deleted then
return
end
for _, hunk in ipairs(bcache.hunks) do
local virt_lines = {}
local do_word_diff = config.word_diff and #hunk.removed.lines == #hunk.added.lines
for i, line in ipairs(hunk.removed.lines) do
local vline = {}
local last_ecol = 1
if do_word_diff then
local regions = require('gitsigns.diff_int').run_word_diff(
{ hunk.removed.lines[i] }, { hunk.added.lines[i] })
for _, region in ipairs(regions) do
local rline, scol, ecol = region[1], region[3], region[4]
if rline > 1 then
break
end
vline[#vline + 1] = { line:sub(last_ecol, scol - 1), config.signs.delete.linehl }
vline[#vline + 1] = { line:sub(scol, ecol - 1), 'TermCursor' }
last_ecol = ecol
end
end
if #line > 0 then
vline[#vline + 1] = { line:sub(last_ecol, -1), config.signs.delete.linehl }
end
local padding = string.rep(' ', VIRT_LINE_LEN - #line)
vline[#vline + 1] = { padding, config.signs.delete.linehl }
virt_lines[i] = vline
end
api.nvim_buf_set_extmark(bufnr, ns_rm, hunk.start - 1, -1, {
virt_lines = virt_lines,
virt_lines_above = hunk.type ~= 'delete',
})
end
end
local update_cnt = 0
local update0 = function(bufnr, bcache)
@ -251,6 +312,8 @@ local update0 = function(bufnr, bcache)
M.apply_win_signs(bufnr, bcache.pending_signs)
show_deleted(bufnr)
end
local summary = gs_hunks.get_summary(bcache.hunks)
summary.head = git_obj.repo.abbrev_head

View File

@ -68,6 +68,7 @@ local record M
toggle_linehl : function()
toggle_word_diff : function()
toggle_current_line_blame : function()
toggle_deleted : function()
end
--- Toggle |gitsigns-config-signcolumn|
@ -100,6 +101,12 @@ M.toggle_current_line_blame = function()
M.refresh()
end
--- Toggle |gitsigns-config-show_deleted|
M.toggle_deleted = function()
config.show_deleted = not config.show_deleted
M.refresh()
end
local function get_cursor_hunk(bufnr: integer, hunks: {Hunk}): Hunk, integer
bufnr = bufnr or current_buf()
hunks = hunks or cache[bufnr].hunks

View File

@ -50,6 +50,7 @@ local record M
signcolumn: boolean
numhl: boolean
linehl: boolean
show_deleted: boolean
sign_priority: integer
keymaps: {string:any}
on_attach: function(bufnr: integer)
@ -272,6 +273,16 @@ M.schema = {
]]
},
show_deleted = {
type = 'boolean',
default = false,
description = [[
Show the old version of hunks inline in the buffer (via virtual lines).
Note: Virtual lines currently use the highlight `GitSignsDeleteLn`.
]]
},
diff_opts = {
type = 'table',
deep_extend = true,

View File

@ -212,6 +212,67 @@ M.apply_word_diff = function(bufnr: integer, row: integer)
end
end
local ns_rm = api.nvim_create_namespace('gitsigns_removed')
local VIRT_LINE_LEN = 300
local function clear_deleted(bufnr: integer)
local marks = api.nvim_buf_get_extmarks(bufnr, ns_rm, 0, -1, {})
for _, mark in ipairs(marks as {{integer, integer, integer}}) do
api.nvim_buf_del_extmark(bufnr, ns_rm, mark[1])
end
end
local function show_deleted(bufnr: integer)
local bcache = cache[bufnr]
clear_deleted(bufnr)
if not config.show_deleted then
return
end
for _, hunk in ipairs(bcache.hunks) do
local virt_lines = {}
local do_word_diff = config.word_diff and #hunk.removed.lines == #hunk.added.lines
for i, line in ipairs(hunk.removed.lines) do
local vline = {}
local last_ecol = 1
if do_word_diff then
local regions = require('gitsigns.diff_int').run_word_diff(
{hunk.removed.lines[i]}, {hunk.added.lines[i]})
for _, region in ipairs(regions) do
local rline, scol, ecol = region[1], region[3], region[4]
if rline > 1 then
break
end
vline[#vline+1] = { line:sub(last_ecol, scol-1), config.signs.delete.linehl }
vline[#vline+1] = { line:sub(scol, ecol-1), 'TermCursor'}
last_ecol = ecol
end
end
if #line > 0 then
vline[#vline+1] = { line:sub(last_ecol, -1), config.signs.delete.linehl }
end
-- Add extra padding so the entire line is highlighted
local padding = string.rep(' ', VIRT_LINE_LEN-#line)
vline[#vline+1] = { padding, config.signs.delete.linehl }
virt_lines[i] = vline
end
api.nvim_buf_set_extmark(bufnr, ns_rm, hunk.start-1, -1, {
virt_lines = virt_lines,
virt_lines_above = hunk.type ~= 'delete',
})
end
end
local update_cnt = 0
local update0 = function(bufnr: integer, bcache: CacheEntry)
@ -251,6 +312,8 @@ local update0 = function(bufnr: integer, bcache: CacheEntry)
-- Apply signs to the window. Other signs will be added by the decoration
-- provider as they are drawn.
M.apply_win_signs(bufnr, bcache.pending_signs)
show_deleted(bufnr)
end
local summary = gs_hunks.get_summary(bcache.hunks)
summary.head = git_obj.repo.abbrev_head