From 2335d5e0ddc106d0a39f24c269fc57f24d9c8d1c Mon Sep 17 00:00:00 2001 From: Oscar Wallberg Date: Wed, 29 Apr 2026 15:46:54 +0200 Subject: [PATCH] feat(git): give every new git window a fresh jumplist --- lua/git/cmd.lua | 4 +--- lua/git/diff.lua | 8 ++++++-- lua/git/log.lua | 26 +++++++++++++++++++++++++- lua/git/sidebar.lua | 4 +++- lua/git/util.lua | 8 +++++--- 5 files changed, 40 insertions(+), 10 deletions(-) diff --git a/lua/git/cmd.lua b/lua/git/cmd.lua index 8026f4c..3976dc0 100644 --- a/lua/git/cmd.lua +++ b/lua/git/cmd.lua @@ -81,9 +81,7 @@ local function place_split(name) if win_id ~= -1 then vim.api.nvim_set_current_win(win_id) else - vim.api.nvim_open_win(buf, true, { - split = vim.o.splitbelow and "below" or "above", - }) + util.place_buf(buf, nil) end return buf end diff --git a/lua/git/diff.lua b/lua/git/diff.lua index 6c9504a..fd8659f 100644 --- a/lua/git/diff.lua +++ b/lua/git/diff.lua @@ -44,8 +44,12 @@ function M.open(left, right, vertical) local left_name = vim.api.nvim_buf_get_name(left) vim.cmd.normal({ "m'", bang = true }) vim.api.nvim_set_current_buf(right) - local prefix = vertical and "leftabove vert " or "leftabove " - vim.cmd(prefix .. "diffsplit " .. vim.fn.fnameescape(left_name)) + vim.cmd.diffsplit({ + args = { left_name }, + mods = { split = "aboveleft", vertical = vertical }, + magic = { file = false }, + }) + vim.cmd("clearjumps") end ---Repoint two existing diff windows at a new pair of buffers. diff --git a/lua/git/log.lua b/lua/git/log.lua index 35bf7ef..91f1c31 100644 --- a/lua/git/log.lua +++ b/lua/git/log.lua @@ -34,8 +34,32 @@ local function populate(buf) if not stdout then return end + local new_lines = util.split_lines(stdout) + local old_str = table.concat( + vim.api.nvim_buf_get_lines(buf, 0, -1, false), + "\n" + ) .. "\n" + local new_str = table.concat(new_lines, "\n") .. "\n" + local hunks = vim.text.diff(old_str, new_str, { + result_type = "indices", + algorithm = "histogram", + }) + ---@cast hunks [integer, integer, integer, integer][] + if #hunks == 0 then + return + end vim.bo[buf].modifiable = true - vim.api.nvim_buf_set_lines(buf, 0, -1, false, util.split_lines(stdout)) + for i = #hunks, 1, -1 do + local sa, ca, sb, cb = unpack(hunks[i]) + local start = ca == 0 and sa or sa - 1 + vim.api.nvim_buf_set_lines( + buf, + start, + start + ca, + false, + vim.list_slice(new_lines, sb, sb + cb - 1) + ) + end vim.bo[buf].modifiable = false vim.bo[buf].modified = false end diff --git a/lua/git/sidebar.lua b/lua/git/sidebar.lua index d5f6f9a..0830cc9 100644 --- a/lua/git/sidebar.lua +++ b/lua/git/sidebar.lua @@ -640,11 +640,13 @@ end ---@param dir "left"|"right" ---@return integer local function vsplit_at(target_win, dir) - return vim.api.nvim_open_win( + local win = vim.api.nvim_open_win( vim.api.nvim_win_get_buf(target_win), true, { split = dir, win = target_win } ) + vim.cmd("clearjumps") + return win end ---@param s ow.Git.SidebarState diff --git a/lua/git/util.lua b/lua/git/util.lua index eb777a0..11d4d15 100644 --- a/lua/git/util.lua +++ b/lua/git/util.lua @@ -82,8 +82,8 @@ end ---Place a buffer in the current window or a new split per `split`. ---`false` replaces the current buffer, dropping a `'` mark first so ----`''` jumps back. A direction string opens a leftabove split. Nil ----falls back to a `splitbelow`-aware horizontal split. +---`''` jumps back. A direction string opens a split on that side. Nil +---falls back to `'splitbelow'` for the direction. ---@param buf integer ---@param split (false|"above"|"below"|"left"|"right")? ---@return integer win @@ -93,9 +93,11 @@ function M.place_buf(buf, split) vim.api.nvim_set_current_buf(buf) return vim.api.nvim_get_current_win() end - return vim.api.nvim_open_win(buf, true, { + local win = vim.api.nvim_open_win(buf, true, { split = split or (vim.o.splitbelow and "below" or "above"), }) + vim.cmd("clearjumps") + return win end ---@class ow.Git.NewScratchOpts : ow.Git.ScratchOpts