diff --git a/pttodoest/src/flags.rs b/pttodoest/src/flags.rs new file mode 100644 index 0000000..d426edc --- /dev/null +++ b/pttodoest/src/flags.rs @@ -0,0 +1,96 @@ +use clap::Parser; +use serde::{Deserialize, Serialize}; +use serde_yaml; +use std::io::{BufRead, Read, Write}; + +#[derive(Debug, Parser)] +pub struct Flags { + #[arg(short = 'f', long = "path", default_value = "$PTTODO_FILE")] + pub path: String, + + #[arg(short = 'a', long = "add")] + pub add: Option, + + #[arg(short = 'e', long = "edit", default_value = "false")] + pub edit: bool, + + #[arg(short = 'd', long = "dry-run", default_value = "false")] + pub dry_run: bool, + + #[arg(short = 's', long = "add-schedule")] + pub 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) + } + + pub 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()); + } +} diff --git a/pttodoest/src/main.rs b/pttodoest/src/main.rs index 42896ea..92fb45f 100755 --- a/pttodoest/src/main.rs +++ b/pttodoest/src/main.rs @@ -1,7 +1,5 @@ -use clap::Parser; -use serde::{Deserialize, Serialize}; -use serde_yaml; -use std::io::{BufRead, Read, Write}; +use crate::flags::*; +mod flags; pub fn main() { let flags = Flags::new().expect("failed to flags"); @@ -27,90 +25,6 @@ pub fn main() { dump(flags.files().expect("couldnt find files from flags")).expect("failed to dump"); } -#[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()); - }); - } -} - fn add(files: Vec, added: String, add_schedule: Option) -> Result<(), String> { let task = Delta::new(added, add_schedule); @@ -149,14 +63,6 @@ mod Delta { } } -mod tests { - use super::*; - - pub fn with_dir(mut foo: impl FnMut(tempdir::TempDir)) { - foo(tempdir::TempDir::new("").unwrap()); - } -} - /* mod v1 { use clap::Parser;