feat(git): trim hunk preview header, focus float on re-invoke
This commit is contained in:
+43
-17
@@ -446,12 +446,9 @@ function M.nav(direction)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param h ow.Git.Hunks.Hunk
|
---@param h ow.Git.Hunks.Hunk
|
||||||
---@param state ow.Git.Hunks.BufState
|
---@return string[]
|
||||||
---@return string
|
local function hunk_body(h)
|
||||||
local function build_patch(h, state)
|
|
||||||
local lines = {
|
local lines = {
|
||||||
"--- a/" .. state.rel,
|
|
||||||
"+++ b/" .. state.rel,
|
|
||||||
string.format(
|
string.format(
|
||||||
"@@ -%d,%d +%d,%d @@",
|
"@@ -%d,%d +%d,%d @@",
|
||||||
h.old_start,
|
h.old_start,
|
||||||
@@ -466,6 +463,15 @@ local function build_patch(h, state)
|
|||||||
for _, l in ipairs(h.new_lines) do
|
for _, l in ipairs(h.new_lines) do
|
||||||
table.insert(lines, "+" .. l)
|
table.insert(lines, "+" .. l)
|
||||||
end
|
end
|
||||||
|
return lines
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param h ow.Git.Hunks.Hunk
|
||||||
|
---@param state ow.Git.Hunks.BufState
|
||||||
|
---@return string
|
||||||
|
local function build_patch(h, state)
|
||||||
|
local lines = { "--- a/" .. state.rel, "+++ b/" .. state.rel }
|
||||||
|
vim.list_extend(lines, hunk_body(h))
|
||||||
return table.concat(lines, "\n") .. "\n"
|
return table.concat(lines, "\n") .. "\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -543,16 +549,22 @@ function M.select_hunk(buf)
|
|||||||
vim.api.nvim_win_set_cursor(0, { last, 0 })
|
vim.api.nvim_win_set_cursor(0, { last, 0 })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local preview_win ---@type integer?
|
||||||
|
|
||||||
---@param buf? integer
|
---@param buf? integer
|
||||||
function M.preview_hunk(buf)
|
function M.preview_hunk(buf)
|
||||||
local _, state, h = cursor_hunk(buf)
|
if preview_win and vim.api.nvim_win_is_valid(preview_win) then
|
||||||
|
vim.api.nvim_set_current_win(preview_win)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local target, state, h = cursor_hunk(buf)
|
||||||
if not state then
|
if not state then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not h then
|
if not h then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local lines = util.split_lines(build_patch(h, state))
|
local lines = hunk_body(h)
|
||||||
local pbuf = vim.api.nvim_create_buf(false, true)
|
local pbuf = vim.api.nvim_create_buf(false, true)
|
||||||
vim.api.nvim_buf_set_lines(pbuf, 0, -1, false, lines)
|
vim.api.nvim_buf_set_lines(pbuf, 0, -1, false, lines)
|
||||||
vim.bo[pbuf].filetype = "diff"
|
vim.bo[pbuf].filetype = "diff"
|
||||||
@@ -573,19 +585,33 @@ function M.preview_hunk(buf)
|
|||||||
height = height,
|
height = height,
|
||||||
style = "minimal",
|
style = "minimal",
|
||||||
})
|
})
|
||||||
vim.api.nvim_create_autocmd({ "CursorMoved", "InsertEnter", "BufLeave" }, {
|
preview_win = win
|
||||||
once = true,
|
|
||||||
callback = function()
|
local function close()
|
||||||
if vim.api.nvim_win_is_valid(win) then
|
|
||||||
vim.api.nvim_win_close(win, true)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
vim.keymap.set("n", "q", function()
|
|
||||||
if vim.api.nvim_win_is_valid(win) then
|
if vim.api.nvim_win_is_valid(win) then
|
||||||
vim.api.nvim_win_close(win, true)
|
vim.api.nvim_win_close(win, true)
|
||||||
end
|
end
|
||||||
end, { buffer = pbuf, nowait = true })
|
end
|
||||||
|
local group =
|
||||||
|
vim.api.nvim_create_augroup("ow.git.hunks.preview", { clear = true })
|
||||||
|
vim.api.nvim_create_autocmd(
|
||||||
|
{ "CursorMoved", "CursorMovedI", "InsertEnter" },
|
||||||
|
{ group = group, buffer = target, callback = close }
|
||||||
|
)
|
||||||
|
vim.api.nvim_create_autocmd("WinLeave", {
|
||||||
|
group = group,
|
||||||
|
buffer = pbuf,
|
||||||
|
callback = close,
|
||||||
|
})
|
||||||
|
vim.api.nvim_create_autocmd("WinClosed", {
|
||||||
|
group = group,
|
||||||
|
pattern = tostring(win),
|
||||||
|
callback = function()
|
||||||
|
preview_win = nil
|
||||||
|
pcall(vim.api.nvim_del_augroup_by_name, "ow.git.hunks.preview")
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
vim.keymap.set("n", "q", close, { buffer = pbuf, nowait = true })
|
||||||
end
|
end
|
||||||
|
|
||||||
repo.on("change", function(r, change)
|
repo.on("change", function(r, change)
|
||||||
|
|||||||
@@ -52,6 +52,15 @@ local function detailed_marks(buf, ns_name)
|
|||||||
return vim.api.nvim_buf_get_extmarks(buf, ns, 0, -1, { details = true })
|
return vim.api.nvim_buf_get_extmarks(buf, ns, 0, -1, { details = true })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return integer?
|
||||||
|
local function find_float()
|
||||||
|
for _, w in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||||
|
if vim.api.nvim_win_get_config(w).relative ~= "" then
|
||||||
|
return w
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
t.test("pure add: hunk shape and add signs", function()
|
t.test("pure add: hunk shape and add signs", function()
|
||||||
local _, buf, state = setup("a\nd\n", "a\nb\nc\nd\n")
|
local _, buf, state = setup("a\nd\n", "a\nb\nc\nd\n")
|
||||||
t.eq(#state.hunks, 1, "one hunk for a pure addition")
|
t.eq(#state.hunks, 1, "one hunk for a pure addition")
|
||||||
@@ -296,6 +305,52 @@ t.test("git_hunk_signs falls back to the default for unset kinds", function()
|
|||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
t.test("preview_hunk shows the hunk body without file headers", function()
|
||||||
|
local _, buf = setup("a\nb\nc\n", "a\nB\nc\n")
|
||||||
|
vim.api.nvim_set_current_buf(buf)
|
||||||
|
vim.api.nvim_win_set_cursor(0, { 2, 0 })
|
||||||
|
hunks.preview_hunk(buf)
|
||||||
|
local float = assert(find_float(), "preview float should open")
|
||||||
|
t.defer(function()
|
||||||
|
pcall(vim.api.nvim_win_close, float, true)
|
||||||
|
end)
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(
|
||||||
|
vim.api.nvim_win_get_buf(float),
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
t.truthy(
|
||||||
|
vim.startswith(lines[1] or "", "@@ "),
|
||||||
|
"first line is the @@ header"
|
||||||
|
)
|
||||||
|
for _, l in ipairs(lines) do
|
||||||
|
t.falsy(vim.startswith(l, "--- "), "no --- file header line")
|
||||||
|
t.falsy(vim.startswith(l, "+++ "), "no +++ file header line")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
t.test("preview_hunk re-invocation focuses the open float", function()
|
||||||
|
local _, buf = setup("a\nb\nc\n", "a\nB\nc\n")
|
||||||
|
vim.api.nvim_set_current_buf(buf)
|
||||||
|
vim.api.nvim_win_set_cursor(0, { 2, 0 })
|
||||||
|
hunks.preview_hunk(buf)
|
||||||
|
local float = assert(find_float(), "preview float should open")
|
||||||
|
t.defer(function()
|
||||||
|
pcall(vim.api.nvim_win_close, float, true)
|
||||||
|
end)
|
||||||
|
t.truthy(
|
||||||
|
vim.api.nvim_get_current_win() ~= float,
|
||||||
|
"the float opens unfocused"
|
||||||
|
)
|
||||||
|
hunks.preview_hunk(buf)
|
||||||
|
t.eq(
|
||||||
|
vim.api.nvim_get_current_win(),
|
||||||
|
float,
|
||||||
|
"re-invoking focuses the existing float"
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
|
||||||
t.test("nav jumps to next and previous hunks with wrap", function()
|
t.test("nav jumps to next and previous hunks with wrap", function()
|
||||||
local _, buf = setup("a\nb\nc\nd\ne\n", "A\nb\nc\nd\nE\n")
|
local _, buf = setup("a\nb\nc\nd\ne\n", "A\nb\nc\nd\nE\n")
|
||||||
vim.api.nvim_set_current_buf(buf)
|
vim.api.nvim_set_current_buf(buf)
|
||||||
|
|||||||
Reference in New Issue
Block a user