local api = vim.api
local M = {}
M.state = {
buf = nil,
win = nil,
commits = {},
selected = {},
cursor = 1,
}
function M.open(commits)
M.state.commits = commits
M.state.selected = {}
M.state.cursor = 1
M.state.buf = api.nvim_create_buf(false, true)
vim.bo[M.state.buf].buftype = "nofile"
vim.bo[M.state.buf].bufhidden = "wipe"
vim.bo[M.state.buf].swapfile = false
vim.bo[M.state.buf].filetype = "gitlogdiff"
local width = 90
local height = math.min(#commits + 2, 30)
local row = math.floor((vim.o.lines - height) / 2)
local col = math.floor((vim.o.columns - width) / 2)
M.state.win = api.nvim_open_win(M.state.buf, true, {
relative = "editor",
width = width,
height = height,
row = row,
col = col,
,
border = "rounded",
title = "Git Commits",
title_pos = "center",
})
vim.wo[M.state.win].cursorline = true
M.render()
M.keymaps()
end
function M.render()
local lines = {}
for i, c in ipairs(M.state.commits) do
local mark = M.state.selected[i] and "" or ""
table.insert(lines, mark .. " " .. c)
end
vim.bo[M.state.buf].modifiable = true
api.nvim_buf_set_lines(M.state.buf, 0, -1, false, lines)
vim.bo[M.state.buf].modifiable = false
api.nvim_win_set_cursor(M.state.win, { M.state.cursor, 0 })
end
function M.move(delta)
M.state.cursor = math.max(1, math.min(#M.state.commits, M.state.cursor + delta))
M.render()
end
function M.toggle()
local i = M.state.cursor
M.state.selected[i] = not M.state.selected[i]
M.render()
end
function M.get_selected_indices()
local indices = {}
for i = 1, #M.state.commits do
if M.state.selected[i] then
table.insert(indices, i)
end
end
return indices
end
function M.get_selected_hashes()
local hashes = {}
local indices = M.get_selected_indices()
for _, i in ipairs(indices) do
local h = M.state.commits[i]:match("^(%w+)")
if h then
table.insert(hashes, h)
end
end
return hashes
end
function M.keymaps()
local opts = { buffer = M.state.buf, silent = true }
vim.keymap.set("n", "j", function()
M.move(1)
end, opts)
vim.keymap.set("n", "k", function()
M.move(-1)
end, opts)
vim.keymap.set("n", "", M.toggle, opts)
vim.keymap.set("n", "", function()
local ui = require("gitlogdiff.ui")
require("gitlogdiff.actions").show_selected(ui.get_selected_hashes(), ui.get_selected_indices())
end, opts)
vim.keymap.set("n", "q", function()
if M.state.win and api.nvim_win_is_valid(M.state.win) then
api.nvim_win_close(M.state.win, true)
end
end, opts)
end
return M