ready.rs

 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(root: &Path, json: bool) -> Result<()> {
10    let conn = db::open(root)?;
11
12    let mut stmt = conn.prepare(
13        "SELECT id, title, description, type, priority, status, effort, parent, created, updated
14         FROM tasks
15         WHERE status = 'open'
16           AND id NOT IN (
17               SELECT b.task_id FROM blockers b
18               JOIN tasks t ON b.blocker_id = t.id
19               WHERE t.status != 'closed'
20           )
21         ORDER BY priority, created",
22    )?;
23
24    let tasks: Vec<db::Task> = stmt
25        .query_map([], db::row_to_task)?
26        .collect::<rusqlite::Result<_>>()?;
27
28    if json {
29        let summary: Vec<serde_json::Value> = tasks
30            .iter()
31            .map(|t| {
32                serde_json::json!({
33                    "id": t.id,
34                    "title": t.title,
35                    "priority": db::priority_label(t.priority),
36                    "effort": db::effort_label(t.effort),
37                })
38            })
39            .collect();
40        println!("{}", serde_json::to_string(&summary)?);
41    } else {
42        let use_color = stdout_use_color();
43        let mut table = Table::new();
44        table.load_preset(NOTHING);
45        table.set_header(vec!["ID", "PRIORITY", "EFFORT", "TITLE"]);
46        for t in &tasks {
47            table.add_row(vec![
48                cell_bold(&t.id, use_color),
49                cell_fg(db::priority_label(t.priority), Color::Red, use_color),
50                cell_fg(db::effort_label(t.effort), Color::Blue, use_color),
51                Cell::new(&t.title),
52            ]);
53        }
54        if !tasks.is_empty() {
55            println!("{table}");
56        }
57    }
58
59    Ok(())
60}