diff --git a/src/main.rs b/src/main.rs index aa6c3a0..e5b2463 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,9 @@ mod things; mod reporter; mod emoji; -use reporter::{MarkdownReporter, Reporter}; +use reporter::{MarkdownReporter, Reporter, Resolution}; -use things::task::Task; +use things::task::{Task, Status}; use anyhow::Result; use clap::{Parser, ValueEnum}; @@ -20,11 +20,26 @@ enum Modes { } impl Modes { - fn format_tasks(&self, task_report: &str) -> String { + fn format_tasks(&self, tasks: Vec) -> String { match self { - Modes::Morning => format!("{}\n\n{}", emoji::pick(3).join(" "), task_report), - Modes::Signoff => format!("Stopping now\n\n{}", task_report), - Modes::Cycle => format!("*Cycle Report*\n\n{}", task_report), + Modes::Morning => { + let task_report = MarkdownReporter.report(tasks, &Resolution::FullTask); + format!("{}\n\n{}", emoji::pick(3).join(" "), task_report) + }, + Modes::Signoff => { + let task_report = MarkdownReporter.report(tasks, &Resolution::FullTask); + format!("Stopping now\n\n{}", task_report) + }, + Modes::Cycle => { + let further_filtered = tasks.into_iter().filter(|t| { + if let Some(p) = &t.project { + return p.status == Status::Completed; + } + return false; + }).collect::>(); + let task_report = MarkdownReporter.report(further_filtered, &Resolution::Project); + format!("*Cycle Report*\n\n{}", task_report) + }, } } } @@ -58,7 +73,7 @@ fn main() -> Result<()> { let reported: Vec = tasks.into_iter().filter(|task| { args.tags.iter().all(|tag| task.has_tag(tag)) }).collect(); - let report = args.mode.format_tasks(&MarkdownReporter.report(reported)); + let report = args.mode.format_tasks(reported); println!("{report}"); Ok(()) diff --git a/src/reporter.rs b/src/reporter.rs index 160171c..258cdb2 100644 --- a/src/reporter.rs +++ b/src/reporter.rs @@ -88,12 +88,17 @@ impl ThingsTree { } } +pub enum Resolution { + FullTask, + Project, +} + pub trait Reporter { fn report_task(&mut self, task: &Task, depth: usize) -> String; - fn report_project(&mut self, project: &ProjectTree, depth: usize) -> String; - fn report_single_area(&mut self, area: &AreaTree) -> String; - fn report_multiple_areas(&mut self, areas: &Vec) -> String; - fn report(&mut self, tasks: Vec) -> String { + fn report_project(&mut self, project: &ProjectTree, depth: usize, resolution: &Resolution) -> String; + fn report_single_area(&mut self, area: &AreaTree, resolution: &Resolution) -> String; + fn report_multiple_areas(&mut self, areas: &Vec, resolution: &Resolution) -> String; + fn report(&mut self, tasks: Vec, resolution: &Resolution) -> String { let tree = ThingsTree::from_tasks(tasks); let untracked_tasks = tree.hanging_tasks .iter() @@ -102,8 +107,8 @@ pub trait Reporter { .join("\n"); let area_tasks: String = match tree.areas.len() { 0 => "".to_string(), - 1 => self.report_single_area(&tree.areas[0]), - _ => self.report_multiple_areas(&tree.areas), + 1 => self.report_single_area(&tree.areas[0], resolution), + _ => self.report_multiple_areas(&tree.areas, resolution), }; let separator = if area_tasks == "" || untracked_tasks == "" { @@ -122,27 +127,41 @@ impl Reporter for MarkdownReporter { fn report_task(&mut self, task: &Task, depth: usize) -> String { format!("{}- {}", String::from(" ").repeat(depth), task.title) } - fn report_project(&mut self, project: &ProjectTree, depth: usize) -> String { - let tasks = project.tasks.iter().map(|t| self.report_task(t, depth + 4)).collect::>().join("\n"); - format!("{}{}\n{}", String::from(" ").repeat(depth), project.title, tasks) + fn report_project(&mut self, project: &ProjectTree, depth: usize, resolution: &Resolution) -> String { + match resolution { + Resolution::FullTask => { + let tasks = project.tasks.iter().map(|t| self.report_task(t, depth + 4)).collect::>().join("\n"); + format!("{}{}\n{}", String::from(" ").repeat(depth), project.title, tasks) + }, + Resolution::Project => { + format!("{}- {}", String::from(" ").repeat(depth), project.title) + } + } } - fn report_single_area(&mut self, area: &AreaTree) -> String { - let project_tasks = area.projects.iter().map(|p| self.report_project(p, 0)).collect::>().join("\n"); + fn report_single_area(&mut self, area: &AreaTree, resolution: &Resolution) -> String { + let project_reports = area.projects + .iter() + .map(|p| self.report_project(p, 0, resolution)) + .collect::>() + .join("\n"); let untracked_tasks = area.hanging_tasks.iter().map(|t| self.report_task(t, 0)).collect::>().join("\n"); - let separator = if project_tasks == "" || untracked_tasks == "" { + let separator = if project_reports == "" || untracked_tasks == "" { "" } else { "\n\n" }; - format!("{}{}{}", project_tasks, separator, untracked_tasks) + match resolution { + Resolution::FullTask => format!("{}{}{}", project_reports, separator, untracked_tasks), + Resolution::Project => format!("{}", project_reports) + } } - fn report_multiple_areas(&mut self, areas: &Vec) -> String { + fn report_multiple_areas(&mut self, areas: &Vec, resolution: &Resolution) -> String { match areas.len() { 0 => "".to_string(), - 1 => self.report_single_area(&areas[0]), + 1 => self.report_single_area(&areas[0], resolution), _ => { areas.iter().map(|area| { - let single = self.report_single_area(area); + let single = self.report_single_area(area, resolution); format!("*{}*\n{}", area.title, single) }) .collect::>() diff --git a/src/things/task.rs b/src/things/task.rs index 90e031f..c929adc 100644 --- a/src/things/task.rs +++ b/src/things/task.rs @@ -5,7 +5,7 @@ use osascript; use serde_json; use chrono::{DateTime, Utc}; -#[derive(Deserialize, Debug)] +#[derive(Deserialize, Debug, Eq, PartialEq)] pub enum Status { #[serde(rename = "completed")] Completed,