|
| 1 | +local api = vim.api |
| 2 | +local snacks = require("snacks") |
| 3 | + |
| 4 | +local M = {} |
| 5 | + |
| 6 | +M.state = { |
| 7 | + buf = nil, |
| 8 | + win = nil, |
| 9 | + commits = {}, |
| 10 | + selected = {}, |
| 11 | + cursor = 1, |
| 12 | +} |
| 13 | + |
| 14 | +function M.open(commits) |
| 15 | + M.state.commits = commits |
| 16 | + M.state.selected = {} |
| 17 | + M.state.cursor = 1 |
| 18 | + |
| 19 | + M.state.buf = api.nvim_create_buf(false, true) |
| 20 | + vim.bo[M.state.buf].buftype = "nofile" |
| 21 | + vim.bo[M.state.buf].bufhidden = "wipe" |
| 22 | + vim.bo[M.state.buf].swapfile = false |
| 23 | + vim.bo[M.state.buf].filetype = "gitlogdiff" |
| 24 | + |
| 25 | + M.state.win_obj = snacks.win({ |
| 26 | + buf = M.state.buf, |
| 27 | + width = 90, |
| 28 | + height = math.min(#commits + 2, 30), |
| 29 | + title = "Git Commits", |
| 30 | + border = "rounded", |
| 31 | + }) |
| 32 | + M.state.win = M.state.win_obj.win |
| 33 | + vim.wo[M.state.win].cursorline = true |
| 34 | + |
| 35 | + M.render() |
| 36 | + M.keymaps() |
| 37 | +end |
| 38 | + |
| 39 | +function M.render() |
| 40 | + local lines = {} |
| 41 | + for i, c in ipairs(M.state.commits) do |
| 42 | + local mark = M.state.selected[i] and "●" or "○" |
| 43 | + table.insert(lines, mark .. " " .. c) |
| 44 | + end |
| 45 | + |
| 46 | + vim.bo[M.state.buf].modifiable = true |
| 47 | + api.nvim_buf_set_lines(M.state.buf, 0, -1, false, lines) |
| 48 | + vim.bo[M.state.buf].modifiable = false |
| 49 | + api.nvim_win_set_cursor(M.state.win, { M.state.cursor, 0 }) |
| 50 | +end |
| 51 | + |
| 52 | +function M.move(delta) |
| 53 | + M.state.cursor = math.max(1, math.min(#M.state.commits, M.state.cursor + delta)) |
| 54 | + M.render() |
| 55 | +end |
| 56 | + |
| 57 | +function M.toggle() |
| 58 | + local i = M.state.cursor |
| 59 | + M.state.selected[i] = not M.state.selected[i] |
| 60 | + M.render() |
| 61 | +end |
| 62 | + |
| 63 | +function M.get_selected_hashes() |
| 64 | + local hashes = {} |
| 65 | + for i, ok in pairs(M.state.selected) do |
| 66 | + if ok then |
| 67 | + local h = M.state.commits[i]:match("^(%w+)") |
| 68 | + table.insert(hashes, h) |
| 69 | + end |
| 70 | + end |
| 71 | + return hashes |
| 72 | +end |
| 73 | + |
| 74 | +function M.keymaps() |
| 75 | + local opts = { buffer = M.state.buf, silent = true } |
| 76 | + |
| 77 | + vim.keymap.set("n", "j", function() M.move(1) end, opts) |
| 78 | + vim.keymap.set("n", "k", function() M.move(-1) end, opts) |
| 79 | + vim.keymap.set("n", "<space>", M.toggle, opts) |
| 80 | + |
| 81 | + vim.keymap.set("n", "<CR>", function() |
| 82 | + require("gitlogdiff.actions").show_selected(M.get_selected_hashes()) |
| 83 | + end, opts) |
| 84 | + |
| 85 | + vim.keymap.set("n", "q", function() |
| 86 | + M.state.win_obj:close() |
| 87 | + end, opts) |
| 88 | +end |
| 89 | + |
| 90 | +return M |
0 commit comments