diff --git a/README.md b/README.md index e334426..304e3b8 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,9 @@ luarocks install diffs.nvim - **Incomplete syntax context**: Treesitter parses each diff hunk in isolation. To improve accuracy, `diffs.nvim` reads lines from disk before and after each - hunk for parsing context (controlled by `highlights.context`, default 25). - This resolves most boundary issues. Set `highlights.context = 0` to disable. + hunk for parsing context (`highlights.context`, enabled by default with 25 + lines). This resolves most boundary issues. Set + `highlights.context.enabled = false` to disable. - **Syntax flashing**: `diffs.nvim` hooks into the `FileType fugitive` event triggered by `vim-fugitive`, at which point the buffer is preliminarily diff --git a/doc/diffs.nvim.txt b/doc/diffs.nvim.txt index 22db825..e4e750b 100644 --- a/doc/diffs.nvim.txt +++ b/doc/diffs.nvim.txt @@ -56,7 +56,10 @@ Configuration is done via `vim.g.diffs`. Set this before the plugin loads: highlights = { background = true, gutter = true, - context = 25, + context = { + enabled = true, + lines = 25, + }, treesitter = { enabled = true, max_lines = 500, @@ -114,15 +117,9 @@ Configuration is done via `vim.g.diffs`. Set this before the plugin loads: Highlight line numbers with matching colors. Only visible if line numbers are enabled. - {context} (integer, default: 25) - Number of lines to read from the source file - before and after each hunk for syntax parsing - context. Improves accuracy at hunk boundaries - where incomplete constructs (e.g., a function - definition with no body) would otherwise confuse - the parser. Set to 0 to disable. Lines are read - from disk with early exit — cost scales with the - context value, not file size. + {context} (table, default: see below) + Syntax parsing context options. + See |diffs.ContextConfig| for fields. {treesitter} (table, default: see below) Treesitter highlighting options. @@ -136,6 +133,20 @@ Configuration is done via `vim.g.diffs`. Set this before the plugin loads: Character-level (intra-line) diff highlighting. See |diffs.IntraConfig| for fields. + *diffs.ContextConfig* + Context config fields: ~ + {enabled} (boolean, default: true) + Read lines from disk before and after each hunk + to provide surrounding syntax context. Improves + accuracy at hunk boundaries where incomplete + constructs (e.g., a function definition with no + body) would otherwise confuse the parser. + + {lines} (integer, default: 25) + Number of context lines to read in each + direction. Lines are read with early exit — + cost scales with this value, not file size. + *diffs.TreesitterConfig* Treesitter config fields: ~ {enabled} (boolean, default: true) @@ -318,13 +329,13 @@ Incomplete Syntax Context ~ *diffs-syntax-context* Treesitter parses each diff hunk in isolation. To provide surrounding code context, diffs.nvim reads lines from disk before and after each hunk -(controlled by `highlights.context`, default 25). This resolves most boundary +(see |diffs.ContextConfig|, enabled by default). This resolves most boundary issues where incomplete constructs (e.g., a function definition at the edge of a hunk with no body) would confuse the parser. -Set `highlights.context = 0` to disable context padding and restore the -previous behavior. In rare cases, context padding may not help if the -relevant surrounding code is very far from the hunk boundaries. +Set `highlights.context.enabled = false` to disable context padding. In rare +cases, context padding may not help if the relevant surrounding code is very +far from the hunk boundaries. Syntax Highlighting Flash ~ *diffs-flash* diff --git a/lua/diffs/highlight.lua b/lua/diffs/highlight.lua index 5107893..198231a 100644 --- a/lua/diffs/highlight.lua +++ b/lua/diffs/highlight.lua @@ -289,7 +289,8 @@ function M.highlight_hunk(bufnr, ns, hunk, opts) ---@type table local covered_lines = {} - local context = opts.highlights.context or 0 + local ctx_cfg = opts.highlights.context + local context = (ctx_cfg and ctx_cfg.enabled) and ctx_cfg.lines or 0 local leading = {} local trailing = {} if (use_ts or use_vim) and context > 0 and hunk.file_new_start and hunk.repo_root then diff --git a/lua/diffs/init.lua b/lua/diffs/init.lua index 8d8f670..4338175 100644 --- a/lua/diffs/init.lua +++ b/lua/diffs/init.lua @@ -11,10 +11,14 @@ ---@field algorithm string ---@field max_lines integer +---@class diffs.ContextConfig +---@field enabled boolean +---@field lines integer + ---@class diffs.Highlights ---@field background boolean ---@field gutter boolean ----@field context integer +---@field context diffs.ContextConfig ---@field treesitter diffs.TreesitterConfig ---@field vim diffs.VimConfig ---@field intra diffs.IntraConfig @@ -81,7 +85,10 @@ local default_config = { highlights = { background = true, gutter = true, - context = 25, + context = { + enabled = true, + lines = 25, + }, treesitter = { enabled = true, max_lines = 500, @@ -233,12 +240,19 @@ local function init() vim.validate({ ['highlights.background'] = { opts.highlights.background, 'boolean', true }, ['highlights.gutter'] = { opts.highlights.gutter, 'boolean', true }, - ['highlights.context'] = { opts.highlights.context, 'number', true }, + ['highlights.context'] = { opts.highlights.context, 'table', 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.context then + vim.validate({ + ['highlights.context.enabled'] = { opts.highlights.context.enabled, 'boolean', true }, + ['highlights.context.lines'] = { opts.highlights.context.lines, 'number', true }, + }) + end + if opts.highlights.treesitter then vim.validate({ ['highlights.treesitter.enabled'] = { opts.highlights.treesitter.enabled, 'boolean', true }, @@ -294,8 +308,13 @@ local function init() if opts.debounce_ms and opts.debounce_ms < 0 then error('diffs: debounce_ms must be >= 0') end - if opts.highlights and opts.highlights.context and opts.highlights.context < 0 then - error('diffs: highlights.context must be >= 0') + if + opts.highlights + and opts.highlights.context + and opts.highlights.context.lines + and opts.highlights.context.lines < 0 + then + error('diffs: highlights.context.lines must be >= 0') end if opts.highlights diff --git a/spec/highlight_spec.lua b/spec/highlight_spec.lua index a556228..eee6d32 100644 --- a/spec/highlight_spec.lua +++ b/spec/highlight_spec.lua @@ -37,7 +37,7 @@ describe('highlight', function() highlights = { background = false, gutter = false, - context = 0, + context = { enabled = false, lines = 0 }, treesitter = { enabled = true, max_lines = 500, @@ -1087,7 +1087,12 @@ describe('highlight', function() repo_root = repo_root, } - highlight.highlight_hunk(bufnr, ns, hunk, default_opts({ highlights = { context = 25 } })) + highlight.highlight_hunk( + bufnr, + ns, + hunk, + default_opts({ highlights = { context = { enabled = true, lines = 25 } } }) + ) local extmarks = get_extmarks(bufnr) for _, mark in ipairs(extmarks) do @@ -1100,7 +1105,7 @@ describe('highlight', function() vim.fn.delete(repo_root, 'rf') end) - it('context = 0 matches behavior without padding', function() + it('context disabled matches behavior without padding', function() local bufnr = create_buffer({ '@@ -1,1 +1,2 @@', ' local x = 1', @@ -1117,7 +1122,12 @@ describe('highlight', function() repo_root = '/nonexistent', } - highlight.highlight_hunk(bufnr, ns, hunk, default_opts({ highlights = { context = 0 } })) + highlight.highlight_hunk( + bufnr, + ns, + hunk, + default_opts({ highlights = { context = { enabled = false, lines = 0 } } }) + ) local extmarks = get_extmarks(bufnr) assert.is_true(#extmarks > 0) @@ -1142,7 +1152,12 @@ describe('highlight', function() } assert.has_no.errors(function() - highlight.highlight_hunk(bufnr, ns, hunk, default_opts({ highlights = { context = 25 } })) + highlight.highlight_hunk( + bufnr, + ns, + hunk, + default_opts({ highlights = { context = { enabled = true, lines = 25 } } }) + ) end) local extmarks = get_extmarks(bufnr) @@ -1180,7 +1195,7 @@ describe('highlight', function() highlights = { background = false, gutter = false, - context = 0, + context = { enabled = false, lines = 0 }, treesitter = { enabled = true, max_lines = 500 }, vim = { enabled = false, max_lines = 200 }, }, @@ -1337,7 +1352,7 @@ describe('highlight', function() highlights = { background = false, gutter = false, - context = 0, + context = { enabled = false, lines = 0 }, treesitter = { enabled = true, max_lines = 500 }, vim = { enabled = false, max_lines = 200 }, },