diff --git a/README.md b/README.md index f0a04a8..ca3d72e 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ syntax highlighting. - Vim syntax fallback for languages without a treesitter parser - Hunk header context highlighting (`@@ ... @@ function foo()`) - Character-level (intra-line) diff highlighting for changed characters -- Inline merge conflict detection, highlighting, and resolution keymaps - Configurable debouncing, max lines, diff prefix concealment, blend alpha, and highlight overrides @@ -64,8 +63,7 @@ luarocks install diffs.nvim compatible, but both plugins modifying line highlights may produce unexpected results - [`git-conflict.nvim`](https://github.com/akinsho/git-conflict.nvim) - - `diffs.nvim` now includes built-in conflict resolution; disable one or the - other to avoid overlap + conflict marker highlighting may overlap with `diffs.nvim` # Acknowledgements diff --git a/doc/diffs.nvim.txt b/doc/diffs.nvim.txt index 7663150..028d8ba 100644 --- a/doc/diffs.nvim.txt +++ b/doc/diffs.nvim.txt @@ -280,41 +280,6 @@ Example configuration: >lua vim.keymap.set('n', 'gD', '(diffs-gvdiff)') < - *(diffs-conflict-ours)* -(diffs-conflict-ours) - Accept current (ours) change. Replaces the - conflict block with ours content. - - *(diffs-conflict-theirs)* -(diffs-conflict-theirs) - Accept incoming (theirs) change. Replaces the - conflict block with theirs content. - - *(diffs-conflict-both)* -(diffs-conflict-both) - Accept both changes (ours then theirs). - - *(diffs-conflict-none)* -(diffs-conflict-none) - Reject both changes (delete entire block). - - *(diffs-conflict-next)* -(diffs-conflict-next) - Jump to next conflict marker. Wraps around. - - *(diffs-conflict-prev)* -(diffs-conflict-prev) - Jump to previous conflict marker. Wraps around. - -Example configuration: >lua - vim.keymap.set('n', 'co', '(diffs-conflict-ours)') - vim.keymap.set('n', 'ct', '(diffs-conflict-theirs)') - vim.keymap.set('n', 'cb', '(diffs-conflict-both)') - vim.keymap.set('n', 'cn', '(diffs-conflict-none)') - vim.keymap.set('n', ']x', '(diffs-conflict-next)') - vim.keymap.set('n', '[x', '(diffs-conflict-prev)') -< - Diff buffer mappings: ~ *diffs-q* q Close the diff window. Available in all `diffs://` diff --git a/lua/diffs/conflict.lua b/lua/diffs/conflict.lua index 9e62a15..84cc2fa 100644 --- a/lua/diffs/conflict.lua +++ b/lua/diffs/conflict.lua @@ -107,8 +107,15 @@ local function apply_highlights(bufnr, regions, config) }) if config.show_virtual_text then + local ours_line = vim.api.nvim_buf_get_lines( + bufnr, + region.marker_ours, + region.marker_ours + 1, + false + )[1] or '' + local ours_name = ours_line:match('^<<<<<<<%s+(.+)$') or '' pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_ours, 0, { - virt_text = { { ' (current)', 'DiffsConflictMarker' } }, + virt_text = { { ' ' .. ours_name .. ' (current)', 'DiffsConflictMarker' } }, virt_text_pos = 'eol', }) end @@ -176,8 +183,15 @@ local function apply_highlights(bufnr, regions, config) }) if config.show_virtual_text then + local theirs_line = vim.api.nvim_buf_get_lines( + bufnr, + region.marker_theirs, + region.marker_theirs + 1, + false + )[1] or '' + local theirs_name = theirs_line:match('^>>>>>>>%s+(.+)$') or '' pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_theirs, 0, { - virt_text = { { ' (incoming)', 'DiffsConflictMarker' } }, + virt_text = { { ' ' .. theirs_name .. ' (incoming)', 'DiffsConflictMarker' } }, virt_text_pos = 'eol', }) end @@ -214,20 +228,11 @@ end local function refresh(bufnr, config) local regions = parse_buffer(bufnr) if #regions == 0 then - vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1) - if diagnostics_suppressed[bufnr] then - pcall(vim.diagnostic.reset, nil, bufnr) - pcall(vim.diagnostic.enable, true, { bufnr = bufnr }) - diagnostics_suppressed[bufnr] = nil - end + M.detach(bufnr) vim.api.nvim_exec_autocmds('User', { pattern = 'DiffsConflictResolved' }) return end apply_highlights(bufnr, regions, config) - if config.disable_diagnostics and not diagnostics_suppressed[bufnr] then - pcall(vim.diagnostic.enable, false, { bufnr = bufnr }) - diagnostics_suppressed[bufnr] = true - end end ---@param bufnr integer @@ -348,19 +353,35 @@ end local function setup_keymaps(bufnr, config) local km = config.keymaps - local maps = { - { km.ours, '(diffs-conflict-ours)' }, - { km.theirs, '(diffs-conflict-theirs)' }, - { km.both, '(diffs-conflict-both)' }, - { km.none, '(diffs-conflict-none)' }, - { km.next, '(diffs-conflict-next)' }, - { km.prev, '(diffs-conflict-prev)' }, - } - - for _, map in ipairs(maps) do - if map[1] then - vim.keymap.set('n', map[1], map[2], { buffer = bufnr }) - end + if km.ours then + vim.keymap.set('n', km.ours, function() + M.resolve_ours(bufnr, config) + end, { buffer = bufnr }) + end + if km.theirs then + vim.keymap.set('n', km.theirs, function() + M.resolve_theirs(bufnr, config) + end, { buffer = bufnr }) + end + if km.both then + vim.keymap.set('n', km.both, function() + M.resolve_both(bufnr, config) + end, { buffer = bufnr }) + end + if km.none then + vim.keymap.set('n', km.none, function() + M.resolve_none(bufnr, config) + end, { buffer = bufnr }) + end + if km.next then + vim.keymap.set('n', km.next, function() + M.goto_next(bufnr) + end, { buffer = bufnr }) + end + if km.prev then + vim.keymap.set('n', km.prev, function() + M.goto_prev(bufnr) + end, { buffer = bufnr }) end end @@ -370,7 +391,6 @@ function M.detach(bufnr) attached_buffers[bufnr] = nil if diagnostics_suppressed[bufnr] then - pcall(vim.diagnostic.reset, nil, bufnr) pcall(vim.diagnostic.enable, true, { bufnr = bufnr }) diagnostics_suppressed[bufnr] = nil end diff --git a/plugin/diffs.lua b/plugin/diffs.lua index 5d3c8b2..e4fc690 100644 --- a/plugin/diffs.lua +++ b/plugin/diffs.lua @@ -57,28 +57,3 @@ end, { desc = 'Unified diff (horizontal)' }) vim.keymap.set('n', '(diffs-gvdiff)', function() cmds.gdiff(nil, true) end, { desc = 'Unified diff (vertical)' }) - -local function conflict_action(fn) - local bufnr = vim.api.nvim_get_current_buf() - local config = require('diffs').get_conflict_config() - fn(bufnr, config) -end - -vim.keymap.set('n', '(diffs-conflict-ours)', function() - conflict_action(require('diffs.conflict').resolve_ours) -end, { desc = 'Accept current (ours) change' }) -vim.keymap.set('n', '(diffs-conflict-theirs)', function() - conflict_action(require('diffs.conflict').resolve_theirs) -end, { desc = 'Accept incoming (theirs) change' }) -vim.keymap.set('n', '(diffs-conflict-both)', function() - conflict_action(require('diffs.conflict').resolve_both) -end, { desc = 'Accept both changes' }) -vim.keymap.set('n', '(diffs-conflict-none)', function() - conflict_action(require('diffs.conflict').resolve_none) -end, { desc = 'Reject both changes' }) -vim.keymap.set('n', '(diffs-conflict-next)', function() - require('diffs.conflict').goto_next(vim.api.nvim_get_current_buf()) -end, { desc = 'Jump to next conflict' }) -vim.keymap.set('n', '(diffs-conflict-prev)', function() - require('diffs.conflict').goto_prev(vim.api.nvim_get_current_buf()) -end, { desc = 'Jump to previous conflict' }) diff --git a/spec/conflict_spec.lua b/spec/conflict_spec.lua index 75eac23..128c567 100644 --- a/spec/conflict_spec.lua +++ b/spec/conflict_spec.lua @@ -631,39 +631,6 @@ describe('conflict', function() helpers.delete_buffer(bufnr) end) - it('re-highlights when markers return after resolution', function() - local bufnr = create_file_buffer({ - '<<<<<<< HEAD', - 'local x = 1', - '=======', - 'local x = 2', - '>>>>>>> feature', - }) - vim.api.nvim_set_current_buf(bufnr) - local cfg = default_config() - conflict.attach(bufnr, cfg) - - assert.is_true(#get_extmarks(bufnr) > 0) - - vim.api.nvim_win_set_cursor(0, { 2, 0 }) - conflict.resolve_ours(bufnr, cfg) - assert.are.equal(0, #get_extmarks(bufnr)) - - vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { - '<<<<<<< HEAD', - 'local x = 1', - '=======', - 'local x = 2', - '>>>>>>> feature', - }) - vim.api.nvim_exec_autocmds('TextChanged', { buffer = bufnr }) - - assert.is_true(#get_extmarks(bufnr) > 0) - - conflict.detach(bufnr) - helpers.delete_buffer(bufnr) - end) - it('detaches after last conflict resolved', function() local bufnr = create_file_buffer({ '<<<<<<< HEAD',