summaryrefslogtreecommitdiffstats
path: root/.config/nvim/plugin/50-git.lua
blob: 4fcdecfee65c5b4b2f21cbbf99ecd732d1fa6a97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
--
-- Git-related utilities
--

vim.keymap.set("n", "<Leader>gt", "<Cmd>GitGutterLineHighlightsToggle<CR>", { desc = "Toggle git line highlighting" })
vim.keymap.set("n", "<Leader>gg", "<Cmd>GitGutter<CR>", { desc = "Refresh GitGutter" })
vim.keymap.set("n", "<Leader>gq", "<Cmd>GitGutterQuickFix<CR>", { desc = "Git hunks to quickfix list" })
vim.keymap.set("n", "<Leader>gz", "<Cmd>GitGutterFold<CR>", { desc = "Fold everything except git diff" })

local function git_blame(file, line)
	local sys = vim.system({
		vim.fn.stdpath("config") .. "/scripts/git_blame.bash",
		tostring(line),
		file,
	}, { text = true }):wait()
	if sys.stdout then
		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
		vim.notify(err_msg, vim.log.levels.ERROR)
	end
end

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" })