diff --git a/neovim/.config/nvim/after/plugin/remaps.lua b/neovim/.config/nvim/after/plugin/remaps.lua index 43d92e0..da76c34 100644 --- a/neovim/.config/nvim/after/plugin/remaps.lua +++ b/neovim/.config/nvim/after/plugin/remaps.lua @@ -16,3 +16,5 @@ vim.keymap.set("n", "tn", ":tabnew") vim.keymap.set("n", "tN", ":-tabnew") vim.keymap.set("n", "H", ":tabprev") vim.keymap.set("n", "L", ":tabnext") + +vim.keymap.set("n", "gl", require("daniil.gitblame").open_blame_window) diff --git a/neovim/.config/nvim/lua/daniil/gitblame.lua b/neovim/.config/nvim/lua/daniil/gitblame.lua new file mode 100644 index 0000000..8497496 --- /dev/null +++ b/neovim/.config/nvim/lua/daniil/gitblame.lua @@ -0,0 +1,47 @@ +local u = require("daniil.utils") + +local M = {} + +---@param line number +---@param path string +---@return string +local function get_commit_hash_at_line(line, path) + local cmd = vim.system({ "git", "blame", "-L", line .. "," .. line, "-p", "--", path }, { text = true }):wait() + + local lines = {} + for s in cmd.stdout:gmatch("[^\r\n]+") do + table.insert(lines, s) + end + + local commit_hash = lines[1]:gmatch("[^%s]+")() -- why I need to call this here but not above. i don't understand + return commit_hash +end + +---@param hash string +---@param dir string +---@return string +local function get_commit_info(hash, dir) + local cmd = vim.system({ "git", "-C", dir, "show", hash }, { text = true }):wait() + return cmd.stdout +end + +function M.open_blame_window() + local cursor = vim.api.nvim_win_get_cursor(0) + local line = cursor[1] + local buf_name = vim.fn.expand("%:.") + + local commit_hash = get_commit_hash_at_line(line, buf_name) + local commit_info = get_commit_info(commit_hash, vim.uv.cwd()) + + local bufnr, winnr = u.create_floating_window_in_center(0.75, 0.75) + u.set_buffer_text(bufnr, commit_info) + + vim.bo[bufnr].filetype = "gitcommit" + + vim.keymap.set("n", "", ":q", { buffer = bufnr }) + vim.keymap.set("n", "q", ":q", { buffer = bufnr }) + + -- TODO: open not at the top of the buffer, but on line in OG file +end + +return M diff --git a/neovim/.config/nvim/lua/daniil/utils.lua b/neovim/.config/nvim/lua/daniil/utils.lua new file mode 100644 index 0000000..fc14b66 --- /dev/null +++ b/neovim/.config/nvim/lua/daniil/utils.lua @@ -0,0 +1,43 @@ +local M = {} + +---@return number width, number height +function M.get_terminal_size() + local width = vim.o.columns + local height = vim.o.lines + return width, height +end + +---@param width number width in percentage of screen width (0.75, 0.5, etc) +---@param height number height in percentage of screen height (0.75, 0.5, etc) +---@return number buffer, number window +function M.create_floating_window_in_center(width, height) + local bufnr = vim.api.nvim_create_buf(false, true) -- not listed, scratch buffer + + local max_width, max_height = M.get_terminal_size() + local win_width = math.floor(max_width * width) + local win_height = math.floor(max_height * height) + + local winnr = vim.api.nvim_open_win(bufnr, true, { + relative = "editor", + width = win_width, + height = win_height, + row = (max_height - win_height) / 2, + col = (max_width - win_width) / 2, + focusable = true, + style = "minimal", + }) + + return bufnr, winnr +end + +---@param bufnr number +---@param content string +function M.set_buffer_text(bufnr, content) + local lines = {} + for s in content:gmatch("[^\r\n]+") do + table.insert(lines, s) + end + vim.api.nvim_buf_set_lines(bufnr, 0, vim.tbl_count(lines), false, lines) +end + +return M