diff --git a/lua/guh/config.lua b/lua/guh/config.lua index a573cc0..2cedcc0 100644 --- a/lua/guh/config.lua +++ b/lua/guh/config.lua @@ -13,6 +13,7 @@ M.s = { html_comments_command = { 'lynx', '-stdin', '-dump' }, keymaps = { diff = { + comment = 'cc', open_file = 'gf', open_file_tab = '', open_file_split = 'o', @@ -27,7 +28,7 @@ M.s = { approve = 'cA', request_changes = 'cR', merge = 'cM', - comment = 'ca', + comment = 'cc', diff = 'cp', }, }, diff --git a/lua/guh/diff.lua b/lua/guh/diff.lua index a4910c7..60c564a 100644 --- a/lua/guh/diff.lua +++ b/lua/guh/diff.lua @@ -79,13 +79,12 @@ function M.load_pr_diff() local diff_content_lines = vim.split(diff_content, '\n') construct_mappings(diff_content_lines, function() vim.schedule(function() - vim.api.nvim_buf_set_name( - buf, - 'PR Diff: ' .. selected_pr.number .. ' (' .. os.date('%Y-%m-%d %H:%M:%S') .. ')' - ) + buf = state.try_set_buf_name(buf, 'diff', selected_pr.number) state.diff_buffer_id = buf vim.bo[buf].buftype = 'nofile' + vim.bo[buf].readonly = false + vim.bo[buf].modifiable = true vim.api.nvim_buf_set_lines(buf, 0, -1, false, diff_content_lines) @@ -99,65 +98,43 @@ function M.load_pr_diff() vim.bo[buf].readonly = true vim.bo[buf].modifiable = false - if not utils.is_empty(config.s.keymaps.diff.open_file) then - vim.api.nvim_buf_set_keymap( - buf, - 'n', - config.s.keymaps.diff.open_file, - '', - { desc = 'Open file', noremap = true, silent = true, callback = open_file_from_diff('edit') } - ) - end - - if not utils.is_empty(config.s.keymaps.diff.open_file_tab) then - vim.api.nvim_buf_set_keymap( - buf, - 'n', - config.s.keymaps.diff.open_file_tab, - '', - { desc = 'Open file in tab', noremap = true, silent = true, callback = open_file_from_diff('tabedit') } - ) - end - - if not utils.is_empty(config.s.keymaps.diff.open_file_split) then - vim.api.nvim_buf_set_keymap( - buf, - 'n', - config.s.keymaps.diff.open_file_split, - '', - { desc = 'Open file in split', noremap = true, silent = true, callback = open_file_from_diff('split') } - ) - end - - if not utils.is_empty(config.s.keymaps.diff.open_file_vsplit) then - vim.api.nvim_buf_set_keymap( - buf, - 'n', - config.s.keymaps.diff.open_file_vsplit, - '', - { desc = 'Open file in vertical split', noremap = true, silent = true, callback = open_file_from_diff('vsplit') } - ) - end - - if not utils.is_empty(config.s.keymaps.diff.approve) then - vim.api.nvim_buf_set_keymap( - buf, - 'n', - config.s.keymaps.diff.approve, - '', - { desc = 'Approve PR', noremap = true, silent = true, callback = pr_commands.approve_pr } - ) - end - - if not utils.is_empty(config.s.keymaps.diff.request_changes) then - vim.api.nvim_buf_set_keymap( - buf, - 'n', - config.s.keymaps.diff.request_changes, - '', - { desc = 'Request PR changes', noremap = true, silent = true, callback = pr_commands.request_changes_pr } - ) - end + utils.buf_keymap(buf, 'n', config.s.keymaps.diff.open_file, 'Open file', open_file_from_diff('edit')) + utils.buf_keymap( + buf, + 'n', + config.s.keymaps.diff.comment, + 'Comment on current line', + 'GuhCommentLine' + ) + utils.buf_keymap( + buf, + 'n', + config.s.keymaps.diff.open_file_tab, + 'Open file in tab', + open_file_from_diff('tabedit') + ) + utils.buf_keymap( + buf, + 'n', + config.s.keymaps.diff.open_file_split, + 'Open file in split', + open_file_from_diff('split') + ) + utils.buf_keymap( + buf, + 'n', + config.s.keymaps.diff.open_file_vsplit, + 'Open file in vertical split', + open_file_from_diff('vsplit') + ) + utils.buf_keymap(buf, 'n', config.s.keymaps.diff.approve, 'Approve PR', pr_commands.approve_pr) + utils.buf_keymap( + buf, + 'n', + config.s.keymaps.diff.request_changes, + 'Request PR changes', + pr_commands.request_changes_pr + ) progress('success') progress = utils.new_progress_report('Loading diff comments') diff --git a/lua/guh/gh.lua b/lua/guh/gh.lua index 5a8c059..9676678 100644 --- a/lua/guh/gh.lua +++ b/lua/guh/gh.lua @@ -20,28 +20,26 @@ end function M.get_current_pr(cb) utils.system_str_cb( 'gh pr view --json headRefName,headRefOid,number,baseRefName,baseRefOid,reviewDecision', - vim.schedule_wrap( - function(result, stderr) - local prefix = 'Unknown JSON field' - if result == nil then - cb(nil) - return - elseif string.sub(stderr, 1, #prefix) == prefix then - utils.system_str_cb( - 'gh pr view --json headRefName,headRefOid,number,baseRefName,reviewDecision', - function(result2) - if result2 == nil then - cb(nil) - return - end - cb(parse_or_default(result2, nil)) + vim.schedule_wrap(function(result, stderr) + local prefix = 'Unknown JSON field' + if result == nil then + cb(nil) + return + elseif string.sub(stderr, 1, #prefix) == prefix then + utils.system_str_cb( + 'gh pr view --json headRefName,headRefOid,number,baseRefName,reviewDecision', + function(result2) + if result2 == nil then + cb(nil) + return end - ) - else - cb(parse_or_default(result, nil)) - end + cb(parse_or_default(result2, nil)) + end + ) + else + cb(parse_or_default(result, nil)) end - ) + end) ) end diff --git a/lua/guh/pr_commands.lua b/lua/guh/pr_commands.lua index f7c9a46..ec0e71b 100644 --- a/lua/guh/pr_commands.lua +++ b/lua/guh/pr_commands.lua @@ -166,10 +166,12 @@ local function show_pr_info(pr_info) end local buf = state.get_buf('info', pr_info.number) - vim.api.nvim_buf_set_name(buf, 'PR View: ' .. pr_info.number .. ' (' .. os.date('%Y-%m-%d %H:%M:%S') .. ')') + buf = state.try_set_buf_name(buf, 'info', pr_info.number) vim.bo[buf].buftype = 'nofile' vim.bo[buf].filetype = 'markdown' + vim.bo[buf].readonly = false + vim.bo[buf].modifiable = true vim.api.nvim_buf_set_lines(buf, 0, -1, false, pr_view) @@ -181,52 +183,13 @@ local function show_pr_info(pr_info) vim.bo[buf].readonly = true vim.bo[buf].modifiable = false - if not utils.is_empty(config.s.keymaps.pr.approve) then - vim.api.nvim_buf_set_keymap( - buf, - 'n', - config.s.keymaps.pr.approve, - '', - { desc = 'Approve PR', noremap = true, silent = true, callback = M.approve_pr } - ) - end - if not utils.is_empty(config.s.keymaps.pr.request_changes) then - vim.api.nvim_buf_set_keymap( - buf, - 'n', - config.s.keymaps.pr.request_changes, - '', - { desc = 'Request PR changes', noremap = true, silent = true, callback = M.request_changes_pr } - ) - end - if not utils.is_empty(config.s.keymaps.pr.merge) then - vim.api.nvim_buf_set_keymap( - buf, - 'n', - config.s.keymaps.pr.merge, - '', - { desc = 'Merge PR in remote repo', noremap = true, silent = true, callback = M.merge_pr } - ) - end - if not utils.is_empty(config.s.keymaps.pr.comment) then - vim.api.nvim_buf_set_keymap(buf, 'n', config.s.keymaps.pr.comment, '', { - desc = 'Comment on PR', - noremap = true, - silent = true, - callback = function() - M.comment_on_pr(M.load_pr_view) - end, - }) - end - if not utils.is_empty(config.s.keymaps.pr.diff) then - vim.api.nvim_buf_set_keymap( - buf, - 'n', - config.s.keymaps.pr.diff, - ':GuhDiff', - { desc = 'View the PR diff', noremap = true, silent = true } - ) - end + utils.buf_keymap(buf, 'n', config.s.keymaps.pr.approve, 'Approve PR', M.approve_pr) + utils.buf_keymap(buf, 'n', config.s.keymaps.pr.request_changes, 'Request PR changes', M.request_changes_pr) + utils.buf_keymap(buf, 'n', config.s.keymaps.pr.merge, 'Merge PR in remote repo', M.merge_pr) + utils.buf_keymap(buf, 'n', config.s.keymaps.pr.comment, 'Comment on PR', function() + M.comment_on_pr(M.load_pr_view) + end) + utils.buf_keymap(buf, 'n', config.s.keymaps.pr.diff, 'View the PR diff', ':GuhDiff') vim.bo.busy = 0 end) @@ -238,7 +201,9 @@ local function load_pr_view_for_pr(selected_pr) return end - vim.bo.busy = 1 + vim.schedule(function() + vim.bo.busy = 1 + end) gh.get_pr_info(selected_pr.number, show_pr_info) end diff --git a/lua/guh/state.lua b/lua/guh/state.lua index 64a02d6..70625b7 100644 --- a/lua/guh/state.lua +++ b/lua/guh/state.lua @@ -11,33 +11,45 @@ M.comments_list = {} --- @type integer|nil Diff view buffer id M.diff_buffer_id = nil ---- @type table> -M.filename_line_to_diff_line = {} - ---- @type table -M.diff_line_to_filename_line = {} - --- feat+prnum => bufnr local bufs = { ---@type table - diff = { - }, + diff = {}, ---@type table - info = { - }, + info = {}, } --- Gets the buf for the given PR + feature, or creates a new one if not found. --- @param feat 'diff'|'info' ---- @param prnum string +--- @param prnum string|number function M.get_buf(feat, prnum) local prnumstr = tostring(prnum) local b = bufs[feat][prnumstr] if type(b) ~= 'number' or vim.api.nvim_buf_is_valid(b) then - b = vim.api.nvim_create_buf(false, true) + b = vim.api.nvim_create_buf(true, true) bufs[feat][prnumstr] = b + assert(type(b) == 'number') end return b end +function M.try_set_buf_name(buf, feat, prnum) + local bufname = ('guh://%s/%s'):format(feat, prnum) + local foundbuf = vim.fn.bufnr(bufname) + if foundbuf > 0 and buf ~= foundbuf then + vim.api.nvim_set_current_buf(foundbuf) + -- XXX fucking hack because Vim creates new buffer after (re)naming it. + bufs[feat][tostring(prnum)] = foundbuf + return foundbuf + end + -- if not vim.api.nvim_buf_get_name(buf):match('guh%:') then + vim.api.nvim_buf_set_name(buf, ('guh://%s/%s'):format(feat, prnum)) + -- XXX fucking hack because Vim creates new buffer after (re)naming it. + bufs[feat][tostring(prnum)] = buf + return buf + -- end +end + +M.bufs = bufs + return M diff --git a/lua/guh/utils.lua b/lua/guh/utils.lua index 8866d06..0d36615 100644 --- a/lua/guh/utils.lua +++ b/lua/guh/utils.lua @@ -80,6 +80,17 @@ function M.new_progress_report(action) end) end +function M.buf_keymap(buf, mode, lhs, desc, rhs) + if not M.is_empty(lhs) then + local opts = {} + opts.desc = opts.desc == nil and desc or opts.desc + opts.noremap = opts.noremap == nil and true or opts.noremap + opts.silent = opts.silent == nil and true or opts.silent + opts.buffer = buf + vim.keymap.set(mode, lhs, rhs, opts) + end +end + function M.get_comment(buf_name, split_command, prompt, content, key_binding, callback) local buf = vim.api.nvim_create_buf(false, true) vim.api.nvim_buf_set_name(buf, buf_name) @@ -105,20 +116,8 @@ function M.get_comment(buf_name, split_command, prompt, content, key_binding, ca callback(input) end - vim.api.nvim_buf_set_keymap( - buf, - 'n', - key_binding, - '', - { noremap = true, silent = true, callback = capture_input_and_close } - ) - vim.api.nvim_buf_set_keymap( - buf, - 'i', - key_binding, - '', - { noremap = true, silent = true, callback = capture_input_and_close } - ) + M.buf_keymap(buf, 'n', key_binding, '', capture_input_and_close) + M.buf_keymap(buf, 'i', key_binding, '', capture_input_and_close) end return M diff --git a/plugin/guh.lua b/plugin/guh.lua index 67d62cf..fafe093 100644 --- a/plugin/guh.lua +++ b/plugin/guh.lua @@ -1 +1 @@ -require('guh').setup{} +require('guh').setup({})