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!("{}", serde_json::json!({"id": task_id, "label": label}));
27            } else {
28                let c = crate::color::stdout_theme();
29                println!("{}added{} label {label}", c.green, c.reset);
30            }
31        }
32        LabelAction::Rm { id, label } => {
33            let task_id = db::resolve_task_id(&store, id, false)?;
34            let ts = db::now_utc();
35            store.apply_and_persist(|doc| {
36                let tasks = doc.get_map("tasks");
37                let task =
38                    db::get_task_map(&tasks, &task_id)?.ok_or_else(|| anyhow!("task not found"))?;
39                let labels = db::get_or_create_child_map(&task, "labels")?;
40                labels.delete(label)?;
41                task.insert("updated_at", ts.clone())?;
42                Ok(())
43            })?;
44
45            if !json {
46                let c = crate::color::stdout_theme();
47                println!("{}removed{} label {label}", c.green, c.reset);
48            }
49        }
50        LabelAction::List { id } => {
51            let task_id = db::resolve_task_id(&store, id, false)?;
52            let task = store
53                .get_task(&task_id, false)?
54                .ok_or_else(|| anyhow!("task not found"))?;
55            if json {
56                println!("{}", serde_json::to_string(&task.labels)?);
57            } else {
58                for l in &task.labels {
59                    println!("{l}");
60                }
61            }
62        }
63        LabelAction::ListAll => {
64            let mut set = BTreeSet::new();
65            for task in store.list_tasks()? {
66                for label in task.labels {
67                    set.insert(label);
68                }
69            }
70            let labels: Vec<_> = set.into_iter().collect();
71            if json {
72                println!("{}", serde_json::to_string(&labels)?);
73            } else {
74                for l in &labels {
75                    println!("{l}");
76                }
77            }
78        }
79    }
80
81    Ok(())
82}