local repo = require("git.repo") local HIGHLIGHTS = { GitDeleted = "Removed", GitIgnored = "Comment", GitUnstaged = "Changed", GitRenamed = "GitStaged", GitSha = "Identifier", GitStaged = "Constant", GitUnmerged = "Todo", GitUnpulled = "Removed", GitUnpushed = "Added", GitUntracked = "Added", } local M = {} function M.status() return vim.b.git_status or "" end ---@param path string ---@return string? function M.head(path) return repo.head(path) end ---@class ow.Git.NewScratchOpts ---@field name string? ---@field bufhidden ("hide"|"wipe")? defaults to "hide" ---@field split (false|"above"|"below"|"left"|"right")? defaults to splitbelow-aware horizontal. `false` places the buffer in the current window (drops a `'` mark first so the user can jump back). ---Create a fresh non-modifiable scratch buffer and place it. Default split ---direction is horizontal, honouring `splitbelow`. Caller flips ---`modifiable`, fills the buffer, and sets `filetype` once content lands. ---@param opts ow.Git.NewScratchOpts? ---@return integer buf ---@return integer win function M.new_scratch(opts) opts = opts or {} local buf = vim.api.nvim_create_buf(false, true) vim.bo[buf].buftype = "nofile" vim.bo[buf].bufhidden = opts.bufhidden or "hide" vim.bo[buf].swapfile = false vim.bo[buf].modifiable = false vim.bo[buf].modified = false if opts.name then pcall(vim.api.nvim_buf_set_name, buf, opts.name) end if opts.split == false then vim.cmd.normal({ "m'", bang = true }) vim.api.nvim_set_current_buf(buf) return buf, vim.api.nvim_get_current_win() end local split = opts.split or (vim.o.splitbelow and "below" or "above") local win = vim.api.nvim_open_win(buf, true, { split = split }) return buf, win end function M.setup() for name, link in pairs(HIGHLIGHTS) do vim.api.nvim_set_hl(0, name, { link = link, default = true }) end vim.filetype.add({ pattern = { ["git://.*:([^:]+)$"] = function(_, bufnr, inner) return vim.filetype.match({ filename = inner, buf = bufnr }) end, }, }) local group = vim.api.nvim_create_augroup("ow.git", { clear = true }) vim.api.nvim_create_autocmd("BufReadCmd", { pattern = "git://*", group = group, callback = function(args) require("git.diff").read_uri(args.buf) end, }) vim.api.nvim_create_autocmd( { "BufReadPost", "BufNewFile", "BufWritePost", "FileChangedShellPost" }, { group = group, callback = function(args) repo.refresh_buf(args.buf) end, } ) vim.api.nvim_create_autocmd({ "BufDelete", "BufWipeout" }, { group = group, callback = function(args) repo.unregister(args.buf) end, }) vim.api.nvim_create_autocmd("FocusGained", { group = group, callback = function() repo.refresh_buf(vim.api.nvim_get_current_buf()) end, }) vim.api.nvim_create_autocmd("VimLeavePre", { group = group, callback = function() repo.stop_all() end, }) vim.keymap.set("n", "gg", function() require("git.sidebar").toggle() end, { desc = "Toggle git status sidebar" }) vim.keymap.set("n", "gl", function() require("git.log").show() end, { desc = "Show git log" }) vim.keymap.set("n", "gd", function() require("git.diff").split({ ref = "", vertical = true }) end, { desc = "Diff index vs worktree (vsplit)" }) vim.keymap.set("n", "gD", function() require("git.diff").split({ ref = "HEAD", vertical = true }) end, { desc = "Diff HEAD vs worktree (vsplit)" }) vim.keymap.set("n", "gh", function() require("git.diff").split({ ref = "", vertical = false }) end, { desc = "Diff index vs worktree (split)" }) vim.keymap.set("n", "gH", function() require("git.diff").split({ ref = "HEAD", vertical = false }) end, { desc = "Diff HEAD vs worktree (split)" }) vim.keymap.set("n", "gc", function() require("git.commit").commit() end, { desc = "Git commit" }) vim.keymap.set("n", "ga", function() require("git.commit").commit({ amend = true }) end, { desc = "Git commit --amend" }) vim.keymap.set("n", "gp", function() require("git.cmd").run({ "push" }) end, { desc = "Git push" }) require("git.cmd").setup() end return M