use clap::{App, AppSettings, Arg, SubCommand};
use std::ffi::{OsStr, OsString};
pub fn create_app<'a>() -> App<'a, 'a> {
App::new(crate_name!())
.setting(AppSettings::SubcommandsNegateReqs)
.version(crate_version!())
.author(crate_authors!())
.about(crate_description!())
.arg(
Arg::with_name("EXPRESSION")
.help("Expression to match (can be a regex)")
.required(true)
.validator_os(is_valid_string)
.index(1),
)
.arg(
Arg::with_name("REPLACEMENT")
.help("Expression replacement")
.required(true)
.validator_os(is_valid_string)
.index(2),
)
.arg(
Arg::with_name("PATH(S)")
.help("Target paths")
.validator_os(is_valid_string)
.multiple(true)
.required(true),
)
.arg(
Arg::with_name("dry-run")
.long("dry-run")
.short("n")
.help("Only show what would be done (default mode)")
.global(true)
.conflicts_with("force"),
)
.arg(
Arg::with_name("force")
.long("force")
.short("f")
.global(true)
.help("Make actual changes to files"),
)
.arg(
Arg::with_name("backup")
.long("backup")
.short("b")
.global(true)
.help("Generate file backups before renaming"),
)
.arg(
Arg::with_name("include-dirs")
.long("include-dirs")
.short("D")
.help("Rename matching directories"),
)
.arg(
Arg::with_name("recursive")
.long("recursive")
.short("r")
.help("Recursive mode"),
)
.arg(
Arg::with_name("max-depth")
.requires("recursive")
.long("max-depth")
.short("d")
.takes_value(true)
.value_name("LEVEL")
.validator(is_integer)
.help("Set max depth in recursive mode"),
)
.arg(
Arg::with_name("hidden")
.requires("recursive")
.long("hidden")
.short("x")
.help("Include hidden files and directories"),
)
.arg(
Arg::with_name("silent")
.long("silent")
.short("s")
.global(true)
.help("Do not print any information"),
)
.arg(
Arg::with_name("color")
.long("color")
.possible_values(&["always", "auto", "never"])
.default_value("auto")
.global(true)
.help("Set color output mode"),
)
.arg(
Arg::with_name("dump")
.long("dump")
.help("Force dumping operations into a file even in dry-run mode")
.global(true)
.conflicts_with("no-dump"),
)
.arg(
Arg::with_name("no-dump")
.long("no-dump")
.help("Do not dump operations into a file")
.global(true)
.conflicts_with("dump"),
)
.arg(
Arg::with_name("replace-limit")
.long("replace-limit")
.short("l")
.takes_value(true)
.value_name("LIMIT")
.default_value("1")
.validator(is_integer)
.help("Limit of replacements, all matches if set to 0"),
)
.subcommand(
SubCommand::with_name("from-file")
.arg(
Arg::with_name("DUMPFILE")
.takes_value(true)
.required(true)
.value_name("DUMPFILE")
.validator_os(is_valid_string)
.index(1),
)
.arg(
Arg::with_name("undo")
.long("undo")
.short("u")
.help("Undo the operations from the dump file"),
)
.about("Read operations from a dump file"),
)
}
#[allow(clippy::all)]
fn is_integer(arg_value: String) -> Result<(), String> {
match arg_value.parse::<usize>() {
Ok(_) => Ok(()),
Err(_) => Err("Value provided is not an integer".to_string()),
}
}
fn is_valid_string(os_str: &OsStr) -> Result<(), OsString> {
match os_str.to_str() {
Some(_) => Ok(()),
None => Err(OsString::from("Value provided is not a valid UTF-8 string")),
}
}
#[cfg(test)]
mod test {}