feat(blame): show commit's hunk in the line popup
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
local M = {}
|
||||
|
||||
---@param win integer
|
||||
---@return boolean
|
||||
local function has_border(win)
|
||||
local b = vim.api.nvim_win_get_config(win).border
|
||||
if not b or b == "none" or b == "" then
|
||||
return false
|
||||
end
|
||||
if type(b) == "table" and #b == 0 then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
---@param lines string[]
|
||||
---@param opts? { min_width?: integer, padding?: integer }
|
||||
---@return integer width
|
||||
---@return integer height
|
||||
function M.size_for(lines, opts)
|
||||
opts = opts or {}
|
||||
local width = 1
|
||||
for _, l in ipairs(lines) do
|
||||
local w = vim.api.nvim_strwidth(l)
|
||||
if w > width then
|
||||
width = w
|
||||
end
|
||||
end
|
||||
width = math.min(
|
||||
math.max(width + (opts.padding or 1), opts.min_width or 30),
|
||||
100,
|
||||
vim.o.columns - 4
|
||||
)
|
||||
local height =
|
||||
math.min(math.max(#lines, 1), 20, math.floor(vim.o.lines / 2))
|
||||
return width, height
|
||||
end
|
||||
|
||||
---@param pbuf integer
|
||||
---@param win integer
|
||||
---@param ns integer
|
||||
function M.paint_overflow(pbuf, win, ns)
|
||||
vim.schedule(function()
|
||||
if
|
||||
not vim.api.nvim_buf_is_valid(pbuf)
|
||||
or not vim.api.nvim_win_is_valid(win)
|
||||
then
|
||||
return
|
||||
end
|
||||
vim.api.nvim_buf_clear_namespace(pbuf, ns, 0, -1)
|
||||
local total = vim.api.nvim_buf_line_count(pbuf)
|
||||
local top, bottom = unpack(vim.api.nvim_win_call(win, function()
|
||||
return { vim.fn.line("w0"), vim.fn.line("w$") }
|
||||
end)) ---@cast top integer
|
||||
---@cast bottom integer
|
||||
local needs_top = top > 1
|
||||
local needs_bottom = bottom < total
|
||||
if has_border(win) then
|
||||
pcall(vim.api.nvim_win_set_config, win, {
|
||||
title = needs_top and { { "▲ ", "FloatBorder" } } or "",
|
||||
title_pos = needs_top and "right" or nil,
|
||||
footer = needs_bottom and { { "▼ ", "FloatBorder" } } or "",
|
||||
footer_pos = needs_bottom and "right" or nil,
|
||||
})
|
||||
return
|
||||
end
|
||||
if needs_top then
|
||||
pcall(vim.api.nvim_buf_set_extmark, pbuf, ns, top - 1, 0, {
|
||||
virt_text = { { "▲ ", "GitPopupEnd" } },
|
||||
virt_text_pos = "right_align",
|
||||
})
|
||||
end
|
||||
if needs_bottom then
|
||||
pcall(vim.api.nvim_buf_set_extmark, pbuf, ns, bottom - 1, 0, {
|
||||
virt_text = { { "▼ ", "GitPopupEnd" } },
|
||||
virt_text_pos = "right_align",
|
||||
})
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -120,6 +120,34 @@ function M.split_lines(content)
|
||||
return lines
|
||||
end
|
||||
|
||||
---@param buf integer
|
||||
---@param ns integer
|
||||
---@param lines string[]
|
||||
---@param start_row integer 0-indexed row of the first line in `lines`
|
||||
function M.paint_diff_lines(buf, ns, lines, start_row)
|
||||
for i, line in ipairs(lines) do
|
||||
local hl ---@type string?
|
||||
local prefix = line:sub(1, 1)
|
||||
if prefix == "+" then
|
||||
hl = "GitHunkAdded"
|
||||
elseif prefix == "-" then
|
||||
hl = "GitHunkRemoved"
|
||||
elseif vim.startswith(line, "@@") then
|
||||
hl = "GitHunkHeader"
|
||||
end
|
||||
if hl then
|
||||
pcall(
|
||||
vim.api.nvim_buf_set_extmark,
|
||||
buf,
|
||||
ns,
|
||||
start_row + i - 1,
|
||||
0,
|
||||
{ line_hl_group = hl }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@class ow.Git.Util.DebounceHandle
|
||||
---@field cancel fun()
|
||||
---@field flush fun()
|
||||
|
||||
Reference in New Issue
Block a user