show.rs

 1use anyhow::Result;
 2use std::path::Path;
 3
 4use crate::db;
 5
 6pub fn run(root: &Path, id: &str, json: bool) -> Result<()> {
 7    let store = db::open(root)?;
 8    let task_id = db::resolve_task_id(&store, id, true)?;
 9    let task = store
10        .get_task(&task_id, true)?
11        .ok_or_else(|| anyhow::anyhow!("task {id} not found"))?;
12
13    if json {
14        println!("{}", serde_json::to_string(&task)?);
15        return Ok(());
16    }
17
18    let c = crate::color::stdout_theme();
19
20    println!(
21        "{}# {}{} {}[{}]{}",
22        c.bold,
23        task.title,
24        c.reset,
25        c.yellow,
26        db::status_label(task.status),
27        c.reset
28    );
29
30    if !task.description.is_empty() {
31        println!();
32        println!("{}", task.description);
33    }
34
35    println!();
36    println!(
37        "{}{}{} · {} · {}{}{} priority · {}{}{} effort",
38        c.bold,
39        task.id,
40        c.reset,
41        task.task_type,
42        c.red,
43        db::priority_label(task.priority),
44        c.reset,
45        c.blue,
46        db::effort_label(task.effort),
47        c.reset,
48    );
49
50    if !task.labels.is_empty() {
51        println!("labels: {}", task.labels.join(", "));
52    }
53
54    let blockers = db::partition_blockers(&store, &task.blockers)?;
55    let total = blockers.open.len() + blockers.resolved.len();
56    if total > 0 {
57        let label = if total == 1 { "blocker" } else { "blockers" };
58        if blockers.open.is_empty() {
59            // All closed: prefix with [all closed], no individual markers.
60            let ids: Vec<String> = blockers.resolved.iter().map(ToString::to_string).collect();
61            println!("{label}: [all closed] {}", ids.join(", "));
62        } else {
63            // Mixed or all open: annotate only the closed ones.
64            let mut ids: Vec<String> = blockers.open.iter().map(ToString::to_string).collect();
65            ids.extend(blockers.resolved.iter().map(|id| format!("{id} [closed]")));
66            println!("{label}: {}", ids.join(", "));
67        }
68    }
69
70    println!("created {} · updated {}", task.created_at, task.updated_at);
71
72    if !task.logs.is_empty() {
73        println!();
74        println!("--- log ---");
75        for log in task.logs {
76            println!("[{}] {}", log.timestamp, log.message);
77        }
78    }
79
80    Ok(())
81}