feat(conflict): add virtual text formatting and action lines
Problem: conflict resolution virtual text only showed plain "current" /
"incoming" labels with no keymap hints, and users had no way to
discover available keymaps without reading docs.
Solution: add keymap hints to default labels ("current — doo"), expose
format_virtual_text config for custom label formatting, and add
show_actions option for codelens-style action lines above conflict
markers. Also add hunk hints in merge diff views.
This commit is contained in:
parent
a2053a132b
commit
6e1a053bc4
6 changed files with 375 additions and 11 deletions
|
|
@ -92,6 +92,21 @@ local function parse_buffer(bufnr)
|
|||
return M.parse(lines)
|
||||
end
|
||||
|
||||
---@param side string
|
||||
---@param config diffs.ConflictConfig
|
||||
---@return string?
|
||||
local function get_virtual_text_label(side, config)
|
||||
local keymap = side == 'ours' and config.keymaps.ours or config.keymaps.theirs
|
||||
if config.format_virtual_text then
|
||||
return config.format_virtual_text(side, keymap)
|
||||
end
|
||||
local label = side == 'ours' and 'current' or 'incoming'
|
||||
if keymap then
|
||||
return ('%s \226\128\148 %s'):format(label, keymap)
|
||||
end
|
||||
return label
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param regions diffs.ConflictRegion[]
|
||||
---@param config diffs.ConflictConfig
|
||||
|
|
@ -107,10 +122,37 @@ local function apply_highlights(bufnr, regions, config)
|
|||
})
|
||||
|
||||
if config.show_virtual_text then
|
||||
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_ours, 0, {
|
||||
virt_text = { { ' (current)', 'DiffsConflictMarker' } },
|
||||
virt_text_pos = 'eol',
|
||||
})
|
||||
local ours_label = get_virtual_text_label('ours', config)
|
||||
if ours_label then
|
||||
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_ours, 0, {
|
||||
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
|
||||
|
||||
for line = region.ours_start, region.ours_end - 1 do
|
||||
|
|
@ -176,10 +218,13 @@ local function apply_highlights(bufnr, regions, config)
|
|||
})
|
||||
|
||||
if config.show_virtual_text then
|
||||
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_theirs, 0, {
|
||||
virt_text = { { ' (incoming)', 'DiffsConflictMarker' } },
|
||||
virt_text_pos = 'eol',
|
||||
})
|
||||
local theirs_label = get_virtual_text_label('theirs', config)
|
||||
if theirs_label then
|
||||
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, region.marker_theirs, 0, {
|
||||
virt_text = { { ' (' .. theirs_label .. ')', 'DiffsConflictMarker' } },
|
||||
virt_text_pos = 'eol',
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
---@field enabled boolean
|
||||
---@field disable_diagnostics 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
|
||||
|
||||
---@class diffs.Config
|
||||
|
|
@ -128,6 +130,7 @@ local default_config = {
|
|||
enabled = true,
|
||||
disable_diagnostics = true,
|
||||
show_virtual_text = true,
|
||||
show_actions = false,
|
||||
keymaps = {
|
||||
ours = 'doo',
|
||||
theirs = 'dot',
|
||||
|
|
@ -274,6 +277,7 @@ local function compute_highlight_groups()
|
|||
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, 'DiffsConflictMarker', { default = true, fg = 0x808080, bold = true })
|
||||
vim.api.nvim_set_hl(0, 'DiffsConflictActions', { default = true, fg = 0x808080 })
|
||||
vim.api.nvim_set_hl(
|
||||
0,
|
||||
'DiffsConflictOursNr',
|
||||
|
|
@ -388,6 +392,8 @@ local function init()
|
|||
['conflict.enabled'] = { opts.conflict.enabled, 'boolean', true },
|
||||
['conflict.disable_diagnostics'] = { opts.conflict.disable_diagnostics, '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 },
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -338,6 +338,43 @@ function M.goto_prev(bufnr)
|
|||
vim.api.nvim_win_set_cursor(0, { candidates[#candidates].start_line + 1, 0 })
|
||||
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 config diffs.ConflictConfig
|
||||
function M.setup_keymaps(bufnr, config)
|
||||
|
|
@ -358,6 +395,8 @@ function M.setup_keymaps(bufnr, config)
|
|||
end
|
||||
end
|
||||
|
||||
apply_hunk_hints(bufnr, config)
|
||||
|
||||
vim.api.nvim_create_autocmd('BufWipeout', {
|
||||
buffer = bufnr,
|
||||
callback = function()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue