diff --git a/README.md b/README.md index 3fdf2ac..a28b0bc 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Batch rename utility for developers -![Alt text](/screenshots/usage.png?raw=true "Regex Screenshot") +![Alt text](/screenshots/regex.png?raw=true "Example Screenshot") ## How to install @@ -28,30 +28,35 @@ If you prefer to build nomino manually, or a pre-compiled executable is not prov ## Usage ```bash -USAGE: - nomino [FLAGS] [OPTIONS] [[SOURCE] OUTPUT]... - -FLAGS: - -e, --extension Preserves the extension of input files in 'sort' and 'regex' options - -h, --help Prints help information - -k, --mkdir Recursively creates all parent directories of '' if they are missing - -w, --overwrite Overwrites output files, otherwise, a '_' is prepended to filename - -p, --print Prints the map table to stdout - -t, --test Runs in test mode without renaming actual files [aliases: dry-run] - --dry-run Alias for --test - -V, --version Prints version information - -OPTIONS: - --depth Optional value to overwrite inferred subdirectory depth value in 'regex' mode - --max-depth Optional value to set the maximum of subdirectory depth value in 'regex' mode - -d, --dir Sets the working directory - -g, --generate Stores a JSON map file in '' after renaming files - -m, --map Sets the path of map file to be used for renaming files - -r, --regex Regex pattern to match by filenames - -s, --sort Sets the order of natural sorting (by name) to rename files using enumerator [possible values: ASC, DESC] - -ARGS: - <[SOURCE] OUTPUT>... OUTPUT is the pattern to be used for renaming files, and SOURCE is the optional regex pattern to match by filenames. SOURCE has the same function as -r option +Usage: + nomino [OPTIONS] [[SOURCE] OUTPUT]... + +Arguments: + [[SOURCE] OUTPUT]... + OUTPUT is the pattern to be used for renaming files, and SOURCE is the optional regex pattern to match by filenames. SOURCE has the same function as -r option + +Options: + -d, --dir Sets the working directory + --depth Optional value to overwrite inferred subdirectory depth value in 'regex' mode + -E, --no-extension Does not preserve the extension of input files in 'sort' and 'regex' options + -g, --generate Stores a JSON map file in '' after renaming files + -h, --help Print help (see a summary with '-h') + -k, --mkdir Recursively creates all parent directories of '' if they are missing + -m, --map Sets the path of map file to be used for renaming files + --from-file Alias for --map + --max-depth Optional value to set the maximum of subdirectory depth value in 'regex' mode + -q, --quiet Does not print the map table to stdout + -r, --regex Regex pattern to match by filenames + -s, --sort Sets the order of natural sorting (by name) to rename files using enumerator + Possible ORDER values: + - asc: Sort in ascending order + - desc: Sort in descending order + -t, --test Runs in test mode without renaming actual files + --dry-run Alias for --test + -V, --version Print version + -w, --overwrite Overwrites output files, otherwise, a '_' is prepended to filename + +OUTPUT pattern accepts placeholders that have the format of '{I:P}' where 'I' is the index of captured group and 'P' is the padding of digits with `0`. Please refer to https://github.com/yaa110/nomino for more information. ``` ## Map file format diff --git a/screenshots/regex.png b/screenshots/regex.png new file mode 100644 index 0000000..841fe7f Binary files /dev/null and b/screenshots/regex.png differ diff --git a/screenshots/usage.png b/screenshots/usage.png deleted file mode 100644 index 3d09591..0000000 Binary files a/screenshots/usage.png and /dev/null differ diff --git a/src/cli.rs b/src/cli.rs index ca09a4b..9a0bbae 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -21,9 +21,9 @@ pub struct Cli { /// Overwrites output files, otherwise, a '_' is prepended to filename. #[arg(short = 'w', long)] pub overwrite: bool, - /// Preserves the extension of input files in 'sort' and 'regex' options. - #[arg(short, long)] - pub extension: bool, + /// Does not preserve the extension of input files in 'sort' and 'regex' options. + #[arg(short = 'E', long = "no-extension")] + pub no_extension: bool, /// Sets the working directory. #[arg(short, long = "dir", value_name = "PATH")] pub directory: Option, @@ -36,11 +36,11 @@ pub struct Cli { /// Stores a JSON map file in '' after renaming files. #[arg(short, long, value_name = "PATH")] pub generate: Option, - /// Prints the map table to stdout. + /// Does not print the map table to stdout. #[arg(short, long)] - pub print: bool, + pub quiet: bool, /// Sets the path of map file to be used for renaming files. - #[arg(short, long, value_name = "PATH")] + #[arg(short, long, value_name = "PATH", visible_alias = "from-file")] pub map: Option, /// Sets the order of natural sorting (by name) to rename files using enumerator. #[arg(short, long, value_name = "ORDER", ignore_case = true)] diff --git a/src/main.rs b/src/main.rs index 436ad6d..0ac9cde 100644 --- a/src/main.rs +++ b/src/main.rs @@ -108,15 +108,15 @@ fn rename_files( fn print_map_table(map: Map) { let mut table = Table::new(); table.set_format(*format::consts::FORMAT_NO_LINESEP_WITH_TITLE); - table.set_titles(row!["Input".cyan(), "Output".cyan()]); + table.set_titles(row![Fc => "Input", "Output"]); map.into_iter() .enumerate() .for_each(|(i, (output, input))| { if let Value::String(input) = input { if i % 2 == 0 { - table.add_row(row![input.as_str(), output.as_str()]); + table.add_row(row![input.as_str().normal(), output.as_str().normal()]); } else { - table.add_row(row![input.as_str().purple(), output.as_str().purple()]); + table.add_row(row![Fm => input.as_str(), output.as_str()]); } } }); @@ -147,12 +147,12 @@ fn run_app() -> Result { opts.map.as_deref(), )?, read_output(output.as_deref())?, - opts.extension, + !opts.no_extension, )?; let (map, with_err) = rename_files( input_iter, opts.test, - opts.print || opts.generate.is_some(), + !opts.quiet || opts.generate.is_some(), opts.overwrite, opts.mkdir, ); @@ -162,7 +162,7 @@ fn run_app() -> Result { serde_json::to_vec_pretty(map.as_ref().unwrap())?.as_slice(), )?; } - if let Some(map) = map.filter(|map| opts.print && !map.is_empty()) { + if let Some(map) = map.filter(|map| !opts.quiet && !map.is_empty()) { colored::control::set_override(std::io::stdout().is_terminal()); print_map_table(map); } diff --git a/tests/default_test.rs b/tests/default_test.rs index b7f84bd..6d610aa 100644 --- a/tests/default_test.rs +++ b/tests/default_test.rs @@ -26,6 +26,7 @@ fn test_default() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), r".*E(\d+).*", @@ -69,7 +70,13 @@ fn test_default_not_overwrite() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() - .args(&["-d", dir.path().to_str().unwrap(), r".*E(\d+).*", "1.mkv"]) + .args(&[ + "-E", + "-d", + dir.path().to_str().unwrap(), + r".*E(\d+).*", + "1.mkv", + ]) .unwrap(); let mut files: Vec = read_dir(dir.path()) @@ -109,6 +116,7 @@ fn test_default_overwrite() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-w", @@ -159,6 +167,7 @@ fn test_default_subdir() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-k", @@ -218,6 +227,7 @@ fn test_default_subdir_depth() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "--depth", "2", "-d", @@ -279,6 +289,7 @@ fn test_default_subdir_max_depth() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "--depth", "3", "--max-depth", @@ -342,6 +353,7 @@ fn test_default_subdir_not_overwrite() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-k", @@ -401,6 +413,7 @@ fn test_default_subdir_overwrite() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-k", diff --git a/tests/map_test.rs b/tests/map_test.rs index 03b4b47..6b34419 100644 --- a/tests/map_test.rs +++ b/tests/map_test.rs @@ -51,6 +51,7 @@ fn test_map() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-m", @@ -74,7 +75,7 @@ fn test_map() { let cmd_undo = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() - .args(&["-d", dir.path().to_str().unwrap(), "-m", "undo.json"]) + .args(&["-E", "-d", dir.path().to_str().unwrap(), "-m", "undo.json"]) .unwrap(); let mut files_undo: Vec = read_dir(dir.path()) diff --git a/tests/regex_test.rs b/tests/regex_test.rs index 816f607..98734ae 100644 --- a/tests/regex_test.rs +++ b/tests/regex_test.rs @@ -26,6 +26,7 @@ fn test_regex() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-r", @@ -71,6 +72,7 @@ fn test_regex_not_overwrite() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-r", @@ -116,6 +118,7 @@ fn test_regex_overwrite() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-w", @@ -167,6 +170,7 @@ fn test_regex_subdir() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-k", @@ -227,6 +231,7 @@ fn test_regex_subdir_depth() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "--depth", "2", "-d", @@ -289,6 +294,7 @@ fn test_regex_subdir_max_depth() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "--depth", "3", "--max-depth", @@ -353,6 +359,7 @@ fn test_regex_subdir_not_overwrite() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-k", @@ -413,6 +420,7 @@ fn test_regex_subdir_overwrite() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() .args(&[ + "-E", "-d", dir.path().to_str().unwrap(), "-k", diff --git a/tests/sort_test.rs b/tests/sort_test.rs index 352d7e7..a39694e 100644 --- a/tests/sort_test.rs +++ b/tests/sort_test.rs @@ -23,7 +23,14 @@ fn test_sort() { let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) .unwrap() - .args(&["-d", dir.path().to_str().unwrap(), "-s", "asc", "{:3}.mkv"]) + .args(&[ + "-E", + "-d", + dir.path().to_str().unwrap(), + "-s", + "asc", + "{:3}.mkv", + ]) .unwrap(); let mut files: Vec = read_dir(dir.path())