feat: highlight improvemnets

This commit is contained in:
Barrett Ruth 2026-02-02 13:53:43 -05:00
parent 6a64a380b0
commit dabf2e2cc9
4 changed files with 71 additions and 25 deletions

View file

@ -56,7 +56,7 @@ CONFIGURATION *fugitive-ts-config*
Example: >lua Example: >lua
disabled_languages = { 'markdown', 'text' } disabled_languages = { 'markdown', 'text' }
< <
{debounce_ms} (integer, default: 50) {debounce_ms} (integer, default: 0)
Debounce delay in milliseconds for re-highlighting Debounce delay in milliseconds for re-highlighting
after buffer changes. Lower values feel snappier after buffer changes. Lower values feel snappier
but use more CPU. but use more CPU.
@ -66,9 +66,11 @@ CONFIGURATION *fugitive-ts-config*
this many lines. Prevents lag on massive diffs. this many lines. Prevents lag on massive diffs.
{hide_prefix} (boolean, default: true) {hide_prefix} (boolean, default: true)
Hide diff prefixes (`+`/`-`/` `) using conceal. Hide diff prefixes (`+`/`-`/` `) using virtual
Makes code appear flush left without the leading text overlay. Makes code appear without the
diff character. Sets `conceallevel=1` on attach. leading diff character. When `highlights.background`
is also enabled, the overlay inherits the line's
background color.
{highlights} (table, default: see below) {highlights} (table, default: see below)
Controls which highlight features are enabled. Controls which highlight features are enabled.

View file

@ -141,11 +141,14 @@ function M.highlight_hunk(bufnr, ns, hunk, opts)
local is_diff_line = prefix == '+' or prefix == '-' local is_diff_line = prefix == '+' or prefix == '-'
local line_hl = is_diff_line and (prefix == '+' and 'FugitiveTsAdd' or 'FugitiveTsDelete') local line_hl = is_diff_line and (prefix == '+' and 'FugitiveTsAdd' or 'FugitiveTsDelete')
or nil or nil
local number_hl = is_diff_line and (prefix == '+' and 'FugitiveTsAddNr' or 'FugitiveTsDeleteNr')
or nil
if opts.hide_prefix then if opts.hide_prefix then
local virt_hl = (opts.highlights.background and line_hl) or nil
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, buf_line, 0, { pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, buf_line, 0, {
end_col = 1, virt_text = { { ' ', virt_hl } },
conceal = '', virt_text_pos = 'overlay',
}) })
end end
@ -155,7 +158,7 @@ function M.highlight_hunk(bufnr, ns, hunk, opts)
priority = 198, priority = 198,
} }
if opts.highlights.gutter then if opts.highlights.gutter then
extmark_opts.number_hl_group = line_hl extmark_opts.number_hl_group = number_hl
end end
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, buf_line, 0, extmark_opts) pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, buf_line, 0, extmark_opts)
end end

View file

@ -25,15 +25,45 @@ local parser = require('fugitive-ts.parser')
local ns = vim.api.nvim_create_namespace('fugitive_ts') local ns = vim.api.nvim_create_namespace('fugitive_ts')
---@param hex integer
---@param bg_hex integer
---@param alpha number
---@return integer
local function blend_color(hex, bg_hex, alpha)
local r = bit.band(bit.rshift(hex, 16), 0xFF)
local g = bit.band(bit.rshift(hex, 8), 0xFF)
local b = bit.band(hex, 0xFF)
local bg_r = bit.band(bit.rshift(bg_hex, 16), 0xFF)
local bg_g = bit.band(bit.rshift(bg_hex, 8), 0xFF)
local bg_b = bit.band(bg_hex, 0xFF)
local blend_r = math.floor(r * alpha + bg_r * (1 - alpha))
local blend_g = math.floor(g * alpha + bg_g * (1 - alpha))
local blend_b = math.floor(b * alpha + bg_b * (1 - alpha))
return bit.bor(bit.lshift(blend_r, 16), bit.lshift(blend_g, 8), blend_b)
end
---@param name string
---@return vim.api.keyset.hl_info
local function resolve_hl(name)
local hl = vim.api.nvim_get_hl(0, { name = name })
while hl.link do
hl = vim.api.nvim_get_hl(0, { name = hl.link })
end
return hl
end
---@type fugitive-ts.Config ---@type fugitive-ts.Config
local default_config = { local default_config = {
enabled = true, enabled = true,
debug = false, debug = false,
languages = {}, languages = {},
disabled_languages = {}, disabled_languages = {},
debounce_ms = 50, debounce_ms = 0,
max_lines_per_hunk = 500, max_lines_per_hunk = 500,
hide_prefix = true, hide_prefix = false,
highlights = { highlights = {
treesitter = true, treesitter = true,
background = true, background = true,
@ -122,10 +152,6 @@ function M.attach(bufnr)
dbg('attaching to buffer %d', bufnr) dbg('attaching to buffer %d', bufnr)
if config.hide_prefix then
vim.api.nvim_set_option_value('conceallevel', 1, { win = 0 })
end
local debounced = create_debounced_highlight(bufnr) local debounced = create_debounced_highlight(bufnr)
highlight_buffer(bufnr) highlight_buffer(bufnr)
@ -185,10 +211,25 @@ function M.setup(opts)
parser.set_debug(config.debug) parser.set_debug(config.debug)
highlight.set_debug(config.debug) highlight.set_debug(config.debug)
local normal = vim.api.nvim_get_hl(0, { name = 'Normal' })
local diff_add = vim.api.nvim_get_hl(0, { name = 'DiffAdd' }) local diff_add = vim.api.nvim_get_hl(0, { name = 'DiffAdd' })
local diff_delete = vim.api.nvim_get_hl(0, { name = 'DiffDelete' }) local diff_delete = vim.api.nvim_get_hl(0, { name = 'DiffDelete' })
vim.api.nvim_set_hl(0, 'FugitiveTsAdd', { bg = diff_add.bg }) local diff_added = resolve_hl('diffAdded')
vim.api.nvim_set_hl(0, 'FugitiveTsDelete', { bg = diff_delete.bg }) local diff_removed = resolve_hl('diffRemoved')
local bg = normal.bg or 0x1e1e2e
local add_bg = diff_add.bg or 0x2e4a3a
local del_bg = diff_delete.bg or 0x4a2e3a
local add_fg = diff_added.fg or diff_add.fg or 0x80c080
local del_fg = diff_removed.fg or diff_delete.fg or 0xc08080
local blended_add = blend_color(add_bg, bg, 0.4)
local blended_del = blend_color(del_bg, bg, 0.4)
vim.api.nvim_set_hl(0, 'FugitiveTsAdd', { bg = blended_add })
vim.api.nvim_set_hl(0, 'FugitiveTsDelete', { bg = blended_del })
vim.api.nvim_set_hl(0, 'FugitiveTsAddNr', { fg = add_fg, bg = blended_add })
vim.api.nvim_set_hl(0, 'FugitiveTsDeleteNr', { fg = del_fg, bg = blended_del })
end end
return M return M

View file

@ -241,7 +241,7 @@ describe('highlight', function()
delete_buffer(bufnr) delete_buffer(bufnr)
end) end)
it('applies conceal extmarks when hide_prefix enabled', function() it('applies overlay extmarks when hide_prefix enabled', function()
local bufnr = create_buffer({ local bufnr = create_buffer({
'@@ -1,1 +1,2 @@', '@@ -1,1 +1,2 @@',
' local x = 1', ' local x = 1',
@ -258,17 +258,17 @@ describe('highlight', function()
highlight.highlight_hunk(bufnr, ns, hunk, default_opts({ hide_prefix = true })) highlight.highlight_hunk(bufnr, ns, hunk, default_opts({ hide_prefix = true }))
local extmarks = get_extmarks(bufnr) local extmarks = get_extmarks(bufnr)
local conceal_count = 0 local overlay_count = 0
for _, mark in ipairs(extmarks) do for _, mark in ipairs(extmarks) do
if mark[4] and mark[4].conceal == '' then if mark[4] and mark[4].virt_text_pos == 'overlay' then
conceal_count = conceal_count + 1 overlay_count = overlay_count + 1
end end
end end
assert.are.equal(2, conceal_count) assert.are.equal(2, overlay_count)
delete_buffer(bufnr) delete_buffer(bufnr)
end) end)
it('does not apply conceal extmarks when hide_prefix disabled', function() it('does not apply overlay extmarks when hide_prefix disabled', function()
local bufnr = create_buffer({ local bufnr = create_buffer({
'@@ -1,1 +1,2 @@', '@@ -1,1 +1,2 @@',
' local x = 1', ' local x = 1',
@ -285,13 +285,13 @@ describe('highlight', function()
highlight.highlight_hunk(bufnr, ns, hunk, default_opts({ hide_prefix = false })) highlight.highlight_hunk(bufnr, ns, hunk, default_opts({ hide_prefix = false }))
local extmarks = get_extmarks(bufnr) local extmarks = get_extmarks(bufnr)
local conceal_count = 0 local overlay_count = 0
for _, mark in ipairs(extmarks) do for _, mark in ipairs(extmarks) do
if mark[4] and mark[4].conceal == '' then if mark[4] and mark[4].virt_text_pos == 'overlay' then
conceal_count = conceal_count + 1 overlay_count = overlay_count + 1
end end
end end
assert.are.equal(0, conceal_count) assert.are.equal(0, overlay_count)
delete_buffer(bufnr) delete_buffer(bufnr)
end) end)