label.rs

 1use anyhow::{anyhow, Result};
 2use std::collections::BTreeSet;
 3use std::path::Path;
 4
 5use crate::cli::LabelAction;
 6use crate::db;
 7
 8pub fn run(root: &Path, action: &LabelAction, json: bool) -> Result<()> {
 9    let store = db::open(root)?;
10
11    match action {
12        LabelAction::Add { id, label } => {
13            let task_id = db::resolve_task_id(&store, id, false)?;
14            let ts = db::now_utc();
15            store.apply_and_persist(|doc| {
16                let tasks = doc.get_map("tasks");
17                let task =
18                    db::get_task_map(&tasks, &task_id)?.ok_or_else(|| anyhow!("task not found"))?;
19                let labels = db::get_or_create_child_map(&task, "labels")?;
20                labels.insert(label, true)?;
21                task.insert("updated_at", ts.clone())?;
22                Ok(())
23            })?;
24
25            if json {
26                println!(
27                    "{}",
28                    serde_json::json!({"id": task_id.as_str(), "label": label})
29                );
30            } else {
31                let c = crate::color::stdout_theme();
32                println!("{}added{} label {label}", c.green, c.reset);
33            }
34        }
35        LabelAction::Rm { id, label } => {
36            let task_id = db::resolve_task_id(&store, id, false)?;
37            let ts = db::now_utc();
38            store.apply_and_persist(|doc| {
39                let tasks = doc.get_map("tasks");
40                let task =
41                    db::get_task_map(&tasks, &task_id)?.ok_or_else(|| anyhow!("task not found"))?;
42                let labels = db::get_or_create_child_map(&task, "labels")?;
43                labels.delete(label)?;
44                task.insert("updated_at", ts.clone())?;
45                Ok(())
46            })?;
47
48            if !json {
49                let c = crate::color::stdout_theme();
50                println!("{}removed{} label {label}", c.green, c.reset);
51            }
52        }
53        LabelAction::List { id } => {
54            let task_id = db::resolve_task_id(&store, id, false)?;
55            let task = store
56                .get_task(&task_id, false)?
57                .ok_or_else(|| anyhow!("task not found"))?;
58            if json {
59                println!("{}", serde_json::to_string(&task.labels)?);
60            } else {
61                for l in &task.labels {
62                    println!("{l}");
63                }
64            }
65        }
66        LabelAction::ListAll => {
67            let mut set = BTreeSet::new();
68            for task in store.list_tasks()? {
69                for label in task.labels {
70                    set.insert(label);
71                }
72            }
73            let labels: Vec<_> = set.into_iter().collect();
74            if json {
75                println!("{}", serde_json::to_string(&labels)?);
76            } else {
77                for l in &labels {
78                    println!("{l}");
79                }
80            }
81        }
82    }
83
84    Ok(())
85}