feat(resolve): add resolve command and log integration (#125)

Add first-class conflict resolution support to jj.nvim.

   - add `jj.cmd.resolve` to run `jj resolve` in a floating terminal or via an
     external tool
   - add `:J resolve` with support for `-r/--revision`, `--tool`,
     `--external/--ext`, and positional filesets
   - integrate resolve into the log buffer with the `gr` mapping and optional
     `resolve_strategies` picker
   - add `utils.is_change_conflicted()` and avoid opening resolve when the
     selected revision has no conflicts
   - document resolve usage, config, and keymaps in the README
   - add tests for resolve arg parsing and conflict detection helpers
This commit is contained in:
Nicolas GB
2026-06-16 19:06:33 +02:00
committed by GitHub
parent 9f2a76d079
commit 7fc91fe6d2
7 changed files with 543 additions and 31 deletions
+59
View File
@@ -943,6 +943,60 @@ function M.handle_log_split()
})
end
--- Handle log resolve conflict
function M.handle_log_resolve()
local revset = get_revset()
if not revset or revset == "" then
return
end
if not utils.is_change_conflicted(revset) then
utils.notify(string.format("Revision `%s` has no conflicts to resolve", revset), vim.log.levels.INFO)
return
end
local exit_func = function(exit_code)
if exit_code == 0 then
utils.notify(string.format("Successfully resolved `%s`", revset), vim.log.levels.INFO)
vim.schedule(function()
M.log({})
end)
else
-- Since we previously replaced the floating with the resolve we actually want to re run the log cmd
if require("jj").config.terminal.window.type == "floating" then
vim.schedule(function()
M.log({})
end)
end
end
end
local strategies = require("jj.cmd").config.resolve_strategies
if strategies and #strategies > 1 then
vim.ui.select(strategies, {
prompt = "Select a resolve strategy: ",
format_item = function(item)
return item.name
end,
}, function(choice)
if choice then
require("jj.cmd").resolve({
rev = revset,
args = choice.args,
external = choice.external,
on_exit = exit_func,
})
end
end)
elseif strategies and #strategies == 1 then
local choice = strategies[1]
require("jj.cmd").resolve({ rev = revset, args = choice.args, external = choice.external, on_exit = exit_func })
else
-- Simply resolve with the default
require("jj.cmd").resolve({ rev = revset, on_exit = exit_func })
end
end
--- Handle diff action in summary tooltip
--- Diffs the file at revset against its parent (revset-)
--- Opens a floating diff, and returns focus to tooltip when closed
@@ -1322,6 +1376,11 @@ function M.log_keymaps()
handler = M.handle_log_select_prev_revision,
modes = { "n", "v" },
},
resolve = {
desc = "Resolve conflicts for revision under cursor",
handler = M.handle_log_resolve,
modes = { "n" },
},
}
local merged_keymaps = cmd.merge_keymaps(cmd.resolve_keymaps_from_specs(keymaps, specs), cmd.terminal_keymaps())