From 96f327ff3ba23b5b040e473e73b0bcdbf174a7b6 Mon Sep 17 00:00:00 2001 From: Yanuo Ma <41042490+esmuellert@users.noreply.github.com> Date: Sat, 5 Sep 2026 23:22:12 -0400 Subject: [PATCH] fix(commands): allow history from active diff buffers Keep the CodeDiff toggle behavior for an argument-less invocation, but dispatch subcommands while a diff session is active. This lets visual line history create its history session instead of closing the current diff. Closes #463 --- lua/codediff/commands/init.lua | 7 ++++--- tests/command_e2e_spec.lua | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/lua/codediff/commands/init.lua b/lua/codediff/commands/init.lua index 69ce6e91..5e6979a2 100644 --- a/lua/codediff/commands/init.lua +++ b/lua/codediff/commands/init.lua @@ -300,15 +300,16 @@ function M.complete(arg_lead, cmd_line) end function M.vscode_diff(opts) - -- Toggle: close the diff view if the current tab already is one. + -- Toggle only when called without a subcommand. Commands such as + -- `:CodeDiff history` must remain dispatchable from an active diff tab. + local fargs, bang = opts.fargs or {}, opts.bang local current_tab = vim.api.nvim_get_current_tabpage() - if lifecycle.get_session(current_tab) then + if #fargs == 0 and lifecycle.get_session(current_tab) then lifecycle.close(current_tab) return end -- Normalize the `install!` alias into the `install` subcommand + bang. - local fargs, bang = opts.fargs, opts.bang if fargs[1] == "install!" then fargs = vim.list_slice(fargs, 1, #fargs) fargs[1] = "install" diff --git a/tests/command_e2e_spec.lua b/tests/command_e2e_spec.lua index f8b19360..77c9d083 100644 --- a/tests/command_e2e_spec.lua +++ b/tests/command_e2e_spec.lua @@ -266,6 +266,43 @@ describe("Command E2E (real dispatch + render)", function() assert.is_true(wait_for_visible("c1")) end) + it("visual line history works from an active diff buffer (#463)", function() + vim.cmd("CodeDiff --inline file " .. repo.path("a.txt") .. " " .. repo.path("file.txt")) + local diff_tab = wait_for_diff_text("line 2 CHANGED") + assert.is_not_nil(diff_tab, "inline diff should open") + + local diff_session = lifecycle.get_session(diff_tab) + assert.is_not_nil(diff_session) + vim.api.nvim_set_current_tabpage(diff_tab) + vim.api.nvim_set_current_win(diff_session.modified_win) + local modified_buf = diff_session.modified_bufnr + vim.api.nvim_buf_set_mark(modified_buf, "<", 1, 0, {}) + vim.api.nvim_buf_set_mark(modified_buf, ">", 2, 0, {}) + + vim.cmd("'<,'>CodeDiff history") + + local history_tab + assert.is_true( + vim.wait(10000, function() + for _, tp in ipairs(session_tabs()) do + local session = lifecycle.get_session(tp) + if session.panel and session.panel.name == "history" then + history_tab = tp + return true + end + end + return false + end, 50), + "visual line history should open a history session" + ) + + local history_session = lifecycle.get_session(history_tab) + assert.is_not_nil(history_session.panel.view) + assert.are.same({ 1, 2 }, history_session.panel.view.opts.line_range) + assert.equals("file.txt", history_session.panel.view.opts.file_path) + assert.is_true(wait_for_visible("c1"), "history should show commits for the selected lines") + end) + -- ── Layout flags (on a real-file diff) ──────────────────────────────────── it(":CodeDiff --inline file — inline layout", function()