git_adr/cli/
show.rs

1//! Show an ADR.
2
3use anyhow::Result;
4use clap::Args as ClapArgs;
5use colored::Colorize;
6
7use crate::core::{ConfigManager, Git, NotesManager};
8
9/// Arguments for the show command.
10#[derive(ClapArgs, Debug)]
11pub struct Args {
12    /// ADR ID to show.
13    pub adr_id: String,
14
15    /// Output format (markdown, yaml, json).
16    #[arg(long, short, default_value = "markdown")]
17    pub format: String,
18
19    /// Show only metadata.
20    #[arg(long)]
21    pub metadata_only: bool,
22}
23
24/// Run the show command.
25///
26/// # Errors
27///
28/// Returns an error if the ADR cannot be shown.
29pub fn run(args: Args) -> Result<()> {
30    let git = Git::new();
31    git.check_repository()?;
32
33    let config = ConfigManager::new(git.clone()).load()?;
34    let notes = NotesManager::new(git, config);
35
36    // Try to find ADR by ID (exact match or partial)
37    let adrs = notes.list()?;
38    let adr = adrs
39        .into_iter()
40        .find(|a| a.id == args.adr_id || a.id.contains(&args.adr_id))
41        .ok_or_else(|| anyhow::anyhow!("ADR not found: {}", args.adr_id))?;
42
43    match args.format.as_str() {
44        "json" => {
45            let output = if args.metadata_only {
46                serde_json::json!({
47                    "id": adr.id,
48                    "title": adr.frontmatter.title,
49                    "status": adr.frontmatter.status.to_string(),
50                    "date": adr.frontmatter.date.as_ref().map(|d| d.datetime().to_rfc3339()),
51                    "tags": adr.frontmatter.tags,
52                    "authors": adr.frontmatter.authors,
53                    "deciders": adr.frontmatter.deciders,
54                    "commit": adr.commit,
55                })
56            } else {
57                serde_json::json!({
58                    "id": adr.id,
59                    "title": adr.frontmatter.title,
60                    "status": adr.frontmatter.status.to_string(),
61                    "date": adr.frontmatter.date.as_ref().map(|d| d.datetime().to_rfc3339()),
62                    "tags": adr.frontmatter.tags,
63                    "authors": adr.frontmatter.authors,
64                    "deciders": adr.frontmatter.deciders,
65                    "commit": adr.commit,
66                    "body": adr.body,
67                })
68            };
69            println!("{}", serde_json::to_string_pretty(&output)?);
70        },
71        "yaml" => {
72            if args.metadata_only {
73                println!("{}", serde_yaml::to_string(&adr.frontmatter)?);
74            } else {
75                println!("{}", adr.to_markdown()?);
76            }
77        },
78        _ => {
79            if args.metadata_only {
80                println!("{} {}", "ID:".bold(), adr.id.cyan());
81                println!("{} {}", "Title:".bold(), adr.frontmatter.title);
82                println!("{} {}", "Status:".bold(), adr.frontmatter.status);
83                if let Some(date) = &adr.frontmatter.date {
84                    println!("{} {}", "Date:".bold(), date.datetime().format("%Y-%m-%d"));
85                }
86                if !adr.frontmatter.tags.is_empty() {
87                    println!("{} {}", "Tags:".bold(), adr.frontmatter.tags.join(", "));
88                }
89                println!("{} {}", "Commit:".bold(), &adr.commit[..8]);
90            } else {
91                println!("{}", adr.to_markdown()?);
92            }
93        },
94    }
95
96    Ok(())
97}