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