refactor(highlights)!: rework highlights

- Added GitSigns*Inline and GitSigns*LnInline to be used with word diff
    - GitSigns*LnInline is used for word diff with config.word_diff
    - GitSigns*Inline is used for word diff in hunk previews

- Added GitSigns*VirtLn and GitSigns*VirtLnInline to be used with
  `config.show_deleted`.

- Define GitSigns highlights conditionally as opposed to only defining
  them if certain features are enabled.
This commit is contained in:
Lewis Russell 2021-10-28 15:09:53 +01:00 committed by Lewis Russell
parent 4861666b58
commit b4548e4c60
14 changed files with 222 additions and 237 deletions

View File

@ -415,18 +415,16 @@ signs *gitsigns-config-signs*
• `show_count` to enable showing count of hunk, e.g. number of deleted
lines.
Note if `hl`, `numhl` or `linehl` use a `GitSigns*` highlight and it is
not defined, it will be automatically derived by searching for other
defined highlights in the following order:
Note if a highlight is not defined, it will be automatically derived by
searching for other defined highlights in the following order:
• `GitGutter*`
• `Signify*`
• `Diff*Gutter`
• `diff*`
• `Diff*`
For example if `signs.add.hl = GitSignsAdd` and `GitSignsAdd` is not
defined but `GitGutterAdd` is defined, then `GitSignsAdd` will be linked
to `GitGutterAdd`.
For example if `GitSignsAdd` is not defined but `GitGutterAdd` is defined,
then `GitSignsAdd` will be linked to `GitGutterAdd`.
keymaps *gitsigns-config-keymaps*
DEPRECATED
@ -744,9 +742,18 @@ word_diff *gitsigns-config-word_diff*
Requires `config.diff_opts.internal = true` .
Uses the highlights:
• GitSignsAddLn
• GitSignsChangeLn
• GitSignsDeleteLn
• For word diff in previews:
• `GitSignsAddInline`
• `GitSignsChangeInline`
• `GitSignsDeleteInline`
• For word diff in buffer:
• `GitSignsAddLnInline`
• `GitSignsChangeLnInline`
• `GitSignsDeleteLnInline`
• For word diff in virtual lines (e.g. show_deleted):
• `GitSignsAddVirtLnInline`
• `GitSignsChangeVirtLnInline`
• `GitSignsDeleteVirtLnInline`
debug_mode *gitsigns-config-debug_mode*
Type: `boolean`, Default: `false`

View File

@ -21,6 +21,7 @@ local Hunk_Public = gs_hunks.Hunk_Public
local api = vim.api
local current_buf = api.nvim_get_current_buf
local add_highlight = api.nvim_buf_add_highlight
local NavHunkOpts = {}
@ -437,17 +438,21 @@ end
local function highlight_hunk_lines(bufnr, offset, hunk)
for i = 1, #hunk.removed.lines do
api.nvim_buf_add_highlight(bufnr, -1, 'DiffRemoved', offset + i - 1, 0, -1)
add_highlight(bufnr, -1, 'GitSignsDeleteLn', offset + i - 1, 0, -1)
end
for i = 1, #hunk.added.lines do
api.nvim_buf_add_highlight(bufnr, -1, 'DiffAdded', #hunk.removed.lines + offset + i - 1, 0, -1)
add_highlight(bufnr, -1, 'GitSignsAddLn', #hunk.removed.lines + offset + i - 1, 0, -1)
end
if config.diff_opts.internal then
local regions = require('gitsigns.diff_int').run_word_diff(hunk.removed.lines, hunk.added.lines)
for _, region in ipairs(regions) do
local removed_regions, added_regions = require('gitsigns.diff_int').run_word_diff(hunk.removed.lines, hunk.added.lines)
for _, region in ipairs(removed_regions) do
local line, scol, ecol = region[1], region[3], region[4]
api.nvim_buf_add_highlight(bufnr, -1, 'TermCursor', line + offset - 1, scol, ecol)
add_highlight(bufnr, -1, 'GitSignsDeleteInline', line + offset - 1, scol, ecol)
end
for _, region in ipairs(added_regions) do
local line, scol, ecol = region[1], region[3], region[4]
add_highlight(bufnr, -1, 'GitSignsAddInline', line + offset - 1, scol, ecol)
end
end
end
@ -499,7 +504,7 @@ M.preview_hunk = noautocmd(function()
local _, bufnr = popup.create(lines, config.preview_config)
api.nvim_buf_add_highlight(bufnr, -1, 'Title', 0, 0, -1)
add_highlight(bufnr, -1, 'Title', 0, 0, -1)
api.nvim_buf_set_var(cbuf, '_gitsigns_preview_open', true)
vim.cmd([[autocmd CursorMoved,CursorMovedI <buffer> ++once silent! unlet b:_gitsigns_preview_open]])
@ -637,7 +642,7 @@ M.blame_line = void(function(opts)
local highlights = {}
local function add_highlight(hlgroup, start, length)
local function add_hl(hlgroup, start, length)
highlights[#highlights + 1] = { hlgroup, #lines - 1, start or 0, length or -1 }
end
@ -660,9 +665,9 @@ M.blame_line = void(function(opts)
local p2 = #result.author
local p3 = #date
add_highlight('Directory', 0, p1)
add_highlight('MoreMsg', p1 + 1, p2)
add_highlight('Label', p1 + p2 + 2, p3 + 2)
add_hl('Directory', 0, p1)
add_hl('MoreMsg', p1 + 1, p2)
add_hl('Label', p1 + p2 + 2, p3 + 2)
vim.list_extend(lines, commit_message)
@ -671,7 +676,7 @@ M.blame_line = void(function(opts)
end
else
lines[#lines + 1] = result.author
add_highlight('ErrorMsg')
add_hl('ErrorMsg')
if full then
scheduler()
hunk, ihunk = get_cursor_hunk(bufnr, bcache.hunks)
@ -682,7 +687,7 @@ M.blame_line = void(function(opts)
if hunk then
lines[#lines + 1] = ''
lines[#lines + 1] = ('Hunk %d of %d'):format(ihunk, nhunk)
add_highlight('Title')
add_hl('Title')
vim.list_extend(lines, gs_hunks.patch_lines(hunk))
end
@ -691,7 +696,7 @@ M.blame_line = void(function(opts)
for _, h in ipairs(highlights) do
local hlgroup, line, start, length = h[1], h[2], h[3], h[4]
api.nvim_buf_add_highlight(pbufnr, -1, hlgroup, line, start, start + length)
add_highlight(pbufnr, -1, hlgroup, line, start, start + length)
end
if hunk then

View File

@ -131,18 +131,16 @@ M.schema = {
`show_count` to enable showing count of hunk, e.g. number of deleted
lines.
Note if `hl`, `numhl` or `linehl` use a `GitSigns*` highlight and it is
not defined, it will be automatically derived by searching for other
defined highlights in the following order:
Note if a highlight is not defined, it will be automatically derived by
searching for other defined highlights in the following order:
`GitGutter*`
`Signify*`
`Diff*Gutter`
`diff*`
`Diff*`
For example if `signs.add.hl = GitSignsAdd` and `GitSignsAdd` is not
defined but `GitGutterAdd` is defined, then `GitSignsAdd` will be linked
to `GitGutterAdd`.
For example if `GitSignsAdd` is not defined but `GitGutterAdd` is defined,
then `GitSignsAdd` will be linked to `GitGutterAdd`.
]],
},
@ -591,9 +589,18 @@ M.schema = {
Requires `config.diff_opts.internal = true` .
Uses the highlights:
GitSignsAddLn
GitSignsChangeLn
GitSignsDeleteLn
For word diff in previews:
`GitSignsAddInline`
`GitSignsChangeInline`
`GitSignsDeleteInline`
For word diff in buffer:
`GitSignsAddLnInline`
`GitSignsChangeLnInline`
`GitSignsDeleteLnInline`
For word diff in virtual lines (e.g. show_deleted):
`GitSignsAddVirtLnInline`
`GitSignsChangeVirtLnInline`
`GitSignsDeleteVirtLnInline`
]],
},

View File

@ -50,11 +50,12 @@ local Region = {}
local gaps_between_regions = 5
function M.run_word_diff(removed, added)
if #removed ~= #added then
return {}
end
local adds = {}
local rems = {}
local ret = {}
if #removed ~= #added then
return rems, adds
end
for i = 1, #removed do
@ -93,14 +94,11 @@ function M.run_word_diff(removed, added)
end
for _, h in ipairs(hunks) do
local rem = { i, h.type, h.removed.start, h.removed.start + h.removed.count }
local add = { i + #removed, h.type, h.added.start, h.added.start + h.added.count }
ret[#ret + 1] = rem
ret[#ret + 1] = add
adds[#adds + 1] = { i + #removed, h.type, h.added.start, h.added.start + h.added.count }
rems[#rems + 1] = { i, h.type, h.removed.start, h.removed.start + h.removed.count }
end
end
return ret
return rems, adds
end
return M

View File

@ -7,71 +7,65 @@ local M = {}
local GitSignHl = {}
local hls = {
GitSignsAdd = { 'GitGutterAdd', 'SignifySignAdd', 'DiffAddedGutter', 'diffAdded', 'DiffAdd' },
GitSignsChange = { 'GitGutterChange', 'SignifySignChange', 'DiffModifiedGutter', 'diffChanged', 'DiffChange' },
GitSignsDelete = { 'GitGutterDelete', 'SignifySignDelete', 'DiffRemovedGutter', 'diffRemoved', 'DiffDelete' },
{ GitSignsAdd = { 'GitGutterAdd', 'SignifySignAdd', 'DiffAddedGutter', 'diffAdded', 'DiffAdd' } },
{ GitSignsChange = { 'GitGutterChange', 'SignifySignChange', 'DiffModifiedGutter', 'diffChanged', 'DiffChange' } },
{ GitSignsDelete = { 'GitGutterDelete', 'SignifySignDelete', 'DiffRemovedGutter', 'diffRemoved', 'DiffDelete' } },
GitSignsAddNr = { 'GitGutterAddLineNr', 'GitSignsAdd', 'SignifySignAdd', 'DiffAddedGutter', 'diffAdded', 'DiffAdd' },
GitSignsChangeNr = { 'GitGutterChangeLineNr', 'GitSignsChange', 'SignifySignChange', 'DiffModifiedGutter', 'diffChanged', 'DiffChange' },
GitSignsDeleteNr = { 'GitGutterDeleteLineNr', 'GitSignsDelete', 'SignifySignDelete', 'DiffRemovedGutter', 'diffRemoved', 'DiffDelete' },
{ GitSignsAddNr = { 'GitGutterAddLineNr', 'GitSignsAdd' } },
{ GitSignsChangeNr = { 'GitGutterChangeLineNr', 'GitSignsChange' } },
{ GitSignsDeleteNr = { 'GitGutterDeleteLineNr', 'GitSignsDelete' } },
GitSignsAddLn = { 'GitGutterAddLine', 'SignifyLineAdd', 'DiffAdd' },
GitSignsChangeLn = { 'GitGutterChangeLine', 'SignifyLineChange', 'DiffChange' },
GitSignsDeleteLn = { 'GitGutterDeleteLine', 'SignifyLineDelete', 'DiffDelete' },
{ GitSignsAddLn = { 'GitGutterAddLine', 'SignifyLineAdd', 'DiffAdd' } },
{ GitSignsChangeLn = { 'GitGutterChangeLine', 'SignifyLineChange', 'DiffChange' } },
{ GitSignsDeleteLn = { 'GitGutterDeleteLine', 'SignifyLineDelete', 'DiffDelete' } },
GitSignsCurrentLineBlame = { 'NonText' },
{ GitSignsCurrentLineBlame = { 'NonText' } },
{ GitSignsAddInline = { 'TermCursor' } },
{ GitSignsDeleteInline = { 'TermCursor' } },
{ GitSignsChangeInline = { 'TermCursor' } },
{ GitSignsAddLnInline = { 'GitSignsAddInline' } },
{ GitSignsChangeLnInline = { 'GitSignsChangeInline' } },
{ GitSignsDeleteLnInline = { 'GitSignsDeleteInline' } },
{ GitSignsAddLnVirtLn = { 'GitSignsAddLn' } },
{ GitSignsChangeVirtLn = { 'GitSignsChangeLn' } },
{ GitSignsDeleteVirtLn = { 'GitSignsDeleteLn' } },
{ GitSignsAddLnVirtLnInLine = { 'GitSignsAddLnInline' } },
{ GitSignsChangeVirtLnInLine = { 'GitSignsChangeLnInline' } },
{ GitSignsDeleteVirtLnInLine = { 'GitSignsDeleteLnInline' } },
}
local function is_hl_set(hl_name)
local exists, hl = pcall(api.nvim_get_hl_by_name, hl_name, true)
local color = hl.foreground or hl.background
local color = hl.foreground or hl.background or hl.reverse
return exists and color ~= nil
end
local function isGitSignHl(hl)
return hls[hl] ~= nil
end
M.setup_highlights = function()
for _, hlg in ipairs(hls) do
for hl, candidates in pairs(hlg) do
if is_hl_set(hl) then
M.setup_highlight = function(hl_name)
if not isGitSignHl(hl_name) then
return
end
if is_hl_set(hl_name) then
dprintf('Highlight %s is already defined', hl_name)
return
end
for _, d in ipairs(hls[hl_name]) do
if is_hl_set(d) then
dprintf('Deriving %s from %s', hl_name, d)
vim.cmd(('highlight default link %s %s'):format(hl_name, d))
return
dprintf('Highlight %s is already defined', hl)
else
for _, d in ipairs(candidates) do
if is_hl_set(d) then
dprintf('Deriving %s from %s', hl, d)
vim.cmd(('highlight default link %s %s'):format(hl, d))
break
end
end
end
end
end
dprintf('Unable to setup highlight %s', hl_name)
end
return M

View File

@ -22,8 +22,7 @@ local util = require('gitsigns.util')
local gs_hunks = require("gitsigns.hunks")
local Hunk = gs_hunks.Hunk
local setup_highlight = require('gitsigns.highlight').setup_highlight
local setup_highlights = require('gitsigns.highlight').setup_highlights
local config = require('gitsigns.config').config
local api = vim.api
@ -184,7 +183,8 @@ M.apply_word_diff = function(bufnr, row)
for _, hunk in ipairs(cache[bufnr].hunks) do
if lnum >= hunk.start and lnum <= hunk.vend then
local size = (#hunk.added.lines + #hunk.removed.lines) / 2
local regions = require('gitsigns.diff_int').run_word_diff(hunk.removed.lines, hunk.added.lines)
local removed_regions, added_regions = require('gitsigns.diff_int').run_word_diff(hunk.removed.lines, hunk.added.lines)
local regions = vim.list_extend(removed_regions or {}, added_regions or {})
for _, region in ipairs(regions) do
local line = region[1]
if lnum == hunk.start + line - size - 1 then
@ -199,10 +199,11 @@ M.apply_word_diff = function(bufnr, row)
end
api.nvim_buf_set_extmark(bufnr, ns, row, scol - 1, {
end_col = ecol - 1,
hl_group = rtype == 'add' and 'GitSignsAddLn' or
rtype == 'change' and 'GitSignsChangeLn' or
'GitSignsDeleteLn',
hl_group = rtype == 'add' and 'GitSignsAddLnInline' or
rtype == 'change' and 'GitSignsChangeLnInline' or
'GitSignsDeleteLnInline',
ephemeral = true,
priority = 1000,
})
end
end
@ -249,19 +250,19 @@ local function show_deleted(bufnr)
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' }
vline[#vline + 1] = { line:sub(last_ecol, scol - 1), 'GitsignsDeleteVirtLn' }
vline[#vline + 1] = { line:sub(scol, ecol - 1), 'GitsignsDeleteVirtLnInline' }
last_ecol = ecol
end
end
if #line > 0 then
vline[#vline + 1] = { line:sub(last_ecol, -1), config.signs.delete.linehl }
vline[#vline + 1] = { line:sub(last_ecol, -1), 'GitsignsDeleteVirtLn' }
end
local padding = string.rep(' ', VIRT_LINE_LEN - #line)
vline[#vline + 1] = { padding, config.signs.delete.linehl }
vline[#vline + 1] = { padding, 'GitsignsDeleteVirtLn' }
virt_lines[i] = vline
end
@ -340,16 +341,6 @@ M.setup_signs_and_highlights = function(redefine)
for t, sign_name in pairs(signs.sign_map) do
local cs = config.signs[t]
setup_highlight(cs.hl)
if config.numhl then
setup_highlight(cs.numhl)
end
if config.linehl or config.word_diff then
setup_highlight(cs.linehl)
end
signs.define(sign_name, {
texthl = cs.hl,
text = config.signcolumn and cs.text or nil,
@ -358,9 +349,8 @@ M.setup_signs_and_highlights = function(redefine)
}, redefine)
end
if config.current_line_blame then
setup_highlight('GitSignsCurrentLineBlame')
end
setup_highlights()
end
return M

View File

@ -21,6 +21,7 @@ local Hunk_Public = gs_hunks.Hunk_Public
local api = vim.api
local current_buf = api.nvim_get_current_buf
local add_highlight = api.nvim_buf_add_highlight
local record NavHunkOpts
forwards: boolean
@ -437,17 +438,21 @@ end
local function highlight_hunk_lines(bufnr: integer, offset: integer, hunk: Hunk)
for i = 1, #hunk.removed.lines do
api.nvim_buf_add_highlight(bufnr, -1, 'DiffRemoved', offset+i-1, 0, -1)
add_highlight(bufnr, -1, 'GitSignsDeleteLn', offset+i-1, 0, -1)
end
for i = 1, #hunk.added.lines do
api.nvim_buf_add_highlight(bufnr, -1, 'DiffAdded', #hunk.removed.lines + offset+i-1, 0, -1)
add_highlight(bufnr, -1, 'GitSignsAddLn', #hunk.removed.lines + offset+i-1, 0, -1)
end
if config.diff_opts.internal then
local regions = require('gitsigns.diff_int').run_word_diff(hunk.removed.lines, hunk.added.lines)
for _, region in ipairs(regions) do
local removed_regions, added_regions = require('gitsigns.diff_int').run_word_diff(hunk.removed.lines, hunk.added.lines)
for _, region in ipairs(removed_regions) do
local line, scol, ecol = region[1], region[3], region[4]
api.nvim_buf_add_highlight(bufnr, -1, 'TermCursor', line+offset-1, scol, ecol)
add_highlight(bufnr, -1, 'GitSignsDeleteInline', line+offset-1, scol, ecol)
end
for _, region in ipairs(added_regions) do
local line, scol, ecol = region[1], region[3], region[4]
add_highlight(bufnr, -1, 'GitSignsAddInline', line+offset-1, scol, ecol)
end
end
end
@ -499,7 +504,7 @@ M.preview_hunk = noautocmd(function()
local _, bufnr = popup.create(lines, config.preview_config)
api.nvim_buf_add_highlight(bufnr, -1, 'Title', 0, 0, -1)
add_highlight(bufnr, -1, 'Title', 0, 0, -1)
api.nvim_buf_set_var(cbuf, '_gitsigns_preview_open', true)
vim.cmd[[autocmd CursorMoved,CursorMovedI <buffer> ++once silent! unlet b:_gitsigns_preview_open]]
@ -637,7 +642,7 @@ M.blame_line = void(function(opts: boolean | BlameOpts)
local highlights: {{string, integer, integer, integer}} = {}
local function add_highlight(hlgroup: string, start: integer, length: integer)
local function add_hl(hlgroup: string, start: integer, length: integer)
highlights[#highlights+1] = {hlgroup, #lines-1, start or 0, length or -1}
end
@ -660,9 +665,9 @@ M.blame_line = void(function(opts: boolean | BlameOpts)
local p2 = #result.author
local p3 = #date
add_highlight('Directory', 0 , p1)
add_highlight('MoreMsg' , p1+1 , p2)
add_highlight('Label' , p1+p2+2, p3+2)
add_hl('Directory', 0 , p1)
add_hl('MoreMsg' , p1+1 , p2)
add_hl('Label' , p1+p2+2, p3+2)
vim.list_extend(lines, commit_message)
@ -671,7 +676,7 @@ M.blame_line = void(function(opts: boolean | BlameOpts)
end
else
lines[#lines+1] = result.author
add_highlight('ErrorMsg')
add_hl('ErrorMsg')
if full then
scheduler()
hunk, ihunk = get_cursor_hunk(bufnr, bcache.hunks)
@ -682,7 +687,7 @@ M.blame_line = void(function(opts: boolean | BlameOpts)
if hunk then
lines[#lines+1] = ''
lines[#lines+1] = ('Hunk %d of %d'):format(ihunk, nhunk)
add_highlight('Title')
add_hl('Title')
vim.list_extend(lines, gs_hunks.patch_lines(hunk))
end
@ -691,7 +696,7 @@ M.blame_line = void(function(opts: boolean | BlameOpts)
for _, h in ipairs(highlights) do
local hlgroup, line, start, length = h[1], h[2], h[3], h[4]
api.nvim_buf_add_highlight(pbufnr, -1, hlgroup, line, start, start+length)
add_highlight(pbufnr, -1, hlgroup, line, start, start+length)
end
if hunk then

View File

@ -131,18 +131,16 @@ M.schema = {
`show_count` to enable showing count of hunk, e.g. number of deleted
lines.
Note if `hl`, `numhl` or `linehl` use a `GitSigns*` highlight and it is
not defined, it will be automatically derived by searching for other
defined highlights in the following order:
Note if a highlight is not defined, it will be automatically derived by
searching for other defined highlights in the following order:
`GitGutter*`
`Signify*`
`Diff*Gutter`
`diff*`
`Diff*`
For example if `signs.add.hl = GitSignsAdd` and `GitSignsAdd` is not
defined but `GitGutterAdd` is defined, then `GitSignsAdd` will be linked
to `GitGutterAdd`.
For example if `GitSignsAdd` is not defined but `GitGutterAdd` is defined,
then `GitSignsAdd` will be linked to `GitGutterAdd`.
]]
},
@ -591,9 +589,18 @@ M.schema = {
Requires `config.diff_opts.internal = true` .
Uses the highlights:
GitSignsAddLn
GitSignsChangeLn
GitSignsDeleteLn
For word diff in previews:
`GitSignsAddInline`
`GitSignsChangeInline`
`GitSignsDeleteInline`
For word diff in buffer:
`GitSignsAddLnInline`
`GitSignsChangeLnInline`
`GitSignsDeleteLnInline`
For word diff in virtual lines (e.g. show_deleted):
`GitSignsAddVirtLnInline`
`GitSignsChangeVirtLnInline`
`GitSignsDeleteVirtLnInline`
]]
},

View File

@ -49,12 +49,13 @@ local type Region = {integer, string, integer, integer}
local gaps_between_regions = 5
function M.run_word_diff(removed: {string}, added: {string}): {Region}
if #removed ~= #added then
return {}
end
function M.run_word_diff(removed: {string}, added: {string}): {Region}, {Region}
local adds: {Region} = {}
local rems: {Region} = {}
local ret: {Region} = {}
if #removed ~= #added then
return rems, adds
end
for i = 1, #removed do
-- pair lines by position
@ -93,14 +94,11 @@ function M.run_word_diff(removed: {string}, added: {string}): {Region}
end
for _, h in ipairs(hunks) do
local rem = {i , h.type, h.removed.start, h.removed.start + h.removed.count}
local add = {i+#removed, h.type, h.added.start , h.added.start + h.added.count}
ret[#ret+1] = rem
ret[#ret+1] = add
adds[#adds+1] = {i+#removed, h.type, h.added.start , h.added.start + h.added.count}
rems[#rems+1] = {i , h.type, h.removed.start, h.removed.start + h.removed.count}
end
end
return ret
return rems, adds
end
return M

View File

@ -4,74 +4,68 @@ local api = vim.api
local dprintf = require("gitsigns.debug").dprintf
local record M
setup_highlight: function(string)
setup_highlights: function()
end
local enum GitSignHl
'GitSignsAdd'
'GitSignsChange'
'GitSignsDelete'
-- Use array of dict so we can iterate deterministically
local hls: {{string:{string}}} = {
{GitSignsAdd = {'GitGutterAdd' , 'SignifySignAdd' , 'DiffAddedGutter' , 'diffAdded' , 'DiffAdd' }},
{GitSignsChange = {'GitGutterChange', 'SignifySignChange', 'DiffModifiedGutter', 'diffChanged', 'DiffChange'}},
{GitSignsDelete = {'GitGutterDelete', 'SignifySignDelete', 'DiffRemovedGutter' , 'diffRemoved', 'DiffDelete'}},
'GitSignsAddNr'
'GitSignsChangeNr'
'GitSignsDeleteNr'
{GitSignsAddNr = {'GitGutterAddLineNr' , 'GitSignsAdd' }},
{GitSignsChangeNr = {'GitGutterChangeLineNr', 'GitSignsChange'}},
{GitSignsDeleteNr = {'GitGutterDeleteLineNr', 'GitSignsDelete'}},
'GitSignsAddLn'
'GitSignsChangeLn'
'GitSignsDeleteLn'
{GitSignsAddLn = {'GitGutterAddLine' , 'SignifyLineAdd' , 'DiffAdd' }},
{GitSignsChangeLn = {'GitGutterChangeLine', 'SignifyLineChange', 'DiffChange'}},
{GitSignsDeleteLn = {'GitGutterDeleteLine', 'SignifyLineDelete', 'DiffDelete'}},
'GitSignsCurrentLineBlame'
end
{GitSignsCurrentLineBlame = {'NonText'}},
local hls: {GitSignHl:{string}} = {
GitSignsAdd = {'GitGutterAdd' , 'SignifySignAdd' , 'DiffAddedGutter' , 'diffAdded' , 'DiffAdd' },
GitSignsChange = {'GitGutterChange', 'SignifySignChange', 'DiffModifiedGutter', 'diffChanged', 'DiffChange'},
GitSignsDelete = {'GitGutterDelete', 'SignifySignDelete', 'DiffRemovedGutter' , 'diffRemoved', 'DiffDelete'},
{GitSignsAddInline = {'TermCursor'}},
{GitSignsDeleteInline = {'TermCursor'}},
{GitSignsChangeInline = {'TermCursor'}},
GitSignsAddNr = {'GitGutterAddLineNr' , 'GitSignsAdd' , 'SignifySignAdd' , 'DiffAddedGutter' , 'diffAdded' , 'DiffAdd' },
GitSignsChangeNr = {'GitGutterChangeLineNr', 'GitSignsChange', 'SignifySignChange', 'DiffModifiedGutter', 'diffChanged', 'DiffChange'},
GitSignsDeleteNr = {'GitGutterDeleteLineNr', 'GitSignsDelete', 'SignifySignDelete', 'DiffRemovedGutter' , 'diffRemoved', 'DiffDelete'},
{GitSignsAddLnInline = {'GitSignsAddInline'}},
{GitSignsChangeLnInline = {'GitSignsChangeInline'}},
{GitSignsDeleteLnInline = {'GitSignsDeleteInline'}},
GitSignsAddLn = {'GitGutterAddLine' , 'SignifyLineAdd' , 'DiffAdd' },
GitSignsChangeLn = {'GitGutterChangeLine', 'SignifyLineChange', 'DiffChange'},
GitSignsDeleteLn = {'GitGutterDeleteLine', 'SignifyLineDelete', 'DiffDelete'},
{GitSignsAddLnVirtLn = {'GitSignsAddLn' }},
{GitSignsChangeVirtLn = {'GitSignsChangeLn'}},
{GitSignsDeleteVirtLn = {'GitSignsDeleteLn'}},
GitSignsCurrentLineBlame = {'NonText'},
{GitSignsAddLnVirtLnInLine = {'GitSignsAddLnInline' }},
{GitSignsChangeVirtLnInLine = {'GitSignsChangeLnInline'}},
{GitSignsDeleteVirtLnInLine = {'GitSignsDeleteLnInline'}},
}
local function is_hl_set(hl_name: string): boolean
-- TODO: this only works with `set termguicolors`
local exists, hl = pcall(api.nvim_get_hl_by_name, hl_name, true)
local color = hl.foreground or hl.background
local color = hl.foreground or hl.background or hl.reverse
return exists and color ~= nil
end
local function isGitSignHl(hl: string): boolean
return hls[hl as GitSignHl] ~= nil
end
-- Setup a GitSign* highlight by deriving it from other potentially present
-- highlights.
M.setup_highlight = function(hl_name: string)
if not isGitSignHl(hl_name) then
return
end
if is_hl_set(hl_name) then
-- Already defined
dprintf('Highlight %s is already defined', hl_name)
return
end
for _, d in ipairs(hls[hl_name as GitSignHl]) do
if is_hl_set(d) then
dprintf('Deriving %s from %s', hl_name, d)
vim.cmd(('highlight default link %s %s'):format(hl_name, d))
return
M.setup_highlights = function()
for _, hlg in ipairs(hls) do
for hl, candidates in pairs(hlg) do
if is_hl_set(hl) then
-- Already defined
dprintf('Highlight %s is already defined', hl)
else
for _, d in ipairs(candidates) do
if is_hl_set(d) then
dprintf('Deriving %s from %s', hl, d)
vim.cmd(('highlight default link %s %s'):format(hl, d))
break
end
end
end
end
end
dprintf('Unable to setup highlight %s', hl_name)
end
return M

View File

@ -22,9 +22,8 @@ local util = require('gitsigns.util')
local gs_hunks = require("gitsigns.hunks")
local Hunk = gs_hunks.Hunk
local setup_highlight = require('gitsigns.highlight').setup_highlight
local config = require('gitsigns.config').config
local setup_highlights = require('gitsigns.highlight').setup_highlights
local config = require('gitsigns.config').config
local api = vim.api
@ -184,7 +183,8 @@ M.apply_word_diff = function(bufnr: integer, row: integer)
for _, hunk in ipairs(cache[bufnr].hunks) do
if lnum >= hunk.start and lnum <= hunk.vend then
local size = (#hunk.added.lines +#hunk.removed.lines) / 2
local regions = require('gitsigns.diff_int').run_word_diff(hunk.removed.lines, hunk.added.lines)
local removed_regions, added_regions = require('gitsigns.diff_int').run_word_diff(hunk.removed.lines, hunk.added.lines)
local regions = vim.list_extend(removed_regions or {}, added_regions or {})
for _, region in ipairs(regions) do
local line = region[1]
if lnum == hunk.start + line - size - 1 then
@ -199,10 +199,11 @@ M.apply_word_diff = function(bufnr: integer, row: integer)
end
api.nvim_buf_set_extmark(bufnr, ns, row, scol-1, {
end_col = ecol-1,
hl_group = rtype == 'add' and 'GitSignsAddLn'
or rtype == 'change' and 'GitSignsChangeLn'
or 'GitSignsDeleteLn',
ephemeral = true
hl_group = rtype == 'add' and 'GitSignsAddLnInline'
or rtype == 'change' and 'GitSignsChangeLnInline'
or 'GitSignsDeleteLnInline',
ephemeral = true,
priority = 1000
})
end
end
@ -249,19 +250,19 @@ local function show_deleted(bufnr: integer)
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'}
vline[#vline+1] = { line:sub(last_ecol, scol-1), 'GitsignsDeleteVirtLn'}
vline[#vline+1] = { line:sub(scol, ecol-1), 'GitsignsDeleteVirtLnInline'}
last_ecol = ecol
end
end
if #line > 0 then
vline[#vline+1] = { line:sub(last_ecol, -1), config.signs.delete.linehl }
vline[#vline+1] = { line:sub(last_ecol, -1), 'GitsignsDeleteVirtLn'}
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 }
vline[#vline+1] = { padding, 'GitsignsDeleteVirtLn'}
virt_lines[i] = vline
end
@ -340,16 +341,6 @@ M.setup_signs_and_highlights = function(redefine: boolean)
for t, sign_name in pairs(signs.sign_map) do
local cs = config.signs[t]
setup_highlight(cs.hl)
if config.numhl then
setup_highlight(cs.numhl)
end
if config.linehl or config.word_diff then
setup_highlight(cs.linehl)
end
signs.define(sign_name, {
texthl = cs.hl,
text = config.signcolumn and cs.text or nil,
@ -358,9 +349,8 @@ M.setup_signs_and_highlights = function(redefine: boolean)
}, redefine)
end
if config.current_line_blame then
setup_highlight('GitSignsCurrentLineBlame')
end
setup_highlights()
end
return M

View File

@ -33,11 +33,10 @@ describe('gitdir_watcher', function()
it('can follow moved files', function()
setup_test_repo()
setup_gitsigns(test_config)
command('Gitsigns clear_debug')
edit(test_file)
match_debug_messages {
"run_job: git --no-pager --version",
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
'attach(1): Attaching (trigger=BufRead)',
p"run_job: git .* config user.name",
"run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD",

View File

@ -107,12 +107,11 @@ describe('gitsigns', function()
it('can open files not in a git repo', function()
setup_gitsigns(config)
command('Gitsigns clear_debug')
local tmpfile = os.tmpname()
edit(tmpfile)
match_debug_messages {
'run_job: git --no-pager --version',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
'attach(1): Attaching (trigger=BufRead)',
p'run_job: git .* config user.name',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
@ -158,11 +157,10 @@ describe('gitsigns', function()
end)
it('does not attach inside .git', function()
command("Gitsigns clear_debug")
edit(scratch..'/.git/index')
match_debug_messages {
'run_job: git --no-pager --version',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
'attach(1): Attaching (trigger=BufRead)',
'new: In git dir',
'attach(1): Empty git obj'
@ -170,6 +168,7 @@ describe('gitsigns', function()
end)
it('doesn\'t attach to ignored files', function()
command("Gitsigns clear_debug")
write_to_file(scratch..'/.gitignore', {'dummy_ignored.txt'})
local ignored_file = scratch.."/dummy_ignored.txt"
@ -178,8 +177,6 @@ describe('gitsigns', function()
edit(ignored_file)
match_debug_messages {
'run_job: git --no-pager --version',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
'attach(1): Attaching (trigger=BufRead)',
p'run_job: git .* config user.name',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
@ -191,11 +188,10 @@ describe('gitsigns', function()
end)
it('doesn\'t attach to non-existent files', function()
command("Gitsigns clear_debug")
edit(newfile)
match_debug_messages {
'run_job: git --no-pager --version',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
'attach(1): Attaching (trigger=BufNewFile)',
p'run_job: git .* config user.name',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
@ -207,11 +203,10 @@ describe('gitsigns', function()
end)
it('doesn\'t attach to non-existent files with non-existent sub-dirs', function()
command("Gitsigns clear_debug")
edit(scratch..'/does/not/exist')
match_debug_messages {
'run_job: git --no-pager --version',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
'attach(1): Attaching (trigger=BufNewFile)',
'attach(1): Not a path',
}
@ -221,10 +216,9 @@ describe('gitsigns', function()
end)
it('can run copen', function()
command("Gitsigns clear_debug")
command("copen")
match_debug_messages {
'run_job: git --no-pager --version',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
'attach(2): Attaching (trigger=BufRead)',
'attach(2): Non-normal buffer',
}
@ -340,11 +334,10 @@ describe('gitsigns', function()
return false
end
]])
command("Gitsigns clear_debug")
edit(test_file)
match_debug_messages {
'run_job: git --no-pager --version',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
'attach(1): Attaching (trigger=BufRead)',
p'run_job: git .* config user.name',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
@ -455,10 +448,9 @@ describe('gitsigns', function()
it('attaches to newly created files', function()
setup_gitsigns(config)
command('Gitsigns clear_debug')
edit(newfile)
match_debug_messages{
'run_job: git --no-pager --version',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
'attach(1): Attaching (trigger=BufNewFile)',
'run_job: git --no-pager config user.name',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
@ -656,6 +648,7 @@ describe('gitsigns', function()
write_to_file(scratch..'/t3.txt', {'hello lewis'})
setup_gitsigns(config)
command('Gitsigns clear_debug')
helpers.exc_exec("vimgrep ben "..scratch..'/*')
@ -664,8 +657,6 @@ describe('gitsigns', function()
}}}
eq({
'run_job: git --no-pager --version',
'run_job: git --no-pager rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD',
'attach(2): attaching is disabled',
'attach(3): attaching is disabled',
'attach(4): attaching is disabled',

View File

@ -384,7 +384,7 @@ global record vim
in_fast_event: function(): boolean
list_extend: function({any}, {any}, integer, integer)
list_extend: function<T>({T}, {T}, integer, integer): {T}
list_slice: function<T>({T}, integer, integer): {T}
record keymap