//! `repo-labels [pattern]` — list the active repo's full label set //! (project-wide), not the labels on one issue/PR (that's `labels //! `). Useful for triage / labelling to discover the valid label //! names + what each means before applying them. 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 { /// Substring pattern to filter label names (case-sensitive). pattern: Option, } pub fn run(client: &Client, args: Args) -> Result<()> { let repo = client.repo(); // Repos can carry more than one page of labels; paginate so the list // is complete rather than capped at the first page. let labels = client.get_json_all(&format!("/repos/{repo}/labels"), 10)?; let filtered: Vec<&Value> = labels .iter() .filter(|l| { let name = l.get("name").and_then(Value::as_str).unwrap_or_default(); args.pattern.as_deref().is_none_or(|p| name.contains(p)) }) .collect(); if client.json_mode() { // Full label objects (id, name, color, description) as a JSON array. print_json(&json!(filtered))?; } else { // One label per line: `name`, plus its description (tab-separated) // when set, so triage can see what each label means at a glance. for l in filtered { let name = l.get("name").and_then(Value::as_str).unwrap_or_default(); let desc = l .get("description") .and_then(Value::as_str) .unwrap_or_default(); if desc.is_empty() { println!("{name}"); } else { println!("{name}\t{desc}"); } } } Ok(()) }