diff --git a/pttodoest/src/main.rs b/pttodoest/src/main.rs index e8dd76b..fb4e516 100755 --- a/pttodoest/src/main.rs +++ b/pttodoest/src/main.rs @@ -1,3 +1,105 @@ +use clap::Parser; +use serde::{Deserialize, Serialize}; +use serde_yaml; +use std::io::{BufRead, Read, Write}; + +pub fn main() { + let _flags = Flags::new().expect("failed to flags"); +} + +#[derive(Debug, Parser)] +struct Flags { + #[arg(short = 'f', long = "path", default_value = "$PTTODO_FILE")] + path: String, + + #[arg(short = 'a', long = "add")] + add: Option, + + #[arg(short = 'e', long = "edit", default_value = "false")] + edit: bool, + + #[arg(short = 'd', long = "dry-run", default_value = "false")] + dry_run: bool, + + #[arg(short = 's', long = "add-schedule")] + add_schedule: Option, +} + +impl Flags { + pub fn new() -> Result { + let mut result = Flags::parse(); + + if result.path.get(..1) == Some("$") { + result.path = match std::env::var(result.path.get(1..).unwrap()) { + Ok(v) => Ok(v), + Err(msg) => Err(format!("'{}' unset: {}", result.path, msg)), + }?; + } + + let _ = result.files()?; + + Ok(result) + } + + fn files(&self) -> Result, String> { + Self::files_with(&self.path) + } + + fn files_with(p: &String) -> Result, String> { + let metadata = match std::fs::metadata(p.clone()) { + Ok(v) => Ok(v), + Err(msg) => Err(format!("failed to load {}: {}", p.clone(), msg)), + }?; + let files = match metadata.is_dir() { + false => Ok(vec![p.clone()]), + true => match std::fs::read_dir(p.clone()) { + Ok(paths) => Ok(paths + .filter(|x| x.is_ok()) + .map(|x| x.unwrap()) + .filter(|x| x.metadata().unwrap().is_file()) + .map(|x| x.path().display().to_string()) + .filter(|x| !x.contains("/.")) + .collect()), + Err(msg) => Err(format!("failed to read {}: {}", p.clone(), msg)), + }, + }?; + assert!(files.len() > 0, "no files"); + Ok(files) + } +} + +#[cfg(test)] +mod test_flags { + use super::*; + + #[test] + fn test_flags_files_unhidden_only() { + tests::with_dir(|d| { + std::fs::File::create(d.path().join("plain")).unwrap(); + std::fs::File::create(d.path().join(".hidden")).unwrap(); + + let flags = Flags { + path: d.path().to_str().unwrap().to_string(), + add: None, + edit: false, + dry_run: true, + add_schedule: None, + }; + let files = flags.files().expect("failed to files from dir"); + assert_eq!(1, files.len()); + }); + } +} + +mod tests { + use super::*; + + pub fn with_dir(mut foo: impl FnMut(tempdir::TempDir)) { + foo(tempdir::TempDir::new("").unwrap()); + } +} + +/* mod v1 { use clap::Parser; use serde::{Deserialize, Serialize}; @@ -1138,3 +1240,4 @@ mod v1 { } } } +*/