update.rs

 1use anyhow::Result;
 2use std::path::Path;
 3
 4use crate::db;
 5
 6pub struct Opts<'a> {
 7    pub status: Option<&'a str>,
 8    pub priority: Option<i32>,
 9    pub title: Option<&'a str>,
10    pub desc: Option<&'a str>,
11    pub json: bool,
12}
13
14pub fn run(root: &Path, id: &str, opts: Opts) -> Result<()> {
15    let conn = db::open(root)?;
16    let ts = db::now_utc();
17
18    let mut sets = vec![format!("updated = '{ts}'")];
19    let mut params: Vec<Box<dyn rusqlite::types::ToSql>> = Vec::new();
20    let mut idx = 1;
21
22    if let Some(s) = opts.status {
23        sets.push(format!("status = ?{idx}"));
24        params.push(Box::new(s.to_string()));
25        idx += 1;
26    }
27    if let Some(p) = opts.priority {
28        sets.push(format!("priority = ?{idx}"));
29        params.push(Box::new(p));
30        idx += 1;
31    }
32    if let Some(t) = opts.title {
33        sets.push(format!("title = ?{idx}"));
34        params.push(Box::new(t.to_string()));
35        idx += 1;
36    }
37    if let Some(d) = opts.desc {
38        sets.push(format!("description = ?{idx}"));
39        params.push(Box::new(d.to_string()));
40        idx += 1;
41    }
42
43    let sql = format!("UPDATE tasks SET {} WHERE id = ?{idx}", sets.join(", "));
44    params.push(Box::new(id.to_string()));
45
46    let param_refs: Vec<&dyn rusqlite::types::ToSql> = params.iter().map(|p| p.as_ref()).collect();
47    conn.execute(&sql, param_refs.as_slice())?;
48
49    if opts.json {
50        let detail = db::load_task_detail(&conn, id)?;
51        println!("{}", serde_json::to_string(&detail)?);
52    } else {
53        let c = crate::color::stdout_theme();
54        println!("{}updated{} {id}", c.green, c.reset);
55    }
56
57    Ok(())
58}