Files
nvim/lua/git/init.lua
T

138 lines
4.5 KiB
Lua

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", "<leader>gg", function()
require("git.sidebar").toggle()
end, { desc = "Toggle git status sidebar" })
vim.keymap.set("n", "<leader>gl", function()
require("git.log").show()
end, { desc = "Show git log" })
vim.keymap.set("n", "<leader>gd", function()
require("git.diff").split({ ref = "", vertical = true })
end, { desc = "Diff index vs worktree (vsplit)" })
vim.keymap.set("n", "<leader>gD", function()
require("git.diff").split({ ref = "HEAD", vertical = true })
end, { desc = "Diff HEAD vs worktree (vsplit)" })
vim.keymap.set("n", "<leader>gh", function()
require("git.diff").split({ ref = "", vertical = false })
end, { desc = "Diff index vs worktree (split)" })
vim.keymap.set("n", "<leader>gH", function()
require("git.diff").split({ ref = "HEAD", vertical = false })
end, { desc = "Diff HEAD vs worktree (split)" })
vim.keymap.set("n", "<leader>gc", function()
require("git.commit").commit()
end, { desc = "Git commit" })
vim.keymap.set("n", "<leader>ga", function()
require("git.commit").commit({ amend = true })
end, { desc = "Git commit --amend" })
vim.keymap.set("n", "<leader>gp", function()
require("git.cmd").run({ "push" })
end, { desc = "Git push" })
require("git.cmd").setup()
end
return M