fix(git): rename log to log_view
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
local repo = require("git.repo")
|
||||
local util = require("git.util")
|
||||
|
||||
local M = {}
|
||||
|
||||
M.URI_PREFIX = "gitlog://"
|
||||
|
||||
local LOG_FORMAT = "%h %ad {%an}%d %s"
|
||||
|
||||
local cr = vim.api.nvim_replace_termcodes("<CR>", true, false, true)
|
||||
|
||||
---@param buf integer
|
||||
local function attach_dispatch(buf)
|
||||
vim.keymap.set("n", "<CR>", function()
|
||||
local r = repo.resolve(buf)
|
||||
-- Anchor past the leading graph chars (matches the leading sha
|
||||
-- column, not any hex word that happens to appear later in the
|
||||
-- subject).
|
||||
local sha = r
|
||||
and vim.api
|
||||
.nvim_get_current_line()
|
||||
:match("^[*|/\\_ ]*(%x%x%x%x%x%x%x+)")
|
||||
if sha then
|
||||
---@cast r -nil
|
||||
require("git.object").open(r, sha, { split = false })
|
||||
else
|
||||
vim.api.nvim_feedkeys(cr, "n", false)
|
||||
end
|
||||
end, { buffer = buf, silent = true, desc = "Open commit" })
|
||||
end
|
||||
|
||||
---@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 r = repo.resolve(buf)
|
||||
local state = r and r:state(buf)
|
||||
if not r or not state then
|
||||
return
|
||||
end
|
||||
local stdout = fetch(r.worktree, state.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(#M.URI_PREFIX + 1)
|
||||
if worktree == "" then
|
||||
return
|
||||
end
|
||||
local r = repo.resolve(worktree)
|
||||
if not r then
|
||||
return
|
||||
end
|
||||
repo.bind(buf, r)
|
||||
|
||||
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
|
||||
|
||||
attach_dispatch(buf)
|
||||
populate(buf)
|
||||
end
|
||||
|
||||
---@class ow.Git.Log.OpenOpts
|
||||
---@field max_count integer?
|
||||
|
||||
---@type table<string, fun(s: string): any>
|
||||
M.opt_parsers = {
|
||||
max_count = tonumber,
|
||||
}
|
||||
|
||||
---@param opts ow.Git.Log.OpenOpts?
|
||||
function M.open(opts)
|
||||
opts = opts or {}
|
||||
local r = repo.resolve()
|
||||
if not r then
|
||||
util.warning("not in a git repository")
|
||||
return
|
||||
end
|
||||
|
||||
local buf = vim.fn.bufadd(M.URI_PREFIX .. r.worktree)
|
||||
repo.bind(buf, r)
|
||||
local state = r:state(buf) --[[@as -nil]]
|
||||
state.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
|
||||
|
||||
---@param cmd_opts table
|
||||
function M.run_glog(cmd_opts)
|
||||
local parsed = { max_count = 1000 }
|
||||
for _, a in ipairs(cmd_opts.fargs) do
|
||||
local k, v = a:match("^([%w_]+)=(.*)$")
|
||||
if not k then
|
||||
util.error("invalid argument: %s", a)
|
||||
return
|
||||
end
|
||||
---@cast v -nil
|
||||
local parser = M.opt_parsers[k]
|
||||
if parser then
|
||||
local value = parser(v)
|
||||
if value ~= nil then
|
||||
parsed[k] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
M.open(parsed)
|
||||
end
|
||||
|
||||
---@param arg_lead string
|
||||
---@return string[]
|
||||
function M.complete_glog(arg_lead)
|
||||
local matches = {}
|
||||
for k in pairs(M.opt_parsers) do
|
||||
local prefix = k .. "="
|
||||
if prefix:sub(1, #arg_lead) == arg_lead then
|
||||
table.insert(matches, prefix)
|
||||
end
|
||||
end
|
||||
table.sort(matches)
|
||||
return matches
|
||||
end
|
||||
|
||||
repo.on_uri_refresh(M.URI_PREFIX, M.read_uri)
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user