list.rs

 1use anyhow::Result;
 2use std::path::Path;
 3
 4use crate::db;
 5
 6pub fn run(
 7    root: &Path,
 8    status: Option<&str>,
 9    priority: Option<i32>,
10    effort: Option<i32>,
11    label: Option<&str>,
12    json: bool,
13) -> Result<()> {
14    let conn = db::open(root)?;
15
16    let mut sql = String::from(
17        "SELECT id, title, description, type, priority, status, effort, parent, created, updated
18         FROM tasks WHERE 1=1",
19    );
20    let mut params: Vec<Box<dyn rusqlite::types::ToSql>> = Vec::new();
21    let mut idx = 1;
22
23    if let Some(s) = status {
24        sql.push_str(&format!(" AND status = ?{idx}"));
25        params.push(Box::new(s.to_string()));
26        idx += 1;
27    }
28    if let Some(p) = priority {
29        sql.push_str(&format!(" AND priority = ?{idx}"));
30        params.push(Box::new(p));
31        idx += 1;
32    }
33    if let Some(e) = effort {
34        sql.push_str(&format!(" AND effort = ?{idx}"));
35        params.push(Box::new(e));
36        idx += 1;
37    }
38    if let Some(l) = label {
39        sql.push_str(&format!(
40            " AND id IN (SELECT task_id FROM labels WHERE label = ?{idx})"
41        ));
42        params.push(Box::new(l.to_string()));
43    }
44
45    sql.push_str(" ORDER BY priority, created");
46
47    let param_refs: Vec<&dyn rusqlite::types::ToSql> = params.iter().map(|p| p.as_ref()).collect();
48    let mut stmt = conn.prepare(&sql)?;
49    let tasks: Vec<db::Task> = stmt
50        .query_map(param_refs.as_slice(), db::row_to_task)?
51        .collect::<rusqlite::Result<_>>()?;
52
53    if json {
54        let details: Vec<db::TaskDetail> = tasks
55            .into_iter()
56            .map(|t| {
57                let labels = db::load_labels(&conn, &t.id)?;
58                let blockers = db::load_blockers(&conn, &t.id)?;
59                Ok(db::TaskDetail {
60                    task: t,
61                    labels,
62                    blockers,
63                })
64            })
65            .collect::<Result<_>>()?;
66        println!("{}", serde_json::to_string(&details)?);
67    } else {
68        let c = crate::color::stdout_theme();
69        for t in &tasks {
70            println!(
71                "{}{:<12}{} {}{:<12}{} {}{:<4}{} {}",
72                c.bold,
73                t.id,
74                c.reset,
75                c.yellow,
76                format!("[{}]", t.status),
77                c.reset,
78                c.red,
79                db::priority_label(t.priority),
80                c.reset,
81                t.title,
82            );
83        }
84    }
85
86    Ok(())
87}