Files
nvim/lua/git/log.lua
T

114 lines
2.7 KiB
Lua

local repo = require("git.repo")
local util = require("git.util")
local M = {}
local LOG_FORMAT = "%h %ad {%an}%d %s"
local URI_PREFIX = "gitlog://"
---@param worktree string
---@param max_count integer?
---@return string?
local function fetch(worktree, max_count)
local cmd = {
"git",
"log",
"--graph",
"--all",
"--decorate",
"--date=short",
"--format=format:" .. LOG_FORMAT,
}
if max_count then
table.insert(cmd, "--max-count=" .. max_count)
end
return util.exec(cmd, { cwd = worktree })
end
---@param buf integer
local function populate(buf)
local worktree = vim.b[buf].git_worktree
local stdout = fetch(worktree, vim.b[buf].git_log_max_count)
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
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
---@param buf integer
function M.read_uri(buf)
local name = vim.api.nvim_buf_get_name(buf)
local worktree = name:sub(#URI_PREFIX + 1)
if worktree == "" then
return
end
vim.b[buf].git_worktree = worktree
vim.bo[buf].swapfile = false
vim.bo[buf].bufhidden = "hide"
vim.bo[buf].buftype = "nofile"
if vim.bo[buf].filetype ~= "gitlog" then
vim.bo[buf].filetype = "gitlog"
end
populate(buf)
end
---@class ow.Git.LogOpts
---@field max_count integer?
---@param opts ow.Git.LogOpts?
function M.open(opts)
opts = opts or {}
local _, worktree = repo.resolve_cwd()
if not worktree then
util.warning("not in a git repository")
return
end
local buf = vim.fn.bufadd(URI_PREFIX .. worktree)
vim.b[buf].git_worktree = worktree
vim.b[buf].git_log_max_count = opts.max_count
local was_loaded = vim.api.nvim_buf_is_loaded(buf)
local win = vim.fn.bufwinid(buf)
if win == -1 then
util.place_buf(buf, nil)
else
vim.api.nvim_set_current_win(win)
end
if was_loaded then
populate(buf)
end
end
return M