feat(highlight): add character-level intra-line diff highlighting
Line-level backgrounds (DiffsAdd/DiffsDelete) now get a second tier:
changed characters within modified lines receive an intense background
overlay (DiffsAddText/DiffsDeleteText at 70% alpha vs 40% for lines).
Treesitter foreground colors show through since the extmarks only set bg.
diff.lua extracts contiguous -/+ change groups from hunk lines and diffs
each group byte-by-byte using vim.diff(). An optional libvscodediff FFI
backend (lib.lua) auto-downloads the .so from codediff.nvim releases and
falls back to native if unavailable.
New config: highlights.intra.{enabled, algorithm, max_lines}. Gated by
max_lines (default 200) to avoid stalling on huge hunks. Priority 201
sits above treesitter (200) so the character bg always wins.
Closes #60
This commit is contained in:
parent
294cbad749
commit
997bc49f8b
7 changed files with 842 additions and 0 deletions
|
|
@ -6,11 +6,17 @@
|
|||
---@field enabled boolean
|
||||
---@field max_lines integer
|
||||
|
||||
---@class diffs.IntraConfig
|
||||
---@field enabled boolean
|
||||
---@field algorithm string
|
||||
---@field max_lines integer
|
||||
|
||||
---@class diffs.Highlights
|
||||
---@field background boolean
|
||||
---@field gutter boolean
|
||||
---@field treesitter diffs.TreesitterConfig
|
||||
---@field vim diffs.VimConfig
|
||||
---@field intra diffs.IntraConfig
|
||||
|
||||
---@class diffs.FugitiveConfig
|
||||
---@field horizontal string|false
|
||||
|
|
@ -82,6 +88,11 @@ local default_config = {
|
|||
enabled = false,
|
||||
max_lines = 200,
|
||||
},
|
||||
intra = {
|
||||
enabled = true,
|
||||
algorithm = 'auto',
|
||||
max_lines = 200,
|
||||
},
|
||||
},
|
||||
fugitive = {
|
||||
horizontal = 'du',
|
||||
|
|
@ -172,10 +183,15 @@ local function compute_highlight_groups()
|
|||
local blended_add = blend_color(add_bg, bg, 0.4)
|
||||
local blended_del = blend_color(del_bg, bg, 0.4)
|
||||
|
||||
local blended_add_text = blend_color(add_bg, bg, 0.7)
|
||||
local blended_del_text = blend_color(del_bg, bg, 0.7)
|
||||
|
||||
vim.api.nvim_set_hl(0, 'DiffsAdd', { default = true, bg = blended_add })
|
||||
vim.api.nvim_set_hl(0, 'DiffsDelete', { default = true, bg = blended_del })
|
||||
vim.api.nvim_set_hl(0, 'DiffsAddNr', { default = true, fg = add_fg, bg = blended_add })
|
||||
vim.api.nvim_set_hl(0, 'DiffsDeleteNr', { default = true, fg = del_fg, bg = blended_del })
|
||||
vim.api.nvim_set_hl(0, 'DiffsAddText', { default = true, bg = blended_add_text })
|
||||
vim.api.nvim_set_hl(0, 'DiffsDeleteText', { default = true, bg = blended_del_text })
|
||||
|
||||
local diff_change = resolve_hl('DiffChange')
|
||||
local diff_text = resolve_hl('DiffText')
|
||||
|
|
@ -207,6 +223,7 @@ local function init()
|
|||
['highlights.gutter'] = { opts.highlights.gutter, 'boolean', true },
|
||||
['highlights.treesitter'] = { opts.highlights.treesitter, 'table', true },
|
||||
['highlights.vim'] = { opts.highlights.vim, 'table', true },
|
||||
['highlights.intra'] = { opts.highlights.intra, 'table', true },
|
||||
})
|
||||
|
||||
if opts.highlights.treesitter then
|
||||
|
|
@ -226,6 +243,20 @@ local function init()
|
|||
['highlights.vim.max_lines'] = { opts.highlights.vim.max_lines, 'number', true },
|
||||
})
|
||||
end
|
||||
|
||||
if opts.highlights.intra then
|
||||
vim.validate({
|
||||
['highlights.intra.enabled'] = { opts.highlights.intra.enabled, 'boolean', true },
|
||||
['highlights.intra.algorithm'] = {
|
||||
opts.highlights.intra.algorithm,
|
||||
function(v)
|
||||
return v == nil or v == 'auto' or v == 'native' or v == 'vscode'
|
||||
end,
|
||||
"'auto', 'native', or 'vscode'",
|
||||
},
|
||||
['highlights.intra.max_lines'] = { opts.highlights.intra.max_lines, 'number', true },
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if opts.fugitive then
|
||||
|
|
@ -266,6 +297,14 @@ local function init()
|
|||
then
|
||||
error('diffs: highlights.vim.max_lines must be >= 1')
|
||||
end
|
||||
if
|
||||
opts.highlights
|
||||
and opts.highlights.intra
|
||||
and opts.highlights.intra.max_lines
|
||||
and opts.highlights.intra.max_lines < 1
|
||||
then
|
||||
error('diffs: highlights.intra.max_lines must be >= 1')
|
||||
end
|
||||
|
||||
config = vim.tbl_deep_extend('force', default_config, opts)
|
||||
log.set_enabled(config.debug)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue