From 217390cfa42717306f24dc2f1338f2bffc4ce8b4 Mon Sep 17 00:00:00 2001 From: Oscar Wallberg Date: Thu, 30 Apr 2026 15:05:47 +0200 Subject: [PATCH] feat(git): :Glog command, per-module setup, plugin/ auto-init --- init.lua | 2 - lua/core/keymap.lua | 25 ++++++++++ lua/git/cmd.lua | 1 - lua/git/diff.lua | 27 +++++++++++ lua/git/init.lua | 110 ++------------------------------------------ lua/git/log.lua | 50 ++++++++++++++++++++ lua/git/object.lua | 11 +++++ lua/git/repo.lua | 31 +++++++++++++ plugin/git.lua | 4 ++ 9 files changed, 153 insertions(+), 108 deletions(-) create mode 100644 plugin/git.lua diff --git a/init.lua b/init.lua index 96ca68a..5e971b5 100644 --- a/init.lua +++ b/init.lua @@ -22,8 +22,6 @@ for _, file in ipairs(files) do end end -require("git").setup() - require("pack").setup({ "https://github.com/navarasu/onedark.nvim", "https://github.com/ibhagwan/fzf-lua", diff --git a/lua/core/keymap.lua b/lua/core/keymap.lua index 51da8b5..5ee4ecc 100644 --- a/lua/core/keymap.lua +++ b/lua/core/keymap.lua @@ -229,3 +229,28 @@ vim.keymap.set("n", "fd", vim.diagnostic.setloclist) vim.keymap.set("n", "fD", vim.diagnostic.setqflist) vim.keymap.set("n", "grt", vim.lsp.buf.type_definition) vim.keymap.set("n", "gd", vim.lsp.buf.definition) + +vim.keymap.set("n", "gd", function() + require("git.diff").split({ vertical = true }) +end) +vim.keymap.set("n", "gD", function() + require("git.diff").split({ rev = "HEAD", vertical = true }) +end) +vim.keymap.set("n", "gh", function() + require("git.diff").split({ vertical = false }) +end) +vim.keymap.set("n", "gH", function() + require("git.diff").split({ rev = "HEAD", vertical = false }) +end) +vim.keymap.set("n", "gg", function() + require("git.sidebar").toggle() +end) +vim.keymap.set("n", "gc", function() + require("git.commit").commit() +end) +vim.keymap.set("n", "ga", function() + require("git.commit").commit({ amend = true }) +end) +vim.keymap.set("n", "gl", function() + require("git.log").open({ max_count = 1000 }) +end) diff --git a/lua/git/cmd.lua b/lua/git/cmd.lua index 700553f..c59866b 100644 --- a/lua/git/cmd.lua +++ b/lua/git/cmd.lua @@ -255,7 +255,6 @@ function M.setup() end, { nargs = "*", complete = complete, - desc = "Run git", }) end diff --git a/lua/git/diff.lua b/lua/git/diff.lua index bec9b4f..fbbc20c 100644 --- a/lua/git/diff.lua +++ b/lua/git/diff.lua @@ -185,4 +185,31 @@ function M.split(opts) place_pair(buf, cur_buf, true, opts.vertical) end +function M.setup() + local function diff_split_cmd(vertical) + return function(opts) + M.split({ + rev = opts.args ~= "" and opts.args or nil, + vertical = vertical, + }) + end + end + + vim.api.nvim_create_user_command( + "Gdiffsplit", + diff_split_cmd(true), + { nargs = "?", desc = "Diff against " } + ) + vim.api.nvim_create_user_command( + "Gvdiffsplit", + diff_split_cmd(true), + { nargs = "?", desc = "Diff against (vertical split)" } + ) + vim.api.nvim_create_user_command( + "Ghdiffsplit", + diff_split_cmd(false), + { nargs = "?", desc = "Diff against (horizontal split)" } + ) +end + return M diff --git a/lua/git/init.lua b/lua/git/init.lua index 0d7b835..bb9d078 100644 --- a/lua/git/init.lua +++ b/lua/git/init.lua @@ -17,116 +17,16 @@ function M.status() return vim.b.git_status or "" end ----@param path string ----@return string? -function M.head(path) - return require("git.repo").head(path) -end - function M.setup() - local cmd = require("git.cmd") - local commit = require("git.commit") - local diff = require("git.diff") - local log = require("git.log") - local repo = require("git.repo") - for name, link in pairs(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("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) - log.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", - require("git.sidebar").toggle, - { desc = "Toggle git status sidebar" } - ) - vim.keymap.set("n", "gl", function() - log.open({ max_count = 1000 }) - end, { desc = "Show git log" }) - vim.keymap.set("n", "gd", function() - diff.split({ vertical = true }) - end, { desc = "Diff index vs worktree (vsplit)" }) - vim.keymap.set("n", "gD", function() - diff.split({ rev = "HEAD", vertical = true }) - end, { desc = "Diff HEAD vs worktree (vsplit)" }) - vim.keymap.set("n", "gh", function() - diff.split({ vertical = false }) - end, { desc = "Diff index vs worktree (split)" }) - vim.keymap.set("n", "gH", function() - diff.split({ rev = "HEAD", vertical = false }) - end, { desc = "Diff HEAD vs worktree (split)" }) - vim.keymap.set("n", "gc", function() - commit.commit() - end, { desc = "Git commit" }) - vim.keymap.set("n", "ga", function() - commit.commit({ amend = true }) - end, { desc = "Git commit --amend" }) - vim.keymap.set("n", "gp", function() - cmd.run({ "push" }) - end, { desc = "Git push" }) - - local function diff_split_cmd(vertical) - return function(opts) - diff.split({ - rev = opts.args ~= "" and opts.args or nil, - vertical = vertical, - }) - end - end - vim.api.nvim_create_user_command( - "Gdiffsplit", - diff_split_cmd(true), - { nargs = "?", desc = "Diff against (vsplit)" } - ) - vim.api.nvim_create_user_command( - "Ghdiffsplit", - diff_split_cmd(false), - { nargs = "?", desc = "Diff against (split)" } - ) - - cmd.setup() + require("git.repo").setup() + require("git.object").setup() + require("git.diff").setup() + require("git.cmd").setup() + require("git.log").setup() end return M diff --git a/lua/git/log.lua b/lua/git/log.lua index 97f1bf1..1aec80b 100644 --- a/lua/git/log.lua +++ b/lua/git/log.lua @@ -84,6 +84,11 @@ end ---@class ow.Git.LogOpts ---@field max_count integer? +---@type table +M.opt_parsers = { + max_count = tonumber, +} + ---@param opts ow.Git.LogOpts? function M.open(opts) opts = opts or {} @@ -110,4 +115,49 @@ function M.open(opts) end end +function M.setup() + local group = vim.api.nvim_create_augroup("ow.git.log", { clear = true }) + vim.api.nvim_create_autocmd("BufReadCmd", { + pattern = "gitlog://*", + group = group, + callback = function(args) + M.read_uri(args.buf) + end, + }) + + vim.api.nvim_create_user_command("Glog", function(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, { + nargs = "*", + complete = function(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, + desc = "Show git log", + }) +end + return M diff --git a/lua/git/object.lua b/lua/git/object.lua index 6e18c1b..dca455c 100644 --- a/lua/git/object.lua +++ b/lua/git/object.lua @@ -363,4 +363,15 @@ function M.open_under_cursor() return false end +function M.setup() + local group = vim.api.nvim_create_augroup("ow.git.object", { clear = true }) + vim.api.nvim_create_autocmd("BufReadCmd", { + pattern = "git://*", + group = group, + callback = function(args) + M.read_uri(args.buf) + end, + }) +end + return M diff --git a/lua/git/repo.lua b/lua/git/repo.lua index 8aeec61..0ad219b 100644 --- a/lua/git/repo.lua +++ b/lua/git/repo.lua @@ -326,4 +326,35 @@ function M.rev_parse(worktree, rev, short) return trimmed ~= "" and trimmed or nil end +function M.setup() + local group = vim.api.nvim_create_augroup("ow.git.repo", { clear = true }) + vim.api.nvim_create_autocmd( + { "BufReadPost", "BufNewFile", "BufWritePost", "FileChangedShellPost" }, + { + group = group, + callback = function(args) + M.refresh_buf(args.buf) + end, + } + ) + vim.api.nvim_create_autocmd({ "BufDelete", "BufWipeout" }, { + group = group, + callback = function(args) + M.unregister(args.buf) + end, + }) + vim.api.nvim_create_autocmd("FocusGained", { + group = group, + callback = function() + M.refresh_buf(vim.api.nvim_get_current_buf()) + end, + }) + vim.api.nvim_create_autocmd("VimLeavePre", { + group = group, + callback = function() + M.stop_all() + end, + }) +end + return M diff --git a/plugin/git.lua b/plugin/git.lua new file mode 100644 index 0000000..b61e5a4 --- /dev/null +++ b/plugin/git.lua @@ -0,0 +1,4 @@ +if vim.g.loaded_git then return end +vim.g.loaded_git = 1 + +require("git").setup()