Skip to content

Commit

Permalink
Changed to StructOpt for CLI argument parser. (#37)
Browse files Browse the repository at this point in the history
Changed to StructOpt for CLI argument parser.
  • Loading branch information
MeirKlemp authored Oct 4, 2020
1 parent e60c042 commit e4af905
Show file tree
Hide file tree
Showing 5 changed files with 400 additions and 365 deletions.
87 changes: 87 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion czkawka_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ homepage = "https://github.com/qarmin/czkawka"
repository = "https://github.com/qarmin/czkawka"

[dependencies]
czkawka_core = { path = "../czkawka_core" }
czkawka_core = { path = "../czkawka_core" }
structopt = "0.3.18"
32 changes: 0 additions & 32 deletions czkawka_cli/src/arguments_pair.rs

This file was deleted.

192 changes: 192 additions & 0 deletions czkawka_cli/src/commands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
use czkawka_core::duplicate::{CheckingMethod, DeleteMethod};
use std::path::PathBuf;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
#[structopt(name = "czkawka", help_message = HELP_MESSAGE, template = HELP_TEMPLATE)]
pub enum Commands {
#[structopt(name = "dup", about = "Finds duplicate files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka dup -d /home/rafal -e /home/rafal/Obrazy -m 25 -x 7z rar IMAGE -s hashmb -f results.txt -D aeo")]
Duplicates {
#[structopt(flatten)]
directories: Directories,
#[structopt(flatten)]
excluded_directories: ExludedDirectories,
#[structopt(flatten)]
excluded_items: ExludedItems,
#[structopt(short, long, parse(try_from_str = parse_min_size), default_value = "1024", help = "Minimum size in bytes", long_help = "Minimum size of checked files in bytes, assigning bigger value may speed up searching")]
min_size: u64,
#[structopt(flatten)]
allowed_extensions: AllowedExtensions,
#[structopt(short, long, default_value = "HASH", parse(try_from_str = parse_checking_method), help = "Search method (SIZE, HASH, HASHMB)", long_help = "Methods to search files.\nSIZE - The fastest method, checking by the file's size,\nHASHMB - More accurate but slower, checking by the hash of the file's first mibibyte or\nHASH - The slowest method, checking by the hash of the entire file")]
search_method: CheckingMethod,
#[structopt(short = "D", long, default_value = "AEO", parse(try_from_str = parse_delete_method), help = "Delete method (AEN, AEO, ON, OO)", long_help = "Methods to delete the files.\nAEN - All files except the newest,\nAEO - All files except the oldest,\nON - Only 1 file, the newest,\nOO - Only 1 file, the oldest")]
delete_method: DeleteMethod,
#[structopt(flatten)]
file_to_save: FileToSave,
#[structopt(flatten)]
not_recursive: NotRecursive,
},
#[structopt(name = "empty-folders", about = "Finds emtpty folders", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka empty-folders -d /home/rafal/rr /home/gateway -f results.txt")]
EmptyFolders {
#[structopt(flatten)]
directories: Directories,
#[structopt(short = "D", long, help = "Delete found folders")]
delete_folders: bool,
#[structopt(flatten)]
file_to_save: FileToSave,
},
#[structopt(name = "big", about = "Finds big files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka big -d /home/rafal/ /home/piszczal -e /home/rafal/Roman -n 25 -x VIDEO -f results.txt")]
BiggestFiles {
#[structopt(flatten)]
directories: Directories,
#[structopt(flatten)]
excluded_directories: ExludedDirectories,
#[structopt(flatten)]
excluded_items: ExludedItems,
#[structopt(flatten)]
allowed_extensions: AllowedExtensions,
#[structopt(short, long, default_value = "50", help = "Number of files to be shown")]
number_of_files: usize,
#[structopt(flatten)]
file_to_save: FileToSave,
#[structopt(flatten)]
not_recursive: NotRecursive,
},
#[structopt(name = "empty-files", about = "Finds emtpy files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka empty-files -d /home/rafal /home/szczekacz -e /home/rafal/Pulpit -R -f results.txt")]
EmptyFiles {
#[structopt(flatten)]
directories: Directories,
#[structopt(flatten)]
excluded_directories: ExludedDirectories,
#[structopt(flatten)]
excluded_items: ExludedItems,
#[structopt(flatten)]
allowed_extensions: AllowedExtensions,
#[structopt(short = "D", long, help = "Delete found files")]
delete_files: bool,
#[structopt(flatten)]
file_to_save: FileToSave,
#[structopt(flatten)]
not_recursive: NotRecursive,
},
#[structopt(name = "temp", about = "Finds temporary files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka temp -d /home/rafal/ -E */.git */tmp* *Pulpit -f results.txt -D")]
Temporary {
#[structopt(flatten)]
directories: Directories,
#[structopt(flatten)]
excluded_directories: ExludedDirectories,
#[structopt(flatten)]
excluded_items: ExludedItems,
#[structopt(short = "D", long, help = "Delete found files")]
delete_files: bool,
#[structopt(flatten)]
file_to_save: FileToSave,
#[structopt(flatten)]
not_recursive: NotRecursive,
},
}

#[derive(Debug, StructOpt)]
pub struct Directories {
#[structopt(short, long, parse(from_os_str), required = true, help = "Directorie(s) to search", long_help = "List of directorie(s) which will be searched(absolute path)")]
pub directories: Vec<PathBuf>,
}

#[derive(Debug, StructOpt)]
pub struct ExludedDirectories {
#[structopt(short, long, parse(from_os_str), help = "Exluded directorie(s)", long_help = "List of directorie(s) which will be excluded from search(absolute path)")]
pub excluded_directories: Vec<PathBuf>,
}

#[derive(Debug, StructOpt)]
pub struct ExludedItems {
#[structopt(short = "E", long, parse(from_os_str), help = "Exluded item(s)", long_help = "List of excluded item(s) which contains * wildcard(may be slow, so use -e where possible)")]
pub excluded_items: Vec<PathBuf>,
}

#[derive(Debug, StructOpt)]
pub struct AllowedExtensions {
#[structopt(
short = "x",
long,
help = "Allowed file extension(s)",
long_help = "List of checked files with provided extension(s). There are also helpful macros which allow to easy use a typcal extensions like:\nIMAGE(\"jpg,kra,gif,png,bmp,tiff,webp,hdr,svg\"),\nTEXT(\"txt,doc,docx,odt,rtf\"),\nVIDEO(\"mp4,flv,mkv,webm,vob,ogv,gifv,avi,mov,wmv,mpg,m4v,m4p,mpeg,3gp\") or\nMUSIC(\"mp3,flac,ogg,tta,wma,webm\")\n "
)]
pub allowed_extensions: Vec<String>,
}

#[derive(Debug, StructOpt)]
pub struct NotRecursive {
#[structopt(short = "R", long, help = "Prevents from recursive check of folders")]
pub not_recursive: bool,
}

#[derive(Debug, StructOpt)]
pub struct FileToSave {
#[structopt(short, long, value_name = "file-name", help = "Saves the results into the file")]
pub file_to_save: Option<PathBuf>,
}

impl FileToSave {
pub fn file_name(&self) -> Option<&str> {
if let Some(file_name) = &self.file_to_save {
return file_name.to_str();
}

None
}
}

fn parse_checking_method(src: &str) -> Result<CheckingMethod, &'static str> {
match src.to_ascii_lowercase().as_str() {
"size" => Ok(CheckingMethod::Size),
"hash" => Ok(CheckingMethod::Hash),
"hashmb" => Ok(CheckingMethod::HashMB),
_ => Err("Couldn't parse the search method (allowed: SIZE, HASH, HASHMB)"),
}
}

fn parse_delete_method(src: &str) -> Result<DeleteMethod, &'static str> {
match src.to_ascii_lowercase().as_str() {
"aen" => Ok(DeleteMethod::AllExceptNewest),
"aeo" => Ok(DeleteMethod::AllExceptOldest),
"on" => Ok(DeleteMethod::OneNewest),
"oo" => Ok(DeleteMethod::OneOldest),
_ => Err("Couldn't parse the delete method (allowed: AEN, AEO, ON, OO)"),
}
}

fn parse_min_size(src: &str) -> Result<u64, String> {
match src.parse::<u64>() {
Ok(min_size) => {
if min_size > 0 {
Ok(min_size)
} else {
Err("Minimum file size must be at least 1 byte".to_string())
}
}
Err(e) => Err(e.to_string()),
}
}

static HELP_MESSAGE: &str = "Prints help information (--help will give more information)";

const HELP_TEMPLATE: &str = r#"
{bin} {version}
USAGE:
{usage} [SCFLAGS] [SCOPTIONS]
FLAGS:
{flags}
SUBCOMMANDS:
{subcommands}
try "{usage} -h" to get more info about a specific tool
EXAMPLES:
{bin} dup -d /home/rafal -e /home/rafal/Obrazy -m 25 -x 7z rar IMAGE -s hashmb -f results.txt -D aeo
{bin} empty-folders -d /home/rafal/rr /home/gateway -f results.txt
{bin} big -d /home/rafal/ /home/piszczal -e /home/rafal/Roman -n 25 -x VIDEO -f results.txt
{bin} empty-files -d /home/rafal /home/szczekacz -e /home/rafal/Pulpit -R -f results.txt
{bin} temp -d /home/rafal/ -E */.git */tmp* *Pulpit -f results.txt -D"#;
Loading

0 comments on commit e4af905

Please sign in to comment.