From 9ab241dc24c32c68ee3a68a8361a5d7f6d5fbc9a Mon Sep 17 00:00:00 2001 From: damocles Date: Mon, 25 May 2026 21:09:35 +0200 Subject: [PATCH] hive-forge: add comments [--json] [--limit] verb (closes #418) --- hive-forge/src/main.rs | 3 ++ hive-forge/src/verbs/comments.rs | 62 ++++++++++++++++++++++++++++++++ hive-forge/src/verbs/mod.rs | 1 + 3 files changed, 66 insertions(+) create mode 100644 hive-forge/src/verbs/comments.rs diff --git a/hive-forge/src/main.rs b/hive-forge/src/main.rs index 62569b09..ba3b74c8 100644 --- a/hive-forge/src/main.rs +++ b/hive-forge/src/main.rs @@ -55,6 +55,8 @@ enum Verb { PrCreate(verbs::pr_create::Args), /// Post a comment on an issue or PR. Comment(verbs::comment::Args), + /// List all comments on an issue or PR. + Comments(verbs::comments::Args), /// Print the body (or full JSON) of a single comment by id. CommentShow(verbs::comment_show::Args), /// Edit an existing comment by id. @@ -94,6 +96,7 @@ fn main() -> Result<()> { Verb::Pr(a) => verbs::pr::run(&client, a), Verb::PrCreate(a) => verbs::pr_create::run(&client, a), Verb::Comment(a) => verbs::comment::run(&client, a), + Verb::Comments(a) => verbs::comments::run(&client, a), Verb::CommentShow(a) => verbs::comment_show::run(&client, a), Verb::CommentEdit(a) => verbs::comment_edit::run(&client, a), Verb::Assign(a) => verbs::assign::run(&client, a), diff --git a/hive-forge/src/verbs/comments.rs b/hive-forge/src/verbs/comments.rs new file mode 100644 index 00000000..4f7dbb32 --- /dev/null +++ b/hive-forge/src/verbs/comments.rs @@ -0,0 +1,62 @@ +//! `comments [--json] [--limit N]` — list all comments on +//! an issue or PR. Closes the curl-fallback gap (#418). + +use anyhow::Result; +use clap::Args as ClapArgs; +use serde_json::{Value, json}; + +use crate::client::Client; +use crate::verbs::print_json; + +#[derive(ClapArgs)] +pub struct Args { + /// Issue or PR number. + number: u64, + /// Print as JSON array instead of human-readable markdown. + #[arg(long)] + json: bool, + /// Page size (Forgejo caps at 50 by default). + #[arg(long, default_value_t = 50)] + limit: u64, +} + +pub fn run(client: &Client, args: Args) -> Result<()> { + let repo = client.repo(); + let v = client.get_json(&format!( + "/repos/{repo}/issues/{}/comments?limit={}", + args.number, args.limit + ))?; + if args.json { + let trimmed: Vec = v + .as_array() + .map(|a| { + a.iter() + .map(|c| { + json!({ + "id": c.get("id"), + "user": c.get("user").and_then(|u| u.get("login")), + "created_at": c.get("created_at"), + "updated_at": c.get("updated_at"), + "body": c.get("body"), + "url": c.get("html_url"), + }) + }) + .collect() + }) + .unwrap_or_default(); + print_json(&Value::Array(trimmed)) + } else { + for c in v.as_array().cloned().unwrap_or_default() { + let user = c + .get("user") + .and_then(|u| u.get("login")) + .and_then(Value::as_str) + .unwrap_or("?"); + let ts = c.get("created_at").and_then(Value::as_str).unwrap_or("?"); + let body = c.get("body").and_then(Value::as_str).unwrap_or(""); + println!("**{user} @ {ts}**: {body}"); + println!(); + } + Ok(()) + } +} diff --git a/hive-forge/src/verbs/mod.rs b/hive-forge/src/verbs/mod.rs index 2cea9d9d..a32ef2a8 100644 --- a/hive-forge/src/verbs/mod.rs +++ b/hive-forge/src/verbs/mod.rs @@ -10,6 +10,7 @@ pub mod close; pub mod comment; pub mod comment_edit; pub mod comment_show; +pub mod comments; pub mod diff; pub mod issue; pub mod issue_create;