Skip to main content

things3_cloud/commands/
upcoming.rs

1use crate::app::Cli;
2use crate::commands::{Command, DetailedArgs};
3use crate::common::{colored, fmt_date, fmt_task_line, fmt_task_with_note, BOLD, CYAN, DIM, ICONS};
4use crate::wire::task::TaskStatus;
5use anyhow::Result;
6use clap::Args;
7use std::io::Write;
8
9#[derive(Debug, Default, Args)]
10pub struct UpcomingArgs {
11    #[command(flatten)]
12    pub detailed: DetailedArgs,
13}
14
15impl Command for UpcomingArgs {
16    fn run_with_ctx(
17        &self,
18        cli: &Cli,
19        out: &mut dyn Write,
20        ctx: &mut dyn crate::cmd_ctx::CmdCtx,
21    ) -> Result<()> {
22        let store = cli.load_store()?;
23        let today = ctx.today();
24        let now_ts = today.timestamp();
25
26        let mut tasks = Vec::new();
27        for t in store.tasks(Some(TaskStatus::Incomplete), Some(false), None) {
28            if t.in_someday() {
29                continue;
30            }
31            let Some(start_date) = t.start_date else {
32                continue;
33            };
34            if start_date.timestamp() > now_ts {
35                tasks.push(t);
36            }
37        }
38        tasks.sort_by_key(|t| t.start_date);
39
40        if tasks.is_empty() {
41            writeln!(
42                out,
43                "{}",
44                colored("No upcoming tasks.", &[DIM], cli.no_color)
45            )?;
46            return Ok(());
47        }
48
49        writeln!(
50            out,
51            "{}",
52            colored(
53                &format!("{} Upcoming  ({} tasks)", ICONS.upcoming, tasks.len()),
54                &[BOLD, CYAN],
55                cli.no_color,
56            )
57        )?;
58
59        let id_prefix_len =
60            store.unique_prefix_length(&tasks.iter().map(|t| t.uuid.clone()).collect::<Vec<_>>());
61
62        let mut current_date = String::new();
63        for task in tasks {
64            let day = fmt_date(task.start_date);
65            if day != current_date {
66                writeln!(out)?;
67                writeln!(
68                    out,
69                    "{}",
70                    colored(&format!("  {}", day), &[BOLD], cli.no_color)
71                )?;
72                current_date = day;
73            }
74            let line = fmt_task_line(
75                &task,
76                &store,
77                false,
78                true,
79                false,
80                Some(id_prefix_len),
81                &today,
82                cli.no_color,
83            );
84            writeln!(
85                out,
86                "{}",
87                fmt_task_with_note(
88                    line,
89                    &task,
90                    "    ",
91                    Some(id_prefix_len),
92                    self.detailed.detailed,
93                    cli.no_color,
94                )
95            )?;
96        }
97        Ok(())
98    }
99}