From d0a1ee037b606301d15c4eaa93831109f2b0eeb1 Mon Sep 17 00:00:00 2001 From: damocles Date: Tue, 26 May 2026 14:36:00 +0200 Subject: [PATCH] hive-forge: make --json a global flag (closes #421) --- docs/gotchas.md | 2 +- hive-forge/src/client.rs | 19 +++++++++++++++++-- hive-forge/src/main.rs | 9 ++++++++- hive-forge/src/verbs/comment_show.rs | 9 +++------ hive-forge/src/verbs/comments.rs | 10 ++++------ 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/docs/gotchas.md b/docs/gotchas.md index d380a6af..f41c9c90 100644 --- a/docs/gotchas.md +++ b/docs/gotchas.md @@ -124,7 +124,7 @@ since #280). Use it instead of ad-hoc curl pipelines: ```bash hive-forge view 42 # title + body + comments hive-forge comments 42 # list all comments (human-readable) -hive-forge comments 42 --json # list as JSON array +hive-forge --json comments 42 # same as above, JSON array (global flag, closes #421) hive-forge comment 42 --body "..." # post comment (inline body) hive-forge comment 42 --body-file - <) -> Result { + /// default. `json_mode` comes from the global `--json` flag — + /// per-verb output formatters key off it via `Client::json_mode`. + pub fn from_env(repo_override: Option, json_mode: bool) -> Result { let base = std::env::var("HIVE_FORGE_URL").unwrap_or_else(|_| DEFAULT_URL.to_owned()); let default_repo = repo_override .or_else(|| std::env::var("HIVE_FORGE_REPO").ok()) @@ -55,9 +60,19 @@ impl Client { http, base, default_repo, + json_mode, }) } + /// True when the operator passed the global `--json` flag. + /// Verbs that have a human-readable default branch on this to + /// emit JSON instead. Verbs whose only output format is JSON + /// (e.g. `issue`, `pr`) can ignore it. + #[must_use] + pub fn json_mode(&self) -> bool { + self.json_mode + } + /// Resolve the API base path (`/api/v1`). fn api(&self) -> String { format!("{}/api/v1", self.base) diff --git a/hive-forge/src/main.rs b/hive-forge/src/main.rs index ba3b74c8..ed5a9563 100644 --- a/hive-forge/src/main.rs +++ b/hive-forge/src/main.rs @@ -35,6 +35,12 @@ struct Cli { /// positional the bash helper used. #[arg(short = 'r', long, global = true)] repo: Option, + /// Emit JSON output instead of the verb's default human-readable + /// shape, for verbs that support both (closes #421). Verbs whose + /// only output is already JSON (`issue`, `pr`, etc.) ignore this + /// flag — they always print JSON regardless. + #[arg(long, global = true)] + json: bool, #[command(subcommand)] verb: Verb, } @@ -87,7 +93,8 @@ enum Verb { fn main() -> Result<()> { let cli = Cli::parse(); - let client = client::Client::from_env(cli.repo).context("initialize forge client")?; + let client = + client::Client::from_env(cli.repo, cli.json).context("initialize forge client")?; match cli.verb { Verb::View(a) => verbs::view::run(&client, a), Verb::Issue(a) => verbs::issue::run(&client, a), diff --git a/hive-forge/src/verbs/comment_show.rs b/hive-forge/src/verbs/comment_show.rs index 9a2e41d6..65e6e8bb 100644 --- a/hive-forge/src/verbs/comment_show.rs +++ b/hive-forge/src/verbs/comment_show.rs @@ -1,5 +1,5 @@ -//! `comment-show [--json] [repo]` — print the body (or full -//! JSON) of a single comment by id. +//! `comment-show ` — print the body (or full JSON envelope +//! when `--json` is set globally) of a single comment by id. use anyhow::Result; use clap::Args as ClapArgs; @@ -12,15 +12,12 @@ use crate::verbs::print_json; pub struct Args { /// Comment id. id: u64, - /// Print full JSON envelope instead of just the body text. - #[arg(long)] - json: bool, } pub fn run(client: &Client, args: Args) -> Result<()> { let repo = client.repo(); let v = client.get_json(&format!("/repos/{repo}/issues/comments/{}", args.id))?; - if args.json { + if client.json_mode() { let trimmed = json!({ "id": v.get("id"), "user": v.get("user").and_then(|u| u.get("login")), diff --git a/hive-forge/src/verbs/comments.rs b/hive-forge/src/verbs/comments.rs index 4f7dbb32..ad9aecb8 100644 --- a/hive-forge/src/verbs/comments.rs +++ b/hive-forge/src/verbs/comments.rs @@ -1,5 +1,6 @@ -//! `comments [--json] [--limit N]` — list all comments on -//! an issue or PR. Closes the curl-fallback gap (#418). +//! `comments [--limit N]` — list all comments on an issue +//! or PR. Closes the curl-fallback gap (#418). Use the global +//! `--json` flag for JSON output (#421). use anyhow::Result; use clap::Args as ClapArgs; @@ -12,9 +13,6 @@ use crate::verbs::print_json; 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, @@ -26,7 +24,7 @@ pub fn run(client: &Client, args: Args) -> Result<()> { "/repos/{repo}/issues/{}/comments?limit={}", args.number, args.limit ))?; - if args.json { + if client.json_mode() { let trimmed: Vec = v .as_array() .map(|a| {