Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 897de35688 | |||
| 8fe4d0c6a7 |
+111
-152
@@ -1,175 +1,134 @@
|
|||||||
local Revision = require("git.core.revision")
|
local Revision = require("git.core.revision")
|
||||||
|
local object = require("git.object")
|
||||||
local repo = require("git.core.repo")
|
local repo = require("git.core.repo")
|
||||||
local util = require("git.core.util")
|
local util = require("git.core.util")
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
---@class ow.Git.Diff.Side
|
|
||||||
---@field buf integer
|
|
||||||
---@field name string?
|
|
||||||
|
|
||||||
---@class ow.Git.Diff.Pair
|
|
||||||
---@field left ow.Git.Diff.Side
|
|
||||||
---@field right ow.Git.Diff.Side
|
|
||||||
|
|
||||||
---@param win integer
|
|
||||||
---@param enabled boolean
|
|
||||||
function M.set_diff(win, enabled)
|
|
||||||
vim.api.nvim_win_call(win, function()
|
|
||||||
vim.cmd(enabled and "diffthis" or "diffoff")
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param left integer
|
|
||||||
---@param right integer
|
|
||||||
---@param vertical boolean
|
|
||||||
function M.open(left, right, vertical)
|
|
||||||
vim.cmd.normal({ "m'", bang = true })
|
|
||||||
vim.api.nvim_set_current_buf(right)
|
|
||||||
vim.cmd.diffthis()
|
|
||||||
vim.api.nvim_open_win(left, true, {
|
|
||||||
split = vertical and "left" or "above",
|
|
||||||
})
|
|
||||||
vim.cmd.diffthis()
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param left_win integer
|
|
||||||
---@param right_win integer
|
|
||||||
---@param pair ow.Git.Diff.Pair
|
|
||||||
function M.update_pair(left_win, right_win, pair)
|
|
||||||
M.set_diff(left_win, false)
|
|
||||||
M.set_diff(right_win, false)
|
|
||||||
vim.api.nvim_win_set_buf(left_win, pair.left.buf)
|
|
||||||
vim.api.nvim_win_set_buf(right_win, pair.right.buf)
|
|
||||||
for _, side in ipairs({ pair.left, pair.right }) do
|
|
||||||
if side.name then
|
|
||||||
util.set_buf_name(side.buf, side.name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
M.set_diff(left_win, true)
|
|
||||||
M.set_diff(right_win, true)
|
|
||||||
vim.api.nvim_win_set_cursor(left_win, { 1, 0 })
|
|
||||||
vim.api.nvim_win_set_cursor(right_win, { 1, 0 })
|
|
||||||
vim.cmd.syncbind()
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param buf_a integer
|
|
||||||
---@param buf_b integer
|
|
||||||
---@param a_left boolean
|
|
||||||
---@param vertical boolean
|
|
||||||
local function place_pair(buf_a, buf_b, a_left, vertical)
|
|
||||||
if a_left then
|
|
||||||
M.open(buf_a, buf_b, vertical)
|
|
||||||
else
|
|
||||||
M.open(buf_b, buf_a, vertical)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param opts ow.Git.Diff.SplitOpts
|
|
||||||
---@param buf integer
|
|
||||||
---@param rev ow.Git.Revision
|
|
||||||
local function uri_split(opts, buf, rev)
|
|
||||||
local r = repo.resolve(buf)
|
|
||||||
if not r then
|
|
||||||
util.error("git URI buffer has no worktree")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if not rev.path then
|
|
||||||
util.error("git URI has no path, cannot diff against worktree")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local object = require("git.object")
|
|
||||||
|
|
||||||
if opts.rev and opts.rev:find(":", 1, true) then
|
|
||||||
if not r:rev_parse(opts.rev, true) then
|
|
||||||
util.error("invalid rev: %s", opts.rev)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
place_pair(
|
|
||||||
buf,
|
|
||||||
object.buf_for(r, Revision.parse(opts.rev)),
|
|
||||||
false,
|
|
||||||
opts.vertical
|
|
||||||
)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not opts.rev then
|
|
||||||
local worktree_path = vim.fs.joinpath(r.worktree, rev.path)
|
|
||||||
if not vim.uv.fs_stat(worktree_path) then
|
|
||||||
util.error("worktree file does not exist: %s", rev.path)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local worktree_buf = vim.fn.bufadd(worktree_path)
|
|
||||||
vim.fn.bufload(worktree_buf)
|
|
||||||
place_pair(buf, worktree_buf, true, opts.vertical)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if rev.stage == 1 then
|
|
||||||
util.warning("gD on merge base is ambiguous, use :Gdiffsplit <rev>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local mapping = {
|
|
||||||
[2] = { Revision.new({ stage = 3, path = rev.path }), true },
|
|
||||||
[3] = { Revision.new({ stage = 2, path = rev.path }), false },
|
|
||||||
[0] = { Revision.new({ base = "HEAD", path = rev.path }), false },
|
|
||||||
}
|
|
||||||
local m = mapping[rev.stage]
|
|
||||||
or { Revision.new({ stage = 0, path = rev.path }), true }
|
|
||||||
local other_rev, left = m[1], m[2]
|
|
||||||
if not r:rev_parse(other_rev:format(), true) then
|
|
||||||
util.error("invalid rev: %s", other_rev:format())
|
|
||||||
return
|
|
||||||
end
|
|
||||||
place_pair(buf, object.buf_for(r, other_rev), left, opts.vertical)
|
|
||||||
end
|
|
||||||
|
|
||||||
---@class ow.Git.Diff.SplitOpts
|
---@class ow.Git.Diff.SplitOpts
|
||||||
---@field rev string?
|
---@field target string?
|
||||||
---@field vertical boolean
|
---@field mods vim.api.keyset.cmd.mods?
|
||||||
|
|
||||||
---@param opts ow.Git.Diff.SplitOpts
|
---@param cur_buf integer
|
||||||
function M.split(opts)
|
---@return string? target
|
||||||
local cur_buf = vim.api.nvim_get_current_buf()
|
---@return string? err
|
||||||
local cur_path = vim.api.nvim_buf_get_name(cur_buf)
|
local function infer_target(cur_buf)
|
||||||
|
local cur_name = vim.api.nvim_buf_get_name(cur_buf)
|
||||||
local cur_rev = require("git.object").parse_uri(cur_path)
|
local cur_rev = object.parse_uri(cur_name)
|
||||||
if cur_rev then
|
if cur_rev then
|
||||||
return uri_split(opts, cur_buf, cur_rev)
|
local r = repo.resolve(cur_buf)
|
||||||
|
if not r then
|
||||||
|
return nil, "git URI buffer has no worktree"
|
||||||
|
end
|
||||||
|
if not cur_rev.path then
|
||||||
|
return nil, "git URI has no path, cannot diff against worktree"
|
||||||
|
end
|
||||||
|
local worktree_path = vim.fs.joinpath(r.worktree, cur_rev.path)
|
||||||
|
if not vim.uv.fs_stat(worktree_path) then
|
||||||
|
return nil, "worktree file does not exist: " .. cur_rev.path
|
||||||
|
end
|
||||||
|
return worktree_path, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if cur_path == "" then
|
if cur_name == "" then
|
||||||
util.error("no file in current buffer")
|
return nil, "no file in current buffer"
|
||||||
return
|
|
||||||
end
|
end
|
||||||
if vim.bo[cur_buf].buftype ~= "" then
|
if vim.bo[cur_buf].buftype ~= "" then
|
||||||
util.error("cannot diff this buffer (not a worktree file)")
|
return nil, "cannot diff this buffer (not a worktree file)"
|
||||||
return
|
|
||||||
end
|
end
|
||||||
cur_path = vim.fn.resolve(cur_path)
|
local resolved = vim.fn.resolve(cur_name)
|
||||||
local r = repo.resolve(cur_path)
|
local r = repo.resolve(resolved)
|
||||||
if not r then
|
if not r then
|
||||||
util.error("not in a git repository")
|
return nil, "not in a git repository"
|
||||||
return
|
end
|
||||||
|
local rel = vim.fs.relpath(r.worktree, resolved)
|
||||||
|
if not rel then
|
||||||
|
return nil, "current buffer is outside the worktree"
|
||||||
|
end
|
||||||
|
return object.format_uri(Revision.new({ stage = 0, path = rel })), nil
|
||||||
end
|
end
|
||||||
local rel = vim.fs.relpath(r.worktree, cur_path)
|
|
||||||
|
|
||||||
local rev
|
---@param target string
|
||||||
if not opts.rev then
|
---@param cur_buf integer
|
||||||
rev = Revision.new({ stage = 0, path = rel })
|
---@return string? resolved
|
||||||
elseif opts.rev:find(":", 1, true) then
|
---@return string? err
|
||||||
rev = Revision.parse(opts.rev)
|
local function resolve_target(target, cur_buf)
|
||||||
else
|
if vim.startswith(target, object.URI_PREFIX) then
|
||||||
rev = Revision.new({ base = opts.rev, path = rel })
|
return target, nil
|
||||||
end
|
end
|
||||||
if not r:rev_parse(rev:format(), true) then
|
if vim.fn.filereadable(target) == 1 then
|
||||||
util.error("invalid rev: %s", rev:format())
|
return target, nil
|
||||||
|
end
|
||||||
|
local cur_name = vim.api.nvim_buf_get_name(cur_buf)
|
||||||
|
local cur_rev = object.parse_uri(cur_name)
|
||||||
|
local r, rel
|
||||||
|
if cur_rev and cur_rev.path then
|
||||||
|
r = repo.resolve(cur_buf)
|
||||||
|
rel = cur_rev.path
|
||||||
|
elseif cur_name ~= "" then
|
||||||
|
local resolved = vim.fn.resolve(cur_name)
|
||||||
|
r = repo.resolve(resolved)
|
||||||
|
if r then
|
||||||
|
rel = vim.fs.relpath(r.worktree, resolved)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not r then
|
||||||
|
return nil, "not in a git repository"
|
||||||
|
end
|
||||||
|
if not rel then
|
||||||
|
return nil, "current buffer has no path"
|
||||||
|
end
|
||||||
|
if not r:rev_parse(target, true) then
|
||||||
|
return nil, "invalid rev: " .. target
|
||||||
|
end
|
||||||
|
return object.format_uri(Revision.new({ base = target, path = rel })), nil
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param cur_buf integer
|
||||||
|
---@param target string
|
||||||
|
---@return 'aboveleft'|'belowright'|nil
|
||||||
|
local function default_split(cur_buf, target)
|
||||||
|
local cur_rev = object.parse_uri(vim.api.nvim_buf_get_name(cur_buf))
|
||||||
|
local target_rev = object.parse_uri(target)
|
||||||
|
if not cur_rev and target_rev then
|
||||||
|
return "aboveleft"
|
||||||
|
end
|
||||||
|
if cur_rev and not target_rev then
|
||||||
|
return "belowright"
|
||||||
|
end
|
||||||
|
if cur_rev and target_rev then
|
||||||
|
if cur_rev.stage == 0 and target_rev.base then
|
||||||
|
return "aboveleft"
|
||||||
|
end
|
||||||
|
if cur_rev.base and target_rev.stage == 0 then
|
||||||
|
return "belowright"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param opts? ow.Git.Diff.SplitOpts
|
||||||
|
function M.split(opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local cur_buf = vim.api.nvim_get_current_buf()
|
||||||
|
local target, err
|
||||||
|
if opts.target then
|
||||||
|
target, err = resolve_target(opts.target, cur_buf)
|
||||||
|
else
|
||||||
|
target, err = infer_target(cur_buf)
|
||||||
|
end
|
||||||
|
if not target then
|
||||||
|
util.error("%s", err or "no diff target")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local buf = require("git.object").buf_for(r, rev)
|
local mods = opts.mods
|
||||||
place_pair(buf, cur_buf, true, opts.vertical)
|
if not mods or mods.split == nil then
|
||||||
|
local placement = default_split(cur_buf, target)
|
||||||
|
if placement then
|
||||||
|
mods = vim.tbl_extend("force", mods or {}, { split = placement })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
vim.cmd.diffsplit({ args = { target }, mods = mods })
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
+6
-1
@@ -334,7 +334,12 @@ local function open_section(r, section)
|
|||||||
local left = side_buf(r, section.blob_a, section.path_a)
|
local left = side_buf(r, section.blob_a, section.path_a)
|
||||||
local right = side_buf(r, section.blob_b, section.path_b)
|
local right = side_buf(r, section.blob_b, section.path_b)
|
||||||
if left and right then
|
if left and right then
|
||||||
require("git.diff").open(left, right, true)
|
vim.cmd.normal({ "m'", bang = true })
|
||||||
|
vim.api.nvim_set_current_buf(right)
|
||||||
|
require("git.diff").split({
|
||||||
|
target = vim.api.nvim_buf_get_name(left),
|
||||||
|
mods = { vertical = true },
|
||||||
|
})
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not left and not right then
|
if not left and not right then
|
||||||
|
|||||||
+32
-27
@@ -176,9 +176,13 @@ local function current_entry(bufnr)
|
|||||||
return s, s.lines[lnum]
|
return s, s.lines[lnum]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@class ow.Git.StatusView.Pane
|
||||||
|
---@field buf integer
|
||||||
|
---@field name string?
|
||||||
|
|
||||||
---@param r ow.Git.Repo
|
---@param r ow.Git.Repo
|
||||||
---@param path string
|
---@param path string
|
||||||
---@return ow.Git.Diff.Side
|
---@return ow.Git.StatusView.Pane
|
||||||
local function head_pane(r, path)
|
local function head_pane(r, path)
|
||||||
local rev = Revision.new({ base = "HEAD", path = path })
|
local rev = Revision.new({ base = "HEAD", path = path })
|
||||||
return {
|
return {
|
||||||
@@ -189,7 +193,7 @@ end
|
|||||||
|
|
||||||
---@param r ow.Git.Repo
|
---@param r ow.Git.Repo
|
||||||
---@param path string
|
---@param path string
|
||||||
---@return ow.Git.Diff.Side
|
---@return ow.Git.StatusView.Pane
|
||||||
local function worktree_pane(r, path)
|
local function worktree_pane(r, path)
|
||||||
local buf = vim.fn.bufadd(vim.fs.joinpath(r.worktree, path))
|
local buf = vim.fn.bufadd(vim.fs.joinpath(r.worktree, path))
|
||||||
vim.fn.bufload(buf)
|
vim.fn.bufload(buf)
|
||||||
@@ -198,7 +202,7 @@ end
|
|||||||
|
|
||||||
---@param s ow.Git.StatusView.State
|
---@param s ow.Git.StatusView.State
|
||||||
---@param path string
|
---@param path string
|
||||||
---@return ow.Git.Diff.Side
|
---@return ow.Git.StatusView.Pane
|
||||||
local function index_pane(s, path)
|
local function index_pane(s, path)
|
||||||
local rev = Revision.new({ stage = 0, path = path })
|
local rev = Revision.new({ stage = 0, path = path })
|
||||||
return {
|
return {
|
||||||
@@ -209,7 +213,7 @@ end
|
|||||||
|
|
||||||
---@param s ow.Git.StatusView.State
|
---@param s ow.Git.StatusView.State
|
||||||
---@param row ow.Git.Status.Row
|
---@param row ow.Git.Status.Row
|
||||||
---@return ow.Git.Diff.Side?
|
---@return ow.Git.StatusView.Pane?
|
||||||
local function older_pane(s, row)
|
local function older_pane(s, row)
|
||||||
local entry = row.entry
|
local entry = row.entry
|
||||||
if row.section == "staged" then
|
if row.section == "staged" then
|
||||||
@@ -227,7 +231,7 @@ end
|
|||||||
|
|
||||||
---@param s ow.Git.StatusView.State
|
---@param s ow.Git.StatusView.State
|
||||||
---@param row ow.Git.Status.Row
|
---@param row ow.Git.Status.Row
|
||||||
---@return ow.Git.Diff.Side?
|
---@return ow.Git.StatusView.Pane?
|
||||||
local function newer_pane(s, row)
|
local function newer_pane(s, row)
|
||||||
local entry = row.entry
|
local entry = row.entry
|
||||||
if row.section == "staged" then
|
if row.section == "staged" then
|
||||||
@@ -250,15 +254,6 @@ local function newer_pane(s, row)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param win integer
|
|
||||||
local function reset_diff_win(win)
|
|
||||||
vim.api.nvim_win_call(win, function()
|
|
||||||
vim.cmd(
|
|
||||||
"setlocal winfixwidth< number< relativenumber< signcolumn< wrap< cursorline<"
|
|
||||||
)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param target_win integer
|
---@param target_win integer
|
||||||
---@param dir "left"|"right"
|
---@param dir "left"|"right"
|
||||||
---@return integer
|
---@return integer
|
||||||
@@ -268,6 +263,9 @@ local function vsplit_at(target_win, dir)
|
|||||||
true,
|
true,
|
||||||
{ split = dir, win = target_win }
|
{ split = dir, win = target_win }
|
||||||
)
|
)
|
||||||
|
vim.api.nvim_win_call(win, function()
|
||||||
|
vim.cmd("setlocal winfixwidth<")
|
||||||
|
end)
|
||||||
vim.cmd.clearjumps()
|
vim.cmd.clearjumps()
|
||||||
return win
|
return win
|
||||||
end
|
end
|
||||||
@@ -322,8 +320,7 @@ local function view_row(s, row, focus_left)
|
|||||||
|
|
||||||
if s.placement ~= "sidebar" then
|
if s.placement ~= "sidebar" then
|
||||||
local pane = right or left
|
local pane = right or left
|
||||||
---@cast pane ow.Git.Diff.Side
|
---@cast pane -nil
|
||||||
diff.set_diff(status_win, false)
|
|
||||||
vim.cmd.normal({ "m'", bang = true })
|
vim.cmd.normal({ "m'", bang = true })
|
||||||
vim.api.nvim_win_set_buf(status_win, pane.buf)
|
vim.api.nvim_win_set_buf(status_win, pane.buf)
|
||||||
if pane.name then
|
if pane.name then
|
||||||
@@ -338,12 +335,13 @@ local function view_row(s, row, focus_left)
|
|||||||
end
|
end
|
||||||
close_other_diff_wins(status_win, target)
|
close_other_diff_wins(status_win, target)
|
||||||
vim.api.nvim_win_set_width(status_win, WINDOW_WIDTH)
|
vim.api.nvim_win_set_width(status_win, WINDOW_WIDTH)
|
||||||
reset_diff_win(target)
|
vim.api.nvim_win_call(target, function()
|
||||||
diff.set_diff(target, false)
|
vim.cmd.diffoff()
|
||||||
|
end)
|
||||||
|
|
||||||
if not (left and right) then
|
if not (left and right) then
|
||||||
local side = right or left
|
local side = right or left
|
||||||
---@cast side ow.Git.Diff.Side
|
---@cast side ow.Git.StatusView.Pane
|
||||||
vim.api.nvim_win_set_buf(target, side.buf)
|
vim.api.nvim_win_set_buf(target, side.buf)
|
||||||
if side.name then
|
if side.name then
|
||||||
util.set_buf_name(side.buf, side.name)
|
util.set_buf_name(side.buf, side.name)
|
||||||
@@ -351,16 +349,23 @@ local function view_row(s, row, focus_left)
|
|||||||
vim.api.nvim_set_current_win(focus_left and target or status_win)
|
vim.api.nvim_set_current_win(focus_left and target or status_win)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
---@cast left ow.Git.Diff.Side
|
---@cast left ow.Git.StatusView.Pane
|
||||||
---@cast right ow.Git.Diff.Side
|
---@cast right ow.Git.StatusView.Pane
|
||||||
|
|
||||||
local left_win = vsplit_at(target, "left")
|
vim.api.nvim_win_set_buf(target, right.buf)
|
||||||
reset_diff_win(left_win)
|
if right.name then
|
||||||
local combined = vim.api.nvim_win_get_width(left_win)
|
util.set_buf_name(right.buf, right.name)
|
||||||
+ vim.api.nvim_win_get_width(target)
|
end
|
||||||
vim.api.nvim_win_set_width(left_win, math.floor(combined / 2))
|
|
||||||
|
|
||||||
diff.update_pair(left_win, target, { left = left, right = right })
|
local older = left.name or vim.api.nvim_buf_get_name(left.buf)
|
||||||
|
local left_win
|
||||||
|
vim.api.nvim_win_call(target, function()
|
||||||
|
diff.split({
|
||||||
|
target = older,
|
||||||
|
mods = { vertical = true },
|
||||||
|
})
|
||||||
|
left_win = vim.api.nvim_get_current_win()
|
||||||
|
end)
|
||||||
vim.api.nvim_set_current_win(focus_left and left_win or status_win)
|
vim.api.nvim_set_current_win(focus_left and left_win or status_win)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+14
-12
@@ -142,22 +142,18 @@ end
|
|||||||
|
|
||||||
local DIFF_DIRECTIONS = { "vertical", "horizontal" }
|
local DIFF_DIRECTIONS = { "vertical", "horizontal" }
|
||||||
|
|
||||||
local function default_vertical()
|
|
||||||
return vim.tbl_contains(vim.opt.diffopt:get(), "vertical")
|
|
||||||
end
|
|
||||||
|
|
||||||
vim.api.nvim_create_user_command("Gdiffsplit", function(opts)
|
vim.api.nvim_create_user_command("Gdiffsplit", function(opts)
|
||||||
local fargs = opts.fargs
|
local fargs = opts.fargs
|
||||||
local vertical = default_vertical()
|
local mods = nil
|
||||||
local rev_idx = 1
|
local rev_idx = 1
|
||||||
if fargs[1] == "vertical" then
|
if fargs[1] == "vertical" then
|
||||||
vertical = true
|
mods = { vertical = true }
|
||||||
rev_idx = 2
|
rev_idx = 2
|
||||||
elseif fargs[1] == "horizontal" then
|
elseif fargs[1] == "horizontal" then
|
||||||
vertical = false
|
mods = { vertical = false }
|
||||||
rev_idx = 2
|
rev_idx = 2
|
||||||
end
|
end
|
||||||
require("git.diff").split({ rev = fargs[rev_idx], vertical = vertical })
|
require("git.diff").split({ target = fargs[rev_idx], mods = mods })
|
||||||
end, {
|
end, {
|
||||||
nargs = "*",
|
nargs = "*",
|
||||||
complete = function(arg_lead, cmd_line, _)
|
complete = function(arg_lead, cmd_line, _)
|
||||||
@@ -219,16 +215,22 @@ vim.keymap.set("n", "<Plug>(git-edit)", function()
|
|||||||
end, { silent = true, desc = "Edit a git object" })
|
end, { silent = true, desc = "Edit a git object" })
|
||||||
|
|
||||||
vim.keymap.set("n", "<Plug>(git-diff-vertical)", function()
|
vim.keymap.set("n", "<Plug>(git-diff-vertical)", function()
|
||||||
require("git.diff").split({ vertical = true })
|
require("git.diff").split({ mods = { vertical = true } })
|
||||||
end, { silent = true, desc = "Diff against index (vertical)" })
|
end, { silent = true, desc = "Diff against index (vertical)" })
|
||||||
vim.keymap.set("n", "<Plug>(git-diff-horizontal)", function()
|
vim.keymap.set("n", "<Plug>(git-diff-horizontal)", function()
|
||||||
require("git.diff").split({ vertical = false })
|
require("git.diff").split({ mods = { vertical = false } })
|
||||||
end, { silent = true, desc = "Diff against index (horizontal)" })
|
end, { silent = true, desc = "Diff against index (horizontal)" })
|
||||||
vim.keymap.set("n", "<Plug>(git-diff-vertical-head)", function()
|
vim.keymap.set("n", "<Plug>(git-diff-vertical-head)", function()
|
||||||
require("git.diff").split({ rev = "HEAD", vertical = true })
|
require("git.diff").split({
|
||||||
|
target = "HEAD",
|
||||||
|
mods = { vertical = true },
|
||||||
|
})
|
||||||
end, { silent = true, desc = "Diff against HEAD (vertical)" })
|
end, { silent = true, desc = "Diff against HEAD (vertical)" })
|
||||||
vim.keymap.set("n", "<Plug>(git-diff-horizontal-head)", function()
|
vim.keymap.set("n", "<Plug>(git-diff-horizontal-head)", function()
|
||||||
require("git.diff").split({ rev = "HEAD", vertical = false })
|
require("git.diff").split({
|
||||||
|
target = "HEAD",
|
||||||
|
mods = { vertical = false },
|
||||||
|
})
|
||||||
end, { silent = true, desc = "Diff against HEAD (horizontal)" })
|
end, { silent = true, desc = "Diff against HEAD (horizontal)" })
|
||||||
|
|
||||||
vim.keymap.set("n", "<Plug>(git-status-toggle)", function()
|
vim.keymap.set("n", "<Plug>(git-status-toggle)", function()
|
||||||
|
|||||||
@@ -234,3 +234,84 @@ t.test("refresh on stage updates the index URI buffer's content", function()
|
|||||||
"index pane should reflect staged content after refresh"
|
"index pane should reflect staged content after refresh"
|
||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
t.test(
|
||||||
|
"re-selecting same entry after close + diffsplit keeps fold state in sync",
|
||||||
|
function()
|
||||||
|
local committed, worktree = {}, {}
|
||||||
|
for i = 1, 30 do
|
||||||
|
committed[i] = "line " .. i
|
||||||
|
worktree[i] = i == 15 and "CHANGED" or ("line " .. i)
|
||||||
|
end
|
||||||
|
local sidebar_win, line = setup_sidebar_with_unstaged_file(
|
||||||
|
"foo.txt",
|
||||||
|
table.concat(committed, "\n") .. "\n",
|
||||||
|
table.concat(worktree, "\n") .. "\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
local prev_foldlevel = vim.o.foldlevel
|
||||||
|
vim.o.foldlevel = 99
|
||||||
|
t.defer(function()
|
||||||
|
vim.o.foldlevel = prev_foldlevel
|
||||||
|
end)
|
||||||
|
|
||||||
|
vim.api.nvim_set_current_win(sidebar_win)
|
||||||
|
vim.api.nvim_win_set_cursor(sidebar_win, { line, 0 })
|
||||||
|
t.press("<Tab>")
|
||||||
|
t.wait_for(function()
|
||||||
|
return find_diff_win("left") ~= nil
|
||||||
|
and find_diff_win("right") ~= nil
|
||||||
|
end, "first diff pair to appear")
|
||||||
|
|
||||||
|
local first_left = assert(find_diff_win("left"))
|
||||||
|
vim.api.nvim_win_close(first_left, false)
|
||||||
|
|
||||||
|
local remaining
|
||||||
|
for _, w in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||||
|
if w ~= sidebar_win then
|
||||||
|
remaining = w
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not remaining then
|
||||||
|
error("a non-sidebar window should remain after close")
|
||||||
|
end
|
||||||
|
vim.api.nvim_set_current_win(remaining)
|
||||||
|
require("git.diff").split({ mods = { vertical = true } })
|
||||||
|
t.wait_for(function()
|
||||||
|
local count = 0
|
||||||
|
for _, w in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||||
|
if vim.wo[w].diff then
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return count == 2
|
||||||
|
end, "diffsplit to produce a diff pair")
|
||||||
|
|
||||||
|
vim.api.nvim_set_current_win(sidebar_win)
|
||||||
|
vim.api.nvim_win_set_cursor(sidebar_win, { line, 0 })
|
||||||
|
t.press("<Tab>")
|
||||||
|
t.wait_for(function()
|
||||||
|
local count = 0
|
||||||
|
for _, w in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||||
|
if vim.wo[w].diff then
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return count == 2
|
||||||
|
end, "diff pair after re-selecting entry")
|
||||||
|
|
||||||
|
local left_win = assert(find_diff_win("left"))
|
||||||
|
local right_win = assert(find_diff_win("right"))
|
||||||
|
t.eq(
|
||||||
|
vim.wo[left_win].foldlevel,
|
||||||
|
0,
|
||||||
|
"left pane foldlevel should be 0 after re-select"
|
||||||
|
)
|
||||||
|
t.eq(
|
||||||
|
vim.wo[right_win].foldlevel,
|
||||||
|
0,
|
||||||
|
"right pane foldlevel should be 0 after re-select"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user