Compare commits
No commits in common. "2834b588f113750dd5ed3bd0b7fa875a1ddb635f" and "a2053a132bc0cccf5ab7d9247c047ea90beddd9d" have entirely different histories.
2834b588f1
...
a2053a132b
10 changed files with 37 additions and 377 deletions
18
README.md
18
README.md
|
|
@ -9,12 +9,18 @@ syntax highlighting.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Treesitter syntax highlighting in fugitive diffs and commit views
|
- Treesitter syntax highlighting in `:Git` diffs and commit views
|
||||||
- Character-level intra-line diff highlighting
|
- Diff header highlighting (`diff --git`, `index`, `---`, `+++`)
|
||||||
- `:Gdiff` unified diff against any revision
|
- `:Gdiffsplit` / `:Gvdiffsplit` syntax through diff backgrounds
|
||||||
- Background-only diff colors for `&diff` buffers
|
- `:Gdiff` unified diff against any git revision with syntax highlighting
|
||||||
- Inline merge conflict detection, highlighting, and resolution
|
- Fugitive status buffer keymaps (`du`/`dU`) for unified diffs
|
||||||
- Vim syntax fallback, context padding, configurable blend/debounce
|
- Background-only diff colors for any `&diff` buffer (`:diffthis`, `vimdiff`)
|
||||||
|
- 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
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,6 @@ Configuration is done via `vim.g.diffs`. Set this before the plugin loads:
|
||||||
enabled = true,
|
enabled = true,
|
||||||
disable_diagnostics = true,
|
disable_diagnostics = true,
|
||||||
show_virtual_text = true,
|
show_virtual_text = true,
|
||||||
show_actions = false,
|
|
||||||
keymaps = {
|
keymaps = {
|
||||||
ours = 'doo',
|
ours = 'doo',
|
||||||
theirs = 'dot',
|
theirs = 'dot',
|
||||||
|
|
@ -417,7 +416,6 @@ Configuration: ~
|
||||||
enabled = true,
|
enabled = true,
|
||||||
disable_diagnostics = true,
|
disable_diagnostics = true,
|
||||||
show_virtual_text = true,
|
show_virtual_text = true,
|
||||||
show_actions = false,
|
|
||||||
keymaps = {
|
keymaps = {
|
||||||
ours = 'doo',
|
ours = 'doo',
|
||||||
theirs = 'dot',
|
theirs = 'dot',
|
||||||
|
|
@ -444,32 +442,9 @@ Configuration: ~
|
||||||
diagnostics alone.
|
diagnostics alone.
|
||||||
|
|
||||||
{show_virtual_text} (boolean, default: true)
|
{show_virtual_text} (boolean, default: true)
|
||||||
Show `(current)` and `(incoming)` labels at
|
Show virtual text labels (" current" and
|
||||||
the end of `<<<<<<<` and `>>>>>>>` marker
|
" incoming") at the end of `<<<<<<<` and
|
||||||
lines. Also controls hunk hints in merge
|
`>>>>>>>` marker lines.
|
||||||
diff views.
|
|
||||||
|
|
||||||
{format_virtual_text} (function|nil, default: nil)
|
|
||||||
Custom formatter for virtual text labels.
|
|
||||||
Receives `(side, keymap)` where `side` is
|
|
||||||
`"ours"` or `"theirs"` and `keymap` is the
|
|
||||||
configured keymap string or `false`. Return
|
|
||||||
a string (label text without parens) or
|
|
||||||
`nil` to hide the label. Example: >lua
|
|
||||||
format_virtual_text = function(side, keymap)
|
|
||||||
if keymap then
|
|
||||||
return side .. ' [' .. keymap .. ']'
|
|
||||||
end
|
|
||||||
return side
|
|
||||||
end
|
|
||||||
<
|
|
||||||
|
|
||||||
{show_actions} (boolean, default: false)
|
|
||||||
Show a codelens-style action line above each
|
|
||||||
`<<<<<<<` marker listing available resolution
|
|
||||||
keymaps. Renders as virtual lines using the
|
|
||||||
`DiffsConflictActions` highlight group.
|
|
||||||
Only keymaps that are not `false` appear.
|
|
||||||
|
|
||||||
{keymaps} (table, default: see above)
|
{keymaps} (table, default: see above)
|
||||||
Buffer-local keymaps for conflict resolution
|
Buffer-local keymaps for conflict resolution
|
||||||
|
|
@ -712,10 +687,6 @@ Conflict highlights: ~
|
||||||
*DiffsConflictBaseNr*
|
*DiffsConflictBaseNr*
|
||||||
DiffsConflictBaseNr Line number for base content lines (diff3).
|
DiffsConflictBaseNr Line number for base content lines (diff3).
|
||||||
|
|
||||||
*DiffsConflictActions*
|
|
||||||
DiffsConflictActions Dimmed foreground (no bold) for the codelens-style
|
|
||||||
action line shown when `show_actions` is true.
|
|
||||||
|
|
||||||
Diff mode window highlights: ~
|
Diff mode window highlights: ~
|
||||||
These are used for |winhighlight| remapping in `&diff` windows.
|
These are used for |winhighlight| remapping in `&diff` windows.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,17 +92,6 @@ local function parse_buffer(bufnr)
|
||||||
return M.parse(lines)
|
return M.parse(lines)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param side string
|
|
||||||
---@param config diffs.ConflictConfig
|
|
||||||
---@return string?
|
|
||||||
local function get_virtual_text_label(side, config)
|
|
||||||
if config.format_virtual_text then
|
|
||||||
local keymap = side == 'ours' and config.keymaps.ours or config.keymaps.theirs
|
|
||||||
return config.format_virtual_text(side, keymap)
|
|
||||||
end
|
|
||||||
return side == 'ours' and 'current' or 'incoming'
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param bufnr integer
|
---@param bufnr integer
|
||||||
---@param regions diffs.ConflictRegion[]
|
---@param regions diffs.ConflictRegion[]
|
||||||
---@param config diffs.ConflictConfig
|
---@param config diffs.ConflictConfig
|
||||||
|
|
@ -118,37 +107,10 @@ local function apply_highlights(bufnr, regions, config)
|
||||||
})
|
})
|
||||||
|
|
||||||
if config.show_virtual_text then
|
if config.show_virtual_text then
|
||||||
local ours_label = get_virtual_text_label('ours', config)
|
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_ours, 0, {
|
||||||
if ours_label then
|
virt_text = { { ' (current)', 'DiffsConflictMarker' } },
|
||||||
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_ours, 0, {
|
virt_text_pos = 'eol',
|
||||||
virt_text = { { ' (' .. ours_label .. ')', 'DiffsConflictMarker' } },
|
})
|
||||||
virt_text_pos = 'eol',
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if config.show_actions then
|
|
||||||
local parts = {}
|
|
||||||
local actions = {
|
|
||||||
{ 'Current', config.keymaps.ours },
|
|
||||||
{ 'Incoming', config.keymaps.theirs },
|
|
||||||
{ 'Both', config.keymaps.both },
|
|
||||||
{ 'None', config.keymaps.none },
|
|
||||||
}
|
|
||||||
for _, action in ipairs(actions) do
|
|
||||||
if action[2] then
|
|
||||||
if #parts > 0 then
|
|
||||||
table.insert(parts, { ' \226\148\130 ', 'DiffsConflictActions' })
|
|
||||||
end
|
|
||||||
table.insert(parts, { ('%s (%s)'):format(action[1], action[2]), 'DiffsConflictActions' })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #parts > 0 then
|
|
||||||
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_ours, 0, {
|
|
||||||
virt_lines = { parts },
|
|
||||||
virt_lines_above = true,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
for line = region.ours_start, region.ours_end - 1 do
|
for line = region.ours_start, region.ours_end - 1 do
|
||||||
|
|
@ -214,13 +176,10 @@ local function apply_highlights(bufnr, regions, config)
|
||||||
})
|
})
|
||||||
|
|
||||||
if config.show_virtual_text then
|
if config.show_virtual_text then
|
||||||
local theirs_label = get_virtual_text_label('theirs', config)
|
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_theirs, 0, {
|
||||||
if theirs_label then
|
virt_text = { { ' (incoming)', 'DiffsConflictMarker' } },
|
||||||
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_theirs, 0, {
|
virt_text_pos = 'eol',
|
||||||
virt_text = { { ' (' .. theirs_label .. ')', 'DiffsConflictMarker' } },
|
})
|
||||||
virt_text_pos = 'eol',
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,13 @@
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local repo_root_cache = {}
|
|
||||||
|
|
||||||
---@param filepath string
|
---@param filepath string
|
||||||
---@return string?
|
---@return string?
|
||||||
function M.get_repo_root(filepath)
|
function M.get_repo_root(filepath)
|
||||||
local dir = vim.fn.fnamemodify(filepath, ':h')
|
local dir = vim.fn.fnamemodify(filepath, ':h')
|
||||||
if repo_root_cache[dir] ~= nil then
|
|
||||||
return repo_root_cache[dir]
|
|
||||||
end
|
|
||||||
local result = vim.fn.systemlist({ 'git', '-C', dir, 'rev-parse', '--show-toplevel' })
|
local result = vim.fn.systemlist({ 'git', '-C', dir, 'rev-parse', '--show-toplevel' })
|
||||||
if vim.v.shell_error ~= 0 then
|
if vim.v.shell_error ~= 0 then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
repo_root_cache[dir] = result[1]
|
|
||||||
return result[1]
|
return result[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,7 @@ local function highlight_vim_syntax(bufnr, ns, hunk, code_lines, covered_lines,
|
||||||
|
|
||||||
local spans = {}
|
local spans = {}
|
||||||
|
|
||||||
pcall(vim.api.nvim_buf_call, scratch, function()
|
vim.api.nvim_buf_call(scratch, function()
|
||||||
vim.cmd('setlocal syntax=' .. ft)
|
vim.cmd('setlocal syntax=' .. ft)
|
||||||
vim.cmd('redraw')
|
vim.cmd('redraw')
|
||||||
|
|
||||||
|
|
@ -256,7 +256,7 @@ local function highlight_vim_syntax(bufnr, ns, hunk, code_lines, covered_lines,
|
||||||
spans = M.coalesce_syntax_spans(query_fn, code_lines)
|
spans = M.coalesce_syntax_spans(query_fn, code_lines)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
pcall(vim.api.nvim_buf_delete, scratch, { force = true })
|
vim.api.nvim_buf_delete(scratch, { force = true })
|
||||||
|
|
||||||
local hunk_line_count = #hunk.lines
|
local hunk_line_count = #hunk.lines
|
||||||
local extmark_count = 0
|
local extmark_count = 0
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,6 @@
|
||||||
---@field enabled boolean
|
---@field enabled boolean
|
||||||
---@field disable_diagnostics boolean
|
---@field disable_diagnostics boolean
|
||||||
---@field show_virtual_text boolean
|
---@field show_virtual_text boolean
|
||||||
---@field format_virtual_text? fun(side: string, keymap: string|false): string?
|
|
||||||
---@field show_actions boolean
|
|
||||||
---@field keymaps diffs.ConflictKeymaps
|
---@field keymaps diffs.ConflictKeymaps
|
||||||
|
|
||||||
---@class diffs.Config
|
---@class diffs.Config
|
||||||
|
|
@ -130,7 +128,6 @@ local default_config = {
|
||||||
enabled = true,
|
enabled = true,
|
||||||
disable_diagnostics = true,
|
disable_diagnostics = true,
|
||||||
show_virtual_text = true,
|
show_virtual_text = true,
|
||||||
show_actions = false,
|
|
||||||
keymaps = {
|
keymaps = {
|
||||||
ours = 'doo',
|
ours = 'doo',
|
||||||
theirs = 'dot',
|
theirs = 'dot',
|
||||||
|
|
@ -203,9 +200,7 @@ local function create_debounced_highlight(bufnr)
|
||||||
timer = nil
|
timer = nil
|
||||||
t:close()
|
t:close()
|
||||||
end
|
end
|
||||||
if vim.api.nvim_buf_is_valid(bufnr) then
|
highlight_buffer(bufnr)
|
||||||
highlight_buffer(bufnr)
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
@ -279,7 +274,6 @@ local function compute_highlight_groups()
|
||||||
vim.api.nvim_set_hl(0, 'DiffsConflictTheirs', { default = true, bg = blended_theirs })
|
vim.api.nvim_set_hl(0, 'DiffsConflictTheirs', { default = true, bg = blended_theirs })
|
||||||
vim.api.nvim_set_hl(0, 'DiffsConflictBase', { default = true, bg = blended_base })
|
vim.api.nvim_set_hl(0, 'DiffsConflictBase', { default = true, bg = blended_base })
|
||||||
vim.api.nvim_set_hl(0, 'DiffsConflictMarker', { default = true, fg = 0x808080, bold = true })
|
vim.api.nvim_set_hl(0, 'DiffsConflictMarker', { default = true, fg = 0x808080, bold = true })
|
||||||
vim.api.nvim_set_hl(0, 'DiffsConflictActions', { default = true, fg = 0x808080 })
|
|
||||||
vim.api.nvim_set_hl(
|
vim.api.nvim_set_hl(
|
||||||
0,
|
0,
|
||||||
'DiffsConflictOursNr',
|
'DiffsConflictOursNr',
|
||||||
|
|
@ -394,8 +388,6 @@ local function init()
|
||||||
['conflict.enabled'] = { opts.conflict.enabled, 'boolean', true },
|
['conflict.enabled'] = { opts.conflict.enabled, 'boolean', true },
|
||||||
['conflict.disable_diagnostics'] = { opts.conflict.disable_diagnostics, 'boolean', true },
|
['conflict.disable_diagnostics'] = { opts.conflict.disable_diagnostics, 'boolean', true },
|
||||||
['conflict.show_virtual_text'] = { opts.conflict.show_virtual_text, 'boolean', true },
|
['conflict.show_virtual_text'] = { opts.conflict.show_virtual_text, 'boolean', true },
|
||||||
['conflict.format_virtual_text'] = { opts.conflict.format_virtual_text, 'function', true },
|
|
||||||
['conflict.show_actions'] = { opts.conflict.show_actions, 'boolean', true },
|
|
||||||
['conflict.keymaps'] = { opts.conflict.keymaps, 'table', true },
|
['conflict.keymaps'] = { opts.conflict.keymaps, 'table', true },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,6 @@ local cached_handle = nil
|
||||||
---@type boolean
|
---@type boolean
|
||||||
local download_in_progress = false
|
local download_in_progress = false
|
||||||
|
|
||||||
---@type fun(handle: table?)[]
|
|
||||||
local pending_callbacks = {}
|
|
||||||
|
|
||||||
---@return string
|
---@return string
|
||||||
local function get_os()
|
local function get_os()
|
||||||
local os_name = jit.os:lower()
|
local os_name = jit.os:lower()
|
||||||
|
|
@ -167,10 +164,9 @@ function M.ensure(callback)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(pending_callbacks, callback)
|
|
||||||
|
|
||||||
if download_in_progress then
|
if download_in_progress then
|
||||||
dbg('download already in progress, queued callback')
|
dbg('download already in progress')
|
||||||
|
callback(nil)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -196,25 +192,21 @@ function M.ensure(callback)
|
||||||
vim.system(cmd, {}, function(result)
|
vim.system(cmd, {}, function(result)
|
||||||
download_in_progress = false
|
download_in_progress = false
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
local handle = nil
|
|
||||||
if result.code ~= 0 then
|
if result.code ~= 0 then
|
||||||
vim.notify('[diffs] failed to download libvscode_diff', vim.log.levels.WARN)
|
vim.notify('[diffs] failed to download libvscode_diff', vim.log.levels.WARN)
|
||||||
dbg('curl failed: %s', result.stderr or '')
|
dbg('curl failed: %s', result.stderr or '')
|
||||||
else
|
callback(nil)
|
||||||
local f = io.open(version_path(), 'w')
|
return
|
||||||
if f then
|
|
||||||
f:write(EXPECTED_VERSION)
|
|
||||||
f:close()
|
|
||||||
end
|
|
||||||
vim.notify('[diffs] libvscode_diff downloaded', vim.log.levels.INFO)
|
|
||||||
handle = M.load()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local cbs = pending_callbacks
|
local f = io.open(version_path(), 'w')
|
||||||
pending_callbacks = {}
|
if f then
|
||||||
for _, cb in ipairs(cbs) do
|
f:write(EXPECTED_VERSION)
|
||||||
cb(handle)
|
f:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
vim.notify('[diffs] libvscode_diff downloaded', vim.log.levels.INFO)
|
||||||
|
callback(M.load())
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -338,43 +338,6 @@ function M.goto_prev(bufnr)
|
||||||
vim.api.nvim_win_set_cursor(0, { candidates[#candidates].start_line + 1, 0 })
|
vim.api.nvim_win_set_cursor(0, { candidates[#candidates].start_line + 1, 0 })
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param bufnr integer
|
|
||||||
---@param config diffs.ConflictConfig
|
|
||||||
local function apply_hunk_hints(bufnr, config)
|
|
||||||
if not config.show_virtual_text then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local hunks = M.parse_hunks(bufnr)
|
|
||||||
for _, hunk in ipairs(hunks) do
|
|
||||||
if M.is_resolved(bufnr, hunk.index) then
|
|
||||||
add_resolved_virtual_text(bufnr, hunk)
|
|
||||||
else
|
|
||||||
local parts = {}
|
|
||||||
local actions = {
|
|
||||||
{ 'current', config.keymaps.ours },
|
|
||||||
{ 'incoming', config.keymaps.theirs },
|
|
||||||
{ 'both', config.keymaps.both },
|
|
||||||
{ 'none', config.keymaps.none },
|
|
||||||
}
|
|
||||||
for _, action in ipairs(actions) do
|
|
||||||
if action[2] then
|
|
||||||
if #parts > 0 then
|
|
||||||
table.insert(parts, { ' | ', 'Comment' })
|
|
||||||
end
|
|
||||||
table.insert(parts, { ('%s: %s'):format(action[2], action[1]), 'Comment' })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #parts > 0 then
|
|
||||||
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, hunk.start_line, 0, {
|
|
||||||
virt_text = parts,
|
|
||||||
virt_text_pos = 'eol',
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param bufnr integer
|
---@param bufnr integer
|
||||||
---@param config diffs.ConflictConfig
|
---@param config diffs.ConflictConfig
|
||||||
function M.setup_keymaps(bufnr, config)
|
function M.setup_keymaps(bufnr, config)
|
||||||
|
|
@ -395,8 +358,6 @@ function M.setup_keymaps(bufnr, config)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
apply_hunk_hints(bufnr, config)
|
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd('BufWipeout', {
|
vim.api.nvim_create_autocmd('BufWipeout', {
|
||||||
buffer = bufnr,
|
buffer = bufnr,
|
||||||
callback = function()
|
callback = function()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ local function default_config(overrides)
|
||||||
enabled = true,
|
enabled = true,
|
||||||
disable_diagnostics = false,
|
disable_diagnostics = false,
|
||||||
show_virtual_text = true,
|
show_virtual_text = true,
|
||||||
show_actions = false,
|
|
||||||
keymaps = {
|
keymaps = {
|
||||||
ours = 'doo',
|
ours = 'doo',
|
||||||
theirs = 'dot',
|
theirs = 'dot',
|
||||||
|
|
@ -686,158 +685,4 @@ describe('conflict', function()
|
||||||
helpers.delete_buffer(bufnr)
|
helpers.delete_buffer(bufnr)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('virtual text formatting', function()
|
|
||||||
after_each(function()
|
|
||||||
conflict.detach(vim.api.nvim_get_current_buf())
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('default labels show current and incoming without keymaps', function()
|
|
||||||
local bufnr = create_file_buffer({
|
|
||||||
'<<<<<<< HEAD',
|
|
||||||
'local x = 1',
|
|
||||||
'=======',
|
|
||||||
'local x = 2',
|
|
||||||
'>>>>>>> feature',
|
|
||||||
})
|
|
||||||
|
|
||||||
conflict.attach(bufnr, default_config())
|
|
||||||
|
|
||||||
local extmarks = get_extmarks(bufnr)
|
|
||||||
local labels = {}
|
|
||||||
for _, mark in ipairs(extmarks) do
|
|
||||||
if mark[4] and mark[4].virt_text then
|
|
||||||
table.insert(labels, mark[4].virt_text[1][1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assert.are.equal(2, #labels)
|
|
||||||
assert.are.equal(' (current)', labels[1])
|
|
||||||
assert.are.equal(' (incoming)', labels[2])
|
|
||||||
|
|
||||||
helpers.delete_buffer(bufnr)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('uses custom format_virtual_text function', function()
|
|
||||||
local bufnr = create_file_buffer({
|
|
||||||
'<<<<<<< HEAD',
|
|
||||||
'local x = 1',
|
|
||||||
'=======',
|
|
||||||
'local x = 2',
|
|
||||||
'>>>>>>> feature',
|
|
||||||
})
|
|
||||||
|
|
||||||
conflict.attach(
|
|
||||||
bufnr,
|
|
||||||
default_config({
|
|
||||||
format_virtual_text = function(side)
|
|
||||||
return side == 'ours' and 'OURS' or 'THEIRS'
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
local extmarks = get_extmarks(bufnr)
|
|
||||||
local labels = {}
|
|
||||||
for _, mark in ipairs(extmarks) do
|
|
||||||
if mark[4] and mark[4].virt_text then
|
|
||||||
table.insert(labels, mark[4].virt_text[1][1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assert.are.equal(2, #labels)
|
|
||||||
assert.are.equal(' (OURS)', labels[1])
|
|
||||||
assert.are.equal(' (THEIRS)', labels[2])
|
|
||||||
|
|
||||||
helpers.delete_buffer(bufnr)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('hides label when format_virtual_text returns nil', function()
|
|
||||||
local bufnr = create_file_buffer({
|
|
||||||
'<<<<<<< HEAD',
|
|
||||||
'local x = 1',
|
|
||||||
'=======',
|
|
||||||
'local x = 2',
|
|
||||||
'>>>>>>> feature',
|
|
||||||
})
|
|
||||||
|
|
||||||
conflict.attach(
|
|
||||||
bufnr,
|
|
||||||
default_config({
|
|
||||||
format_virtual_text = function()
|
|
||||||
return nil
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
local extmarks = get_extmarks(bufnr)
|
|
||||||
local virt_text_count = 0
|
|
||||||
for _, mark in ipairs(extmarks) do
|
|
||||||
if mark[4] and mark[4].virt_text then
|
|
||||||
virt_text_count = virt_text_count + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assert.are.equal(0, virt_text_count)
|
|
||||||
|
|
||||||
helpers.delete_buffer(bufnr)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
describe('action lines', function()
|
|
||||||
after_each(function()
|
|
||||||
conflict.detach(vim.api.nvim_get_current_buf())
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('adds virt_lines when show_actions is true', function()
|
|
||||||
local bufnr = create_file_buffer({
|
|
||||||
'<<<<<<< HEAD',
|
|
||||||
'local x = 1',
|
|
||||||
'=======',
|
|
||||||
'local x = 2',
|
|
||||||
'>>>>>>> feature',
|
|
||||||
})
|
|
||||||
|
|
||||||
conflict.attach(bufnr, default_config({ show_actions = true }))
|
|
||||||
|
|
||||||
local extmarks = get_extmarks(bufnr)
|
|
||||||
local virt_lines_count = 0
|
|
||||||
for _, mark in ipairs(extmarks) do
|
|
||||||
if mark[4] and mark[4].virt_lines then
|
|
||||||
virt_lines_count = virt_lines_count + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assert.are.equal(1, virt_lines_count)
|
|
||||||
|
|
||||||
helpers.delete_buffer(bufnr)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('omits disabled keymaps from action line', function()
|
|
||||||
local bufnr = create_file_buffer({
|
|
||||||
'<<<<<<< HEAD',
|
|
||||||
'local x = 1',
|
|
||||||
'=======',
|
|
||||||
'local x = 2',
|
|
||||||
'>>>>>>> feature',
|
|
||||||
})
|
|
||||||
|
|
||||||
conflict.attach(
|
|
||||||
bufnr,
|
|
||||||
default_config({ show_actions = true, keymaps = { both = false, none = false } })
|
|
||||||
)
|
|
||||||
|
|
||||||
local extmarks = get_extmarks(bufnr)
|
|
||||||
for _, mark in ipairs(extmarks) do
|
|
||||||
if mark[4] and mark[4].virt_lines then
|
|
||||||
local line = mark[4].virt_lines[1]
|
|
||||||
local text = ''
|
|
||||||
for _, chunk in ipairs(line) do
|
|
||||||
text = text .. chunk[1]
|
|
||||||
end
|
|
||||||
assert.is_truthy(text:find('Current'))
|
|
||||||
assert.is_truthy(text:find('Incoming'))
|
|
||||||
assert.is_falsy(text:find('Both'))
|
|
||||||
assert.is_falsy(text:find('None'))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers.delete_buffer(bufnr)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
end)
|
end)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ local function default_config(overrides)
|
||||||
enabled = true,
|
enabled = true,
|
||||||
disable_diagnostics = false,
|
disable_diagnostics = false,
|
||||||
show_virtual_text = true,
|
show_virtual_text = true,
|
||||||
show_actions = false,
|
|
||||||
keymaps = {
|
keymaps = {
|
||||||
ours = 'doo',
|
ours = 'doo',
|
||||||
theirs = 'dot',
|
theirs = 'dot',
|
||||||
|
|
@ -618,65 +617,6 @@ describe('merge', function()
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('hunk hints', function()
|
|
||||||
it('adds keymap hints on hunk header lines', function()
|
|
||||||
local d_bufnr = create_diff_buffer({
|
|
||||||
'diff --git a/file.lua b/file.lua',
|
|
||||||
'--- a/file.lua',
|
|
||||||
'+++ b/file.lua',
|
|
||||||
'@@ -1,1 +1,1 @@',
|
|
||||||
'-local x = 1',
|
|
||||||
'+local x = 2',
|
|
||||||
})
|
|
||||||
|
|
||||||
merge.setup_keymaps(d_bufnr, default_config())
|
|
||||||
|
|
||||||
local extmarks =
|
|
||||||
vim.api.nvim_buf_get_extmarks(d_bufnr, merge.get_namespace(), 0, -1, { details = true })
|
|
||||||
local hint_marks = {}
|
|
||||||
for _, mark in ipairs(extmarks) do
|
|
||||||
if mark[4] and mark[4].virt_text then
|
|
||||||
local text = ''
|
|
||||||
for _, chunk in ipairs(mark[4].virt_text) do
|
|
||||||
text = text .. chunk[1]
|
|
||||||
end
|
|
||||||
table.insert(hint_marks, { line = mark[2], text = text })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assert.are.equal(1, #hint_marks)
|
|
||||||
assert.are.equal(3, hint_marks[1].line)
|
|
||||||
assert.is_truthy(hint_marks[1].text:find('doo'))
|
|
||||||
assert.is_truthy(hint_marks[1].text:find('dot'))
|
|
||||||
|
|
||||||
helpers.delete_buffer(d_bufnr)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('does not add hints when show_virtual_text is false', function()
|
|
||||||
local d_bufnr = create_diff_buffer({
|
|
||||||
'diff --git a/file.lua b/file.lua',
|
|
||||||
'--- a/file.lua',
|
|
||||||
'+++ b/file.lua',
|
|
||||||
'@@ -1,1 +1,1 @@',
|
|
||||||
'-local x = 1',
|
|
||||||
'+local x = 2',
|
|
||||||
})
|
|
||||||
|
|
||||||
merge.setup_keymaps(d_bufnr, default_config({ show_virtual_text = false }))
|
|
||||||
|
|
||||||
local extmarks =
|
|
||||||
vim.api.nvim_buf_get_extmarks(d_bufnr, merge.get_namespace(), 0, -1, { details = true })
|
|
||||||
local virt_text_count = 0
|
|
||||||
for _, mark in ipairs(extmarks) do
|
|
||||||
if mark[4] and mark[4].virt_text then
|
|
||||||
virt_text_count = virt_text_count + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assert.are.equal(0, virt_text_count)
|
|
||||||
|
|
||||||
helpers.delete_buffer(d_bufnr)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
describe('fugitive integration', function()
|
describe('fugitive integration', function()
|
||||||
it('parse_file_line returns status for unmerged files', function()
|
it('parse_file_line returns status for unmerged files', function()
|
||||||
local fugitive = require('diffs.fugitive')
|
local fugitive = require('diffs.fugitive')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue