Files
nvim/plugin/git.lua
T

256 lines
7.7 KiB
Lua

if vim.g.loaded_git then
return
end
vim.g.loaded_git = 1
local DEFAULT_HIGHLIGHTS = {
GitIgnored = "Comment",
GitSha = "Identifier",
GitStaged = "Constant",
GitUnmerged = "Todo",
GitUnpulled = "Removed",
GitUnpushed = "Added",
GitUnstaged = "Changed",
GitUntracked = "Added",
GitStagedAdded = "GitStaged",
GitStagedCopied = "GitStaged",
GitStagedDeleted = "GitStaged",
GitStagedModified = "GitStaged",
GitStagedRenamed = "GitStaged",
GitStagedTypeChanged = "GitStaged",
GitUnstagedAdded = "GitUnstaged",
GitUnstagedCopied = "GitUnstaged",
GitUnstagedDeleted = "Removed",
GitUnstagedModified = "GitUnstaged",
GitUnstagedRenamed = "GitStaged",
GitUnstagedTypeChanged = "GitUnstaged",
GitUnmergedAddedByThem = "GitUnmerged",
GitUnmergedAddedByUs = "GitUnmerged",
GitUnmergedBothAdded = "GitUnmerged",
GitUnmergedBothDeleted = "GitUnmerged",
GitUnmergedBothModified = "GitUnmerged",
GitUnmergedDeletedByThem = "GitUnmerged",
GitUnmergedDeletedByUs = "GitUnmerged",
}
for name, link in pairs(DEFAULT_HIGHLIGHTS) do
vim.api.nvim_set_hl(0, name, { link = link, default = true })
end
local group = vim.api.nvim_create_augroup("ow.git", { clear = true })
vim.api.nvim_create_autocmd({ "BufReadPost", "BufNewFile" }, {
group = group,
callback = function(args)
require("git.core.repo").track(args.buf)
end,
})
vim.api.nvim_create_autocmd({ "BufWritePost", "FileChangedShellPost" }, {
group = group,
callback = function(args)
require("git.core.repo").refresh(args.buf)
end,
})
vim.api.nvim_create_autocmd({ "ShellCmdPost", "TermLeave", "FocusGained" }, {
group = group,
callback = function()
require("git.core.repo").refresh_all()
end,
})
vim.api.nvim_create_autocmd({ "BufDelete", "BufWipeout" }, {
group = group,
callback = function(args)
require("git.core.repo").unbind(args.buf)
end,
})
vim.api.nvim_create_autocmd("VimLeavePre", {
group = group,
callback = function()
require("git.core.repo").stop_all()
end,
})
vim.api.nvim_create_autocmd({ "VimEnter", "DirChanged", "TabEnter" }, {
group = group,
callback = function()
require("git.core.repo").update_cwd_repo()
end,
})
vim.api.nvim_create_autocmd("TabClosed", {
group = group,
callback = function(args)
local tab = tonumber(args.file) --[[@as integer?]]
if tab then
require("git.core.repo").release_tab(tab)
end
end,
})
vim.api.nvim_create_autocmd("BufReadCmd", {
pattern = "git://*",
group = group,
callback = function(args)
require("git.object").read_uri(args.buf)
end,
})
vim.api.nvim_create_autocmd("BufReadCmd", {
pattern = "gitlog://*",
group = group,
callback = function(args)
require("git.log_view").read_uri(args.buf)
end,
})
vim.api.nvim_create_autocmd("BufReadCmd", {
pattern = "gitstatus://*",
group = group,
callback = function(args)
require("git.status_view").read_uri(args.buf)
end,
})
vim.api.nvim_create_user_command("G", function(opts)
local cmd = require("git.cmd")
cmd.run(cmd.parse_args(opts.args), { bang = opts.bang })
end, {
nargs = "*",
bang = true,
complete = function(...)
return require("git.cmd").complete(...)
end,
})
vim.api.nvim_create_user_command("Grefresh", function()
require("git.core.repo").refresh_all()
end, { desc = "Refresh git status for all repos" })
vim.api.nvim_create_user_command("Glog", function(opts)
require("git.log_view").run_glog(opts)
end, {
nargs = "*",
complete = function(...)
return require("git.log_view").complete_glog(...)
end,
desc = "Show git log",
})
local function complete_rev(...)
return require("git.cmd").complete_rev(...)
end
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)
local fargs = opts.fargs
local vertical = default_vertical()
local rev_idx = 1
if fargs[1] == "vertical" then
vertical = true
rev_idx = 2
elseif fargs[1] == "horizontal" then
vertical = false
rev_idx = 2
end
require("git.diff").split({ rev = fargs[rev_idx], vertical = vertical })
end, {
nargs = "*",
complete = function(arg_lead, cmd_line, _)
local rest = cmd_line:gsub("^%s*%S+%s*", "", 1)
local trailing_space = rest == "" or rest:sub(-1):match("%s") ~= nil
local tokens = vim.split(vim.trim(rest), "%s+", { trimempty = true })
local prior = trailing_space and tokens
or vim.list_slice(tokens, 1, #tokens - 1)
local results = {}
if #prior == 0 then
for _, d in ipairs(DIFF_DIRECTIONS) do
if vim.startswith(d, arg_lead) then
table.insert(results, d)
end
end
end
local first_is_direction = prior[1] == "vertical"
or prior[1] == "horizontal"
if #prior == 0 or (#prior == 1 and first_is_direction) then
vim.list_extend(results, complete_rev(arg_lead))
end
return results
end,
desc = "Open a diff split",
})
vim.api.nvim_create_user_command("Gedit", function(opts)
vim.cmd.edit({
args = { require("git.object").URI_PREFIX .. opts.args },
magic = { file = false },
})
end, {
nargs = 1,
complete = complete_rev,
desc = "Edit a git object (<rev>)",
})
vim.api.nvim_create_user_command("Gstatus", function(opts)
require("git.status_view").open({
placement = opts.fargs[1] --[[@as ow.Git.StatusView.Placement]]
or "split",
})
end, {
nargs = "?",
complete = function()
return require("git.status_view").PLACEMENTS
end,
desc = "Open git status view",
})
vim.keymap.set("n", "<Plug>(git-edit)", function()
local rev = vim.fn.input("Edit git object: ")
if rev == "" then
return
end
vim.cmd.edit({
args = { require("git.object").URI_PREFIX .. rev },
magic = { file = false },
})
end, { silent = true, desc = "Edit a git object" })
vim.keymap.set("n", "<Plug>(git-diff-vertical)", function()
require("git.diff").split({ vertical = true })
end, { silent = true, desc = "Diff against index (vertical)" })
vim.keymap.set("n", "<Plug>(git-diff-horizontal)", function()
require("git.diff").split({ vertical = false })
end, { silent = true, desc = "Diff against index (horizontal)" })
vim.keymap.set("n", "<Plug>(git-diff-vertical-head)", function()
require("git.diff").split({ rev = "HEAD", vertical = true })
end, { silent = true, desc = "Diff against HEAD (vertical)" })
vim.keymap.set("n", "<Plug>(git-diff-horizontal-head)", function()
require("git.diff").split({ rev = "HEAD", vertical = false })
end, { silent = true, desc = "Diff against HEAD (horizontal)" })
vim.keymap.set("n", "<Plug>(git-status-toggle)", function()
require("git.status_view").toggle()
end, { silent = true, desc = "Toggle git status sidebar" })
vim.keymap.set("n", "<Plug>(git-log)", function()
require("git.log_view").open({ max_count = 1000 })
end, { silent = true, desc = "Open git log" })
vim.keymap.set("n", "<Plug>(git-commit)", function()
require("git.commit").commit()
end, { silent = true, desc = "Start a git commit" })
vim.keymap.set("n", "<Plug>(git-commit-amend)", function()
require("git.commit").commit({ args = { "--amend" } })
end, { silent = true, desc = "Amend the last git commit" })
if vim.g.git_statusline ~= false then
vim.api.nvim_create_autocmd("BufWinEnter", {
group = group,
once = true,
callback = function()
require("git.statusline")
end,
})
end