diff --git a/Cargo.toml b/Cargo.toml index cd1b656..5255f6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,4 @@ edition = "2021" [dependencies] thiserror = "1.0" +clap = { version = "4.4", features = ["derive"] } diff --git a/src/main.rs b/src/main.rs index 2ee2541..a44e53c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,76 @@ mod tag_engine; -fn main() { - println!("Hello, world!"); +use std::collections::BTreeSet; +use std::error::Error; +use clap::Parser; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Cli { + /// Files to process + #[arg(required = true)] + files: Vec, +} + +fn list_tags(files: &[String]) -> Result, Box> { + let mut unique_tags = BTreeSet::new(); + + for file in files { + if let Ok((_, tags, _)) = tag_engine::parse_tags(file) { + unique_tags.extend(tags); + } + } + + Ok(unique_tags.into_iter().collect()) +} + +fn main() -> Result<(), Box> { + let cli = Cli::parse(); + + let tags = list_tags(&cli.files)?; + + for tag in tags { + println!("{}", tag); + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_list_tags_empty() { + let files = Vec::new(); + let tags = list_tags(&files).unwrap(); + assert!(tags.is_empty()); + } + + #[test] + fn test_list_tags_single_file() { + let files = vec!["document.txt -- tag1 tag2".to_string()]; + let tags = list_tags(&files).unwrap(); + assert_eq!(tags, vec!["tag1", "tag2"]); + } + + #[test] + fn test_list_tags_multiple_files() { + let files = vec![ + "doc1.txt -- tag1 tag2".to_string(), + "doc2.txt -- tag2 tag3".to_string(), + ]; + let tags = list_tags(&files).unwrap(); + assert_eq!(tags, vec!["tag1", "tag2", "tag3"]); + } + + #[test] + fn test_list_tags_with_invalid() { + let files = vec![ + "valid.txt -- good tag1".to_string(), + "invalid.txt -- bad:tag".to_string(), + ]; + let tags = list_tags(&files).unwrap(); + assert_eq!(tags, vec!["good", "tag1"]); + } }