things3_cloud/commands/
logbook.rs1use crate::app::Cli;
2use crate::commands::{Command, DetailedArgs};
3use crate::common::{
4 BOLD, DIM, GREEN, ICONS, colored, fmt_date_local, fmt_task_line, fmt_task_with_note, parse_day,
5};
6use anyhow::Result;
7use clap::Args;
8use std::io::Write;
9
10#[derive(Debug, Default, Args)]
11#[command(about = "Show the Logbook")]
12pub struct LogbookArgs {
13 #[command(flatten)]
14 pub detailed: DetailedArgs,
15 #[arg(long = "from", help = "Show items completed on/after this date (YYYY-MM-DD)")]
16 pub from_date: Option<String>,
17 #[arg(long = "to", help = "Show items completed on/before this date (YYYY-MM-DD)")]
18 pub to_date: Option<String>,
19}
20
21impl Command for LogbookArgs {
22 fn run_with_ctx(
23 &self,
24 cli: &Cli,
25 out: &mut dyn Write,
26 ctx: &mut dyn crate::cmd_ctx::CmdCtx,
27 ) -> Result<()> {
28 let store = cli.load_store()?;
29 let today = ctx.today();
30
31 let from_day =
32 parse_day(self.from_date.as_deref(), "--from").map_err(anyhow::Error::msg)?;
33 let to_day = parse_day(self.to_date.as_deref(), "--to").map_err(anyhow::Error::msg)?;
34
35 if let (Some(from), Some(to)) = (from_day, to_day)
36 && from > to
37 {
38 eprintln!("--from date must be before or equal to --to date");
39 return Ok(());
40 }
41
42 let tasks = store.logbook(from_day, to_day);
43 if tasks.is_empty() {
44 writeln!(
45 out,
46 "{}",
47 colored("Logbook is empty.", &[DIM], cli.no_color)
48 )?;
49 return Ok(());
50 }
51
52 let id_prefix_len =
53 store.unique_prefix_length(&tasks.iter().map(|t| t.uuid.clone()).collect::<Vec<_>>());
54
55 writeln!(
56 out,
57 "{}",
58 colored(
59 &format!("{} Logbook ({} tasks)", ICONS.done, tasks.len()),
60 &[BOLD, GREEN],
61 cli.no_color,
62 )
63 )?;
64
65 let mut current_day = String::new();
66 for task in tasks {
67 let day = fmt_date_local(task.stop_date);
68 if day != current_day {
69 writeln!(out)?;
70 writeln!(
71 out,
72 "{}",
73 colored(&format!(" {}", day), &[BOLD], cli.no_color)
74 )?;
75 current_day = day;
76 }
77 let line = fmt_task_line(
78 &task,
79 &store,
80 true,
81 false,
82 false,
83 Some(id_prefix_len),
84 &today,
85 cli.no_color,
86 );
87 writeln!(
88 out,
89 "{}",
90 fmt_task_with_note(
91 line,
92 &task,
93 " ",
94 Some(id_prefix_len),
95 self.detailed.detailed,
96 cli.no_color,
97 )
98 )?;
99 }
100
101 Ok(())
102 }
103}