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 ()", }) 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", "(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", "(git-diff-vertical)", function() require("git.diff").split({ vertical = true }) end, { silent = true, desc = "Diff against index (vertical)" }) vim.keymap.set("n", "(git-diff-horizontal)", function() require("git.diff").split({ vertical = false }) end, { silent = true, desc = "Diff against index (horizontal)" }) vim.keymap.set("n", "(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", "(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", "(git-status-toggle)", function() require("git.status_view").toggle() end, { silent = true, desc = "Toggle git status sidebar" }) vim.keymap.set("n", "(git-log)", function() require("git.log_view").open({ max_count = 1000 }) end, { silent = true, desc = "Open git log" }) vim.keymap.set("n", "(git-commit)", function() require("git.commit").commit() end, { silent = true, desc = "Start a git commit" }) vim.keymap.set("n", "(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