From d7537e93d0561e4821043aa864b4f245d7f7ba03 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Mon, 2 Feb 2026 00:57:41 -0500 Subject: [PATCH] feat: fix highlighting --- doc/fugitive-ts.nvim.txt | 29 +++++++++++++++-------------- lua/fugitive-ts/highlight.lua | 14 +++++++++----- lua/fugitive-ts/init.lua | 3 --- spec/highlight_spec.lua | 29 +++++++++++++---------------- spec/init_spec.lua | 1 - 5 files changed, 37 insertions(+), 39 deletions(-) diff --git a/doc/fugitive-ts.nvim.txt b/doc/fugitive-ts.nvim.txt index 19a8bbc..4945f0c 100644 --- a/doc/fugitive-ts.nvim.txt +++ b/doc/fugitive-ts.nvim.txt @@ -66,9 +66,11 @@ CONFIGURATION *fugitive-ts-config* this many lines. Prevents lag on massive diffs. {conceal_prefixes} (boolean, default: true) - Hide diff prefixes (`+`/`-`/` `) using extmark - conceal. Makes code appear without the leading - diff character. + Hide diff prefixes (`+`/`-`/` `) using virtual + text overlay. Makes code appear without the + leading diff character. When `highlights.background` + is also enabled, the overlay inherits the line's + background color. {highlights} (table, default: see below) Controls which highlight features are enabled. @@ -79,23 +81,22 @@ CONFIGURATION *fugitive-ts-config* {treesitter} (boolean, default: true) Apply treesitter syntax highlighting to code. - {headers} (boolean, default: true) - Highlight function context in hunk headers. - The context portion of `@@ -10,3 +10,4 @@ func()` - will receive treesitter highlighting. - {background} (boolean, default: true) - Apply `DiffAdd` background to `+` lines and - `DiffDelete` background to `-` lines. + Apply background highlighting to `+`/`-` lines + using `FugitiveTsAdd`/`FugitiveTsDelete` groups + (derived from `DiffAdd`/`DiffDelete` backgrounds). {linenr} (boolean, default: true) - Highlight line numbers with `DiffAdd`/`DiffDelete` - colors matching the line background. + Highlight line numbers with matching colors. + Only visible if line numbers are enabled. {vim} (boolean, default: false) Experimental: Use vim syntax highlighting as fallback when no treesitter parser is available. + Note: Header context (e.g., `@@ -10,3 +10,4 @@ func()`) is always + highlighted with treesitter when a parser is available. + ============================================================================== API *fugitive-ts-api* @@ -129,10 +130,10 @@ IMPLEMENTATION *fugitive-ts-implementation* - Language is detected from the filename using |vim.filetype.match()| - Diff prefixes (`+`/`-`/` `) are stripped from code lines - Code is parsed with |vim.treesitter.get_string_parser()| - - Background extmarks (`DiffAdd`/`DiffDelete`) applied at priority 198 + - Background extmarks (`FugitiveTsAdd`/`FugitiveTsDelete`) at priority 198 - `Normal` extmarks at priority 199 clear underlying diff foreground - Treesitter highlights are applied as extmarks at priority 200 - - Conceal extmarks hide diff prefixes when `conceal_prefixes` is enabled + - Virtual text overlays hide diff prefixes when `conceal_prefixes` is enabled 4. Re-highlighting occurs on `TextChanged` (debounced) and `Syntax` events ============================================================================== diff --git a/lua/fugitive-ts/highlight.lua b/lua/fugitive-ts/highlight.lua index f8cc026..8c95ceb 100644 --- a/lua/fugitive-ts/highlight.lua +++ b/lua/fugitive-ts/highlight.lua @@ -119,7 +119,7 @@ function M.highlight_hunk(bufnr, ns, hunk, opts) return end - if opts.highlights.headers and hunk.header_context and hunk.header_context_col then + if hunk.header_context and hunk.header_context_col then local header_line = hunk.start_line - 1 pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, header_line, hunk.header_context_col, { end_col = hunk.header_context_col + #hunk.header_context, @@ -138,15 +138,19 @@ function M.highlight_hunk(bufnr, ns, hunk, opts) local line_len = #line local prefix = line:sub(1, 1) + local is_diff_line = prefix == '+' or prefix == '-' + local line_hl = is_diff_line and (prefix == '+' and 'FugitiveTsAdd' or 'FugitiveTsDelete') + or nil + if opts.conceal_prefixes then + local virt_hl = (opts.highlights.background and line_hl) or nil pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, buf_line, 0, { - end_col = 1, - conceal = '', + virt_text = { { ' ', virt_hl } }, + virt_text_pos = 'overlay', }) end - if opts.highlights.background and (prefix == '+' or prefix == '-') then - local line_hl = prefix == '+' and 'FugitiveTsAdd' or 'FugitiveTsDelete' + if opts.highlights.background and is_diff_line then local extmark_opts = { line_hl_group = line_hl, priority = 198, diff --git a/lua/fugitive-ts/init.lua b/lua/fugitive-ts/init.lua index e3f053e..37e129c 100644 --- a/lua/fugitive-ts/init.lua +++ b/lua/fugitive-ts/init.lua @@ -1,6 +1,5 @@ ---@class fugitive-ts.Highlights ---@field treesitter boolean ----@field headers boolean ---@field background boolean ---@field linenr boolean ---@field vim boolean @@ -37,7 +36,6 @@ local default_config = { conceal_prefixes = true, highlights = { treesitter = true, - headers = true, background = true, linenr = true, vim = false, @@ -173,7 +171,6 @@ function M.setup(opts) if opts.highlights then vim.validate({ ['highlights.treesitter'] = { opts.highlights.treesitter, 'boolean', true }, - ['highlights.headers'] = { opts.highlights.headers, 'boolean', true }, ['highlights.background'] = { opts.highlights.background, 'boolean', true }, ['highlights.linenr'] = { opts.highlights.linenr, 'boolean', true }, ['highlights.vim'] = { opts.highlights.vim, 'boolean', true }, diff --git a/spec/highlight_spec.lua b/spec/highlight_spec.lua index 93c8784..fcdf8dd 100644 --- a/spec/highlight_spec.lua +++ b/spec/highlight_spec.lua @@ -35,7 +35,6 @@ describe('highlight', function() conceal_prefixes = false, highlights = { treesitter = true, - headers = false, background = false, linenr = false, vim = false, @@ -164,7 +163,7 @@ describe('highlight', function() lines = { ' local x = 1', '+local y = 2' }, } - highlight.highlight_hunk(bufnr, ns, hunk, default_opts({ highlights = { headers = true } })) + highlight.highlight_hunk(bufnr, ns, hunk, default_opts()) local extmarks = get_extmarks(bufnr) local has_header_extmark = false @@ -178,9 +177,9 @@ describe('highlight', function() delete_buffer(bufnr) end) - it('does not highlight header when disabled', function() + it('does not highlight header when no header_context', function() local bufnr = create_buffer({ - '@@ -10,3 +10,4 @@ function hello()', + '@@ -10,3 +10,4 @@', ' local x = 1', }) @@ -188,8 +187,6 @@ describe('highlight', function() filename = 'test.lua', lang = 'lua', start_line = 1, - header_context = 'function hello()', - header_context_col = 18, lines = { ' local x = 1' }, } @@ -244,7 +241,7 @@ describe('highlight', function() delete_buffer(bufnr) end) - it('applies conceal extmarks when conceal_prefixes enabled', function() + it('applies overlay extmarks when conceal_prefixes enabled', function() local bufnr = create_buffer({ '@@ -1,1 +1,2 @@', ' local x = 1', @@ -261,17 +258,17 @@ describe('highlight', function() highlight.highlight_hunk(bufnr, ns, hunk, default_opts({ conceal_prefixes = true })) local extmarks = get_extmarks(bufnr) - local conceal_count = 0 + local overlay_count = 0 for _, mark in ipairs(extmarks) do - if mark[4] and mark[4].conceal == '' then - conceal_count = conceal_count + 1 + if mark[4] and mark[4].virt_text_pos == 'overlay' then + overlay_count = overlay_count + 1 end end - assert.are.equal(2, conceal_count) + assert.are.equal(2, overlay_count) delete_buffer(bufnr) end) - it('does not apply conceal extmarks when conceal_prefixes disabled', function() + it('does not apply overlay extmarks when conceal_prefixes disabled', function() local bufnr = create_buffer({ '@@ -1,1 +1,2 @@', ' local x = 1', @@ -288,13 +285,13 @@ describe('highlight', function() highlight.highlight_hunk(bufnr, ns, hunk, default_opts({ conceal_prefixes = false })) local extmarks = get_extmarks(bufnr) - local conceal_count = 0 + local overlay_count = 0 for _, mark in ipairs(extmarks) do - if mark[4] and mark[4].conceal == '' then - conceal_count = conceal_count + 1 + if mark[4] and mark[4].virt_text_pos == 'overlay' then + overlay_count = overlay_count + 1 end end - assert.are.equal(0, conceal_count) + assert.are.equal(0, overlay_count) delete_buffer(bufnr) end) diff --git a/spec/init_spec.lua b/spec/init_spec.lua index 77c3db0..5f3b8e8 100644 --- a/spec/init_spec.lua +++ b/spec/init_spec.lua @@ -27,7 +27,6 @@ describe('fugitive-ts', function() conceal_prefixes = false, highlights = { treesitter = true, - headers = false, background = true, linenr = true, vim = false,