diff options
| -rw-r--r-- | .config/nvim/plugin/50-git.lua | 70 | ||||
| -rwxr-xr-x | .config/nvim/scripts/git_blame.bash | 10 |
2 files changed, 67 insertions, 13 deletions
diff --git a/.config/nvim/plugin/50-git.lua b/.config/nvim/plugin/50-git.lua index c7177b2..4fcdecf 100644 --- a/.config/nvim/plugin/50-git.lua +++ b/.config/nvim/plugin/50-git.lua @@ -9,17 +9,12 @@ vim.keymap.set("n", "<Leader>gz", "<Cmd>GitGutterFold<CR>", { desc = "Fold every local function git_blame(file, line) local sys = vim.system({ - "bash", - "-c", - string.format( - 'grep -E --only-matching "^author .*$|^summary .*$|^[[:xdigit:]]{40}" <(git blame -L %d,%d --porcelain -- %s)', - line, - line, - file - ), - }):wait() + vim.fn.stdpath("config") .. "/scripts/git_blame.bash", + tostring(line), + file, + }, { text = true }):wait() if sys.stdout then - vim.notify(sys.stdout, vim.log.levels.INFO) + return vim.split(sys.stdout, "\n", { trimempty = true }) end if sys.code ~= 0 then local err_msg = "git blame failed (" .. sys.code .. ")\n" .. sys.stderr @@ -27,6 +22,55 @@ local function git_blame(file, line) end end -vim.api.nvim_create_user_command("GitBlame", function() - git_blame(vim.api.nvim_buf_get_name(0), vim.api.nvim_win_get_cursor(0)[1]) -end, { desc = "Show current line git blame" }) +local git_blame_toggle = (function() + local win, auid, buf + + local function close() + if win and vim.api.nvim_win_is_valid(win) then + vim.api.nvim_win_close(win, true) + end + if buf and vim.api.nvim_buf_is_valid(buf) then + vim.api.nvim_buf_delete(buf, { force = true }) + end + win, auid, buf = nil, nil, nil + end + + return function() + if win and vim.api.nvim_win_is_valid(win) then + if auid then + vim.api.nvim_del_autocmd(auid) + end + vim.api.nvim_set_current_win(win) + vim.api.nvim_create_autocmd("BufLeave", { + once = true, + callback = close, + }) + return + end + + local text = git_blame(vim.api.nvim_buf_get_name(0), vim.api.nvim_win_get_cursor(0)[1]) + if not text then + return + end + + buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_lines(buf, 0, -1, false, text) + win = vim.api.nvim_open_win(buf, false, { + relative = "cursor", + width = 50, + height = #text, + row = 0, + col = 0, + style = "minimal", + border = "rounded", + title = "git blame", + noautocmd = true, + }) + auid = vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI", "BufLeave" }, { + once = true, + callback = close, + }) + end +end)() + +vim.api.nvim_create_user_command("GitBlame", git_blame_toggle, { desc = "Open/enter git blame window" }) diff --git a/.config/nvim/scripts/git_blame.bash b/.config/nvim/scripts/git_blame.bash new file mode 100755 index 0000000..b197081 --- /dev/null +++ b/.config/nvim/scripts/git_blame.bash @@ -0,0 +1,10 @@ +#!/usr/bin/bash +set -euo pipefail + +line="${1:?line argument missing}" +file="${2:?file argument missing}" +sha=$(git blame -L "$line,$line" --porcelain -- "$file" | + head -1 | + grep -Eo '[[:xdigit:]]+' | + head -1) +git log -1 "$sha" |
