From 3b8951758e16c4ad1c4cc68d2cbf216b70ae2452 Mon Sep 17 00:00:00 2001 From: Oscar Wallberg Date: Tue, 19 May 2026 19:55:02 +0200 Subject: [PATCH] fix(git): reset diff-pair cursor on sidebar selection --- lua/git/status_view.lua | 3 ++ test/git/status_view_test.lua | 80 +++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/lua/git/status_view.lua b/lua/git/status_view.lua index 1b0bf06..1e88cc6 100644 --- a/lua/git/status_view.lua +++ b/lua/git/status_view.lua @@ -404,7 +404,10 @@ local function view_row(s, row, focus_left) mods = { vertical = true }, }) left_win = vim.api.nvim_get_current_win() + vim.api.nvim_win_set_cursor(left_win, { 1, 0 }) + vim.api.nvim_win_set_cursor(target, { 1, 0 }) end) + ---@cast left_win -nil vim.api.nvim_set_current_win(focus_left and left_win or status_win) end diff --git a/test/git/status_view_test.lua b/test/git/status_view_test.lua index fa61fab..16a77a6 100644 --- a/test/git/status_view_test.lua +++ b/test/git/status_view_test.lua @@ -405,3 +405,83 @@ t.test("sidebar buffer name does not get written to disk", function() "no real file should be created at the sidebar buffer's path" ) end) + +t.test( + "diffsplit from sidebar resets cursor so panes stay in sync", + function() + local committed, worktree = {}, {} + for i = 1, 100 do + committed[i] = "line " .. i + worktree[i] = i == 10 + and "CHANGED " .. i + or i == 40 and "CHANGED " .. i + or i == 70 and "CHANGED " .. i + or i == 90 and "CHANGED " .. i + or ("line " .. i) + end + local repo = h.make_repo({ + ["file.txt"] = table.concat(committed, "\n") .. "\n", + }) + t.write(repo, "file.txt", table.concat(worktree, "\n") .. "\n") + vim.cmd("cd " .. repo) + + -- Open the worktree file in a normal window and position cursor in + -- what becomes a folded section after diff is set up. + vim.cmd("edit file.txt") + vim.api.nvim_win_set_cursor(0, { 50, 0 }) + + require("git.status_view").open({ placement = "sidebar" }) + local sidebar_buf, sidebar_win = find_sidebar() + assert(sidebar_buf and sidebar_win) + local r = assert(require("git.core.repo").find(vim.fn.getcwd())) + r:refresh() + t.wait_for(function() + return r.status and #r.status:rows("unstaged") > 0 + end, "git status to report unstaged changes") + + local entry_line + for i, l in + ipairs(vim.api.nvim_buf_get_lines(sidebar_buf, 0, -1, false)) + do + if l:match("file.txt$") then + entry_line = i + break + end + end + if not entry_line then + error("entry line should exist") + end + + vim.api.nvim_set_current_win(sidebar_win) + vim.api.nvim_win_set_cursor(sidebar_win, { entry_line, 0 }) + t.press("") + t.wait_for(function() + return find_diff_win("left") ~= nil + and find_diff_win("right") ~= nil + end, "diff pair to appear") + + local left_win = assert(find_diff_win("left")) + local right_win = assert(find_diff_win("right")) + local left_top = + vim.api.nvim_win_call(left_win, function() return vim.fn.line("w0") end) + local right_top = vim.api.nvim_win_call( + right_win, + function() return vim.fn.line("w0") end + ) + t.eq( + left_top, + right_top, + "left and right panes should have the same topline after diffsplit" + ) + t.eq( + vim.api.nvim_win_get_cursor(left_win), + { 1, 0 }, + "left pane should start at line 1" + ) + t.eq( + vim.api.nvim_win_get_cursor(right_win), + { 1, 0 }, + "right pane should start at line 1" + ) + end +)