diff --git a/Cargo.lock b/Cargo.lock index bca000e..a4a1536 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,7 +173,7 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "day-reporter" -version = "0.2.0" +version = "1.0.0" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index bfd4001..4eb7199 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "day-reporter" -version = "0.2.0" +version = "1.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/main.rs b/src/main.rs index b72c3f5..0523aef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,14 @@ mod things; mod reporter; mod emoji; +mod names; use reporter::{MarkdownReporter, Reporter, Resolution, ReportOptions}; use things::task::{Task, Status}; use anyhow::Result; use clap::{Parser, ValueEnum}; +use names::sanitize_names; #[derive(ValueEnum, Copy, Clone, Eq, PartialEq)] enum Modes { @@ -20,19 +22,19 @@ enum Modes { } impl Modes { - fn format_tasks(&self, tasks: Vec, tags: Vec) -> String { + fn format_tasks(&self, tasks: Vec, tags: &Vec) -> String { match self { Modes::Morning => { let task_report = MarkdownReporter.report(tasks, &ReportOptions { resolution: Resolution::FullTask, - tags, + tags: tags.to_vec(), }); format!("{}\n\n{}", emoji::pick(3).join(" "), task_report) }, Modes::Signoff => { let task_report = MarkdownReporter.report(tasks, &ReportOptions { resolution: Resolution::FullTask, - tags, + tags: tags.to_vec(), }); format!("Stopping now\n\n{}", task_report) }, @@ -45,7 +47,7 @@ impl Modes { }).collect::>(); let task_report = MarkdownReporter.report(further_filtered, &ReportOptions { resolution: Resolution::Project, - tags, + tags: tags.to_vec(), }); format!("*Cycle Report*\n\n{}", task_report) }, @@ -82,8 +84,9 @@ 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(reported, args.tags); - println!("{report}"); + let report = args.mode.format_tasks(reported, &args.tags); + let sanitized = sanitize_names(&report, &args.tags); + println!("{sanitized}"); Ok(()) } diff --git a/src/names.rs b/src/names.rs new file mode 100644 index 0000000..9fab02d --- /dev/null +++ b/src/names.rs @@ -0,0 +1,39 @@ +fn sanitize(src: &str) -> String { + // NOTE: The values on the right are _NOT_ the characters they appear to be. + src.replace("a", "а") + .replace("e", "e") + .replace("i", "і") + .replace("o", "о") + .replace("u", "ս") +} + +/// Replace vowel characters with look alikes to avoid Slack mention logic +/// # Args +/// - `src`: The source text to modify +/// - `names`: The set of names to sanitize +fn sanitize_strings<'a>(src: &'a str, names: &Vec) -> String { + let sanitization_strings = names.iter() + .map(|name| (name, sanitize(name))) + .collect::>(); + let mut dest = src.to_string(); + for (name, replacement) in sanitization_strings { + dest = dest.replace(name, &replacement); + } + return dest; +} + +fn extract_names_from_tags(tags: &Vec) -> Vec { + tags + .iter() + .filter(|t| t.starts_with("@")) + .map(|t| { + let formatted_name = t.strip_prefix("@").expect(&format!("{t} should have started with @")); + String::from(formatted_name) + }) + .collect() +} + +pub fn sanitize_names(src: &str, tags: &Vec) -> String { + let name_tags = extract_names_from_tags(tags); + sanitize_strings(src, &name_tags) +}