skipped 6 lines 7 7 #[derive(Parser, Debug)] 8 8 #[command(author, version, about, long_about = None)] 9 9 pub struct Params { 10 - /// Filetypes to deduplicate ( default = all) 10 + /// Filetypes to deduplicate [ default = all] 11 11 #[arg(short, long)] 12 12 pub types: Option<String>, 13 - /// Run Deduplicator on dir different from pwd 14 - #[arg(long , value_hint = ValueHint::DirPath)] 13 + /// Run Deduplicator on dir different from pwd ( e . g . , ~ / Pictures ) 14 + #[arg(value_hint = ValueHint::DirPath, value_name = " scan_dir_path " )] 15 15 pub dir: Option<PathBuf>, 16 16 /// Delete files interactively 17 17 #[arg(long, short)] 18 18 pub interactive: bool, 19 - /// Minimum filesize of duplicates to scan (e.g., 100B/1K/2M/3G/4T). [ default = 0 ] 19 + /// Minimum filesize of duplicates to scan (e.g., 100B/1K/2M/3G/4T). 20 + #[arg(long, short = 's', default_value = "1b")] 21 + pub min_size: Option<String>, 22 + /// Max Depth to scan while looking for duplicates 23 + #[arg(long, short = 'd')] 24 + pub max_depth: Option<usize>, 25 + /// Min Depth to scan while looking for duplicates 26 + #[arg(long)] 27 + pub min_depth: Option<usize>, 28 + /// Follow links while scanning directories 20 29 #[arg(long, short)] 21 - pub minsize: Option<String>, 30 + pub follow_links: bool, 22 31 } 23 32 24 33 impl Params { 25 - pub fn get_minsize (&self) -> Option<u64> { 26 - match &self.minsize { 34 + pub fn get_min_size (&self) -> Option<u64> { 35 + match &self.min_size { 27 36 Some(msize) => match msize.parse::<bytesize::ByteSize>() { 28 37 Ok(units) => Some(units.0), 29 38 Err(_) => None, skipped 9 lines 39 48 Ok(dir) 40 49 } 41 50 51 + fn add_glob_min_depth(&self, builder: GlobWalkerBuilder) -> Result<GlobWalkerBuilder> { 52 + match self.min_depth { 53 + Some(mindepth) => Ok(builder.min_depth(mindepth)), 54 + None => Ok(builder), 55 + } 56 + } 57 + 58 + fn add_glob_max_depth(&self, builder: GlobWalkerBuilder) -> Result<GlobWalkerBuilder> { 59 + match self.max_depth { 60 + Some(maxdepth) => Ok(builder.max_depth(maxdepth)), 61 + None => Ok(builder), 62 + } 63 + } 64 + 65 + fn add_glob_follow_links(&self, builder: GlobWalkerBuilder) -> Result<GlobWalkerBuilder> { 66 + match self.follow_links { 67 + true => Ok(builder.follow_links(true)), 68 + false => Ok(builder.follow_links(false)), 69 + } 70 + } 71 + 42 72 pub fn get_glob_walker(&self) -> Result<GlobWalker> { 43 73 let pattern: String = match self.types.as_ref() { 44 74 Some(filetypes) => format!("**/*{{{filetypes}}}"), 45 75 None => "**/*".to_string(), 46 76 }; 47 - // TODO: add params for maximum depth and following symlinks, then pass them to this builder 48 - GlobWalkerBuilder::from_patterns(self.get_directory()?, &[pattern]) 49 - .build() 50 - .map_err(|e| anyhow!(e)) 77 + 78 + let glob_walker_builder = self 79 + .add_glob_min_depth(GlobWalkerBuilder::from_patterns( 80 + self.get_directory()?, 81 + &[pattern], 82 + )) 83 + .and_then(|builder| self.add_glob_max_depth(builder)) 84 + .and_then(|builder| self.add_glob_follow_links(builder))?; 85 + 86 + glob_walker_builder.build().map_err(|e| anyhow!(e)) 51 87 } 52 88 } 53 89