use async_std::path::PathBuf;
use bool_ext::BoolExt;
use std::ops::Not;
use structopt::{clap::AppSettings, StructOpt};
#[cfg(test)]
#[path = "./cli_test.rs"]
pub mod cli_test;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Multiple operation modes specified")]
MultipleOperationModes,
#[error("Unknown content `{content}` of environment variable `{var_name}`")]
UnknownEnvVarContent { var_name: String, content: String },
}
#[derive(Debug, StructOpt)]
#[structopt(setting(AppSettings::ColoredHelp))]
pub struct Cli {
#[structopt(short = "n", long)]
pub dry_run: bool,
#[structopt(short, long)]
pub run: bool,
#[structopt(short, long, parse(from_occurrences))]
pub verbose: u8,
#[structopt(short, long)]
pub continue_on_error: bool,
#[structopt(short = "T", long)]
pub traverse_tree: bool,
#[structopt(short, long)]
pub file: bool,
#[structopt(short, long)]
pub directory: bool,
#[structopt(short, long)]
pub symlink: bool,
#[structopt(short = "i", long)]
pub case_insensetive: bool,
#[structopt(
long,
default_value = "true",
env = "FRS_SHOW_ICONS",
parse(try_from_str)
)]
pub icons: bool,
pub search_pattern: String,
pub replace_pattern: String,
#[structopt(default_value = ".")]
pub base_path: PathBuf,
}
impl Cli {
pub fn post_automations(&mut self) -> Result<(), Error> {
self.set_operation_mode()?;
self.set_verbosity();
self.set_types();
Ok(())
}
fn set_operation_mode(&mut self) -> Result<(), Error> {
(self.run && self.dry_run)
.not()
.err(Error::MultipleOperationModes)?;
let do_var_name = "FRS_DEFAULT_OP";
match std::env::var(do_var_name)
.unwrap_or_else(|_| "DRY-RUN".to_string())
.to_uppercase()
.as_str()
{
"RUN" => {
if !self.dry_run {
self.run = true
}
}
"DRY-RUN" => {
if !self.run {
self.dry_run = true
}
}
invalid_do => {
return Err(Error::UnknownEnvVarContent {
var_name: do_var_name.to_string(),
content: invalid_do.to_string(),
})
}
}
Ok(())
}
fn set_verbosity(&mut self) {
self.verbose = self.verbose.max(self.dry_run as u8);
}
fn set_types(&mut self) {
let no_type_selected = !(self.file || self.directory || self.symlink);
self.file |= no_type_selected;
self.directory |= no_type_selected && !self.traverse_tree;
self.symlink |= no_type_selected;
}
}