mirror of
https://github.com/folke/snacks.nvim
synced 2025-12-23 08:47:57 +00:00
feat(gh): when on a review comment, the gh_comment action will now do a reply instead of a top-level comment. Fixes #2410
This commit is contained in:
parent
2099572fe8
commit
a4f2b9da2d
5 changed files with 77 additions and 10 deletions
|
|
@ -6,6 +6,7 @@ local M = {}
|
|||
---@class snacks.gh.action.ctx
|
||||
---@field items snacks.picker.gh.Item[]
|
||||
---@field picker? snacks.Picker
|
||||
---@field main? number
|
||||
---@field action? snacks.picker.Action
|
||||
|
||||
---@class snacks.gh.cli.Action.ctx
|
||||
|
|
@ -79,6 +80,7 @@ M.actions.gh_actions = {
|
|||
if ctx.action and ctx.action.cmd then
|
||||
return Snacks.picker.actions.jump(ctx.picker, item, ctx.action)
|
||||
end
|
||||
ctx.main = ctx.main or ctx.picker and ctx.picker.main or nil
|
||||
local actions = M.get_actions(item)
|
||||
actions.gh_actions = nil -- remove this action
|
||||
actions.gh_perform_action = nil -- remove this action
|
||||
|
|
@ -103,6 +105,7 @@ M.actions.gh_actions = {
|
|||
if ctx.picker then
|
||||
ctx.picker:focus()
|
||||
end
|
||||
ctx.main = ctx.main or picker and picker.main or nil
|
||||
it.action.action(item, ctx)
|
||||
picker:close()
|
||||
end,
|
||||
|
|
@ -233,6 +236,35 @@ M.actions.gh_yank = {
|
|||
end,
|
||||
}
|
||||
|
||||
M.actions.gh_comment = {
|
||||
desc = "Comment on {type} #{number}",
|
||||
icon = " ",
|
||||
action = function(item, ctx)
|
||||
local win = ctx.main or vim.api.nvim_get_current_win()
|
||||
local buf = vim.api.nvim_win_get_buf(win)
|
||||
|
||||
local action = vim.deepcopy(M.cli_actions.gh_comment)
|
||||
if item.uri == vim.api.nvim_buf_get_name(buf) then
|
||||
local lino = vim.api.nvim_win_get_cursor(win)[1]
|
||||
---@type {line:number, id:number}[]
|
||||
local comments = vim.b[buf].snacks_gh_comments or {}
|
||||
for _, c in ipairs(comments) do
|
||||
if c.line == lino then
|
||||
action.title = "Reply to comment on {type} #{number}"
|
||||
action.api = {
|
||||
endpoint = "/repos/{repo}/pulls/{number}/comments",
|
||||
input = {
|
||||
in_reply_to = c.id,
|
||||
},
|
||||
}
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
M.run(item, action, ctx)
|
||||
end,
|
||||
}
|
||||
|
||||
---@type table<string, snacks.gh.cli.Action>
|
||||
M.cli_actions = {
|
||||
gh_comment = {
|
||||
|
|
@ -570,7 +602,6 @@ function M._run(ctx, force)
|
|||
Api.request(
|
||||
cb,
|
||||
Snacks.config.merge(ctx.opts.api or {}, {
|
||||
input = ctx.input,
|
||||
args = ctx.args,
|
||||
on_error = function()
|
||||
spinner:stop()
|
||||
|
|
@ -655,10 +686,20 @@ function M.submit(ctx)
|
|||
|
||||
if body:find("%S") then
|
||||
if edit == "body-file" then
|
||||
vim.list_extend(ctx.args, { "--body-file", "-" })
|
||||
ctx.input = body
|
||||
if ctx.opts.api then
|
||||
ctx.opts.api.input = ctx.opts.api.input or {}
|
||||
ctx.opts.api.input.body = body
|
||||
else
|
||||
ctx.input = body
|
||||
vim.list_extend(ctx.args, { "--body-file", "-" })
|
||||
end
|
||||
else
|
||||
vim.list_extend(ctx.args, { "--" .. edit, body })
|
||||
if ctx.opts.api then
|
||||
ctx.opts.api.fields = ctx.opts.api.fields or {}
|
||||
ctx.opts.api.fields[edit] = body
|
||||
else
|
||||
vim.list_extend(ctx.args, { "--" .. edit, body })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ function M.request(cb, opts)
|
|||
cb(proc, data and data:find("%S") and proc:json() or nil)
|
||||
end, {
|
||||
args = args,
|
||||
input = opts.input,
|
||||
input = opts.input and vim.json.encode(opts.input) or nil,
|
||||
on_error = opts.on_error,
|
||||
})
|
||||
end
|
||||
|
|
@ -417,6 +417,7 @@ function M.comments(item, cb)
|
|||
comments(first: 50) {
|
||||
nodes {
|
||||
id
|
||||
databaseId
|
||||
body
|
||||
path
|
||||
diffHunk
|
||||
|
|
@ -427,7 +428,7 @@ function M.comments(item, cb)
|
|||
createdAt
|
||||
subjectType
|
||||
author { login }
|
||||
replyTo { id }
|
||||
replyTo { id databaseId }
|
||||
reactionGroups {
|
||||
content
|
||||
users { totalCount }
|
||||
|
|
@ -439,6 +440,7 @@ function M.comments(item, cb)
|
|||
comments(first: 100) {
|
||||
nodes {
|
||||
id
|
||||
databaseId
|
||||
body
|
||||
author { login }
|
||||
authorAssociation
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ local extend = Snacks.picker.highlight.extend
|
|||
---@field item snacks.picker.gh.Item
|
||||
---@field opts snacks.gh.Config
|
||||
---@field comment_skip table<string, boolean>
|
||||
---@field is_review? boolean
|
||||
|
||||
---@param field string
|
||||
local function time_prop(field)
|
||||
|
|
@ -296,17 +297,24 @@ function M.render(buf, item, opts)
|
|||
if #threads > 0 then
|
||||
lines[#lines + 1] = { { "" } } -- empty line
|
||||
lines[#lines + 1] = { { "---", "@punctuation.special.markdown" } }
|
||||
lines[#lines + 1] = {} -- empty line
|
||||
|
||||
for _, thread in ipairs(threads) do
|
||||
lines[#lines + 1] = {} -- empty line
|
||||
local c = #lines
|
||||
|
||||
if thread.submitted then
|
||||
---@cast thread snacks.gh.Review
|
||||
ctx.is_review = true
|
||||
vim.list_extend(lines, M.review(thread, 1, ctx))
|
||||
else
|
||||
---@cast thread snacks.gh.Comment
|
||||
ctx.is_review = false
|
||||
vim.list_extend(lines, M.comment(thread, 1, ctx))
|
||||
end
|
||||
|
||||
if #lines > c then -- only add separator if there were comments added
|
||||
lines[#lines + 1] = {} -- empty line
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -316,7 +324,13 @@ function M.render(buf, item, opts)
|
|||
vim.api.nvim_buf_clear_namespace(buf, ns, 0, -1)
|
||||
|
||||
local changed = #lines ~= #buf_lines
|
||||
local comments = {} ---@type {line:number, id:number}[]
|
||||
for l, line in ipairs(lines) do
|
||||
for _, segment in ipairs(line) do
|
||||
if segment.meta and segment.meta.reply then
|
||||
comments[#comments + 1] = { line = l, id = segment.meta.reply }
|
||||
end
|
||||
end
|
||||
local line_text, extmarks = Snacks.picker.highlight.to_text(line)
|
||||
if line_text ~= buf_lines[l] then
|
||||
vim.api.nvim_buf_set_lines(buf, l - 1, l, false, { line_text })
|
||||
|
|
@ -339,6 +353,7 @@ function M.render(buf, item, opts)
|
|||
end
|
||||
end
|
||||
end
|
||||
vim.b[buf].snacks_gh_comments = comments
|
||||
if #lines < #buf_lines then
|
||||
vim.api.nvim_buf_set_lines(buf, #lines, -1, false, {})
|
||||
end
|
||||
|
|
@ -490,6 +505,14 @@ function M.comment(comment, level, ctx)
|
|||
vim.list_extend(ret, M.comment(reply, level, ctx))
|
||||
ctx.comment_skip[reply.id] = true
|
||||
end
|
||||
if ctx.is_review then
|
||||
for _, line in ipairs(ret) do
|
||||
local reply_id = comment.replyTo and comment.replyTo.databaseId or comment.databaseId
|
||||
if reply_id then
|
||||
line[#line + 1] = { "", meta = { reply = reply_id } }
|
||||
end
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
---@field params? table<string, string|number|boolean> typed fields (--field)
|
||||
---@field header? table<string, string|number|boolean>
|
||||
---@field jq? string
|
||||
---@field input? string
|
||||
---@field input? any
|
||||
---@field method? "GET" | "POST" | "PATCH" | "PUT" | "DELETE"
|
||||
---@field paginate? boolean
|
||||
---@field silent? boolean
|
||||
|
|
@ -138,6 +138,7 @@
|
|||
|
||||
---@class snacks.gh.Comment
|
||||
---@field id string
|
||||
---@field databaseId number
|
||||
---@field url string
|
||||
---@field author { login: string }
|
||||
---@field authorAssociation? string
|
||||
|
|
@ -149,7 +150,7 @@
|
|||
---@field createdAt string
|
||||
---@field reactionGroups? snacks.gh.Reaction[]
|
||||
---@field created? number
|
||||
---@field replyTo? {id: string}
|
||||
---@field replyTo? {id: string, databaseId: number}
|
||||
---@field path? string
|
||||
---@field diffHunk? string
|
||||
---@field line? number
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ local M = {}
|
|||
|
||||
---@alias snacks.picker.format.resolve fun(max_width:number):snacks.picker.Highlight[]
|
||||
---@alias snacks.picker.Extmark vim.api.keyset.set_extmark|{col:number, row?:number, field?:string}
|
||||
---@alias snacks.picker.Text {[1]:string, [2]:(string|string[])?, virtual?:boolean, field?:string, resolve?:snacks.picker.format.resolve}
|
||||
---@alias snacks.picker.Text {[1]:string, [2]:(string|string[])?, virtual?:boolean, field?:string, resolve?:snacks.picker.format.resolve, meta?:table<string, any>}
|
||||
---@alias snacks.picker.Highlight snacks.picker.Text|snacks.picker.Extmark
|
||||
---@alias snacks.picker.format fun(item:snacks.picker.Item, picker:snacks.Picker):snacks.picker.Highlight[]
|
||||
---@alias snacks.picker.preview fun(ctx: snacks.picker.preview.ctx):boolean?
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue