use clap::Parser;
use regex::Regex;
use std::error::Error;
#[derive(Debug)]
pub struct Config {
pub magic_comment_str: String,
pub template_re: Regex,
pub run_python: bool,
pub delete_python: bool,
pub tab_size: u32,
}
#[derive(Debug, Default)]
pub struct FileOptions {
pub input: String,
pub output: Option<String>,
}
impl Default for Config {
fn default() -> Self {
Self::new(
"!".to_string(),
Self::default_template_re(),
false,
false,
4,
)
}
}
fn parse_key_val(s: &str) -> Result<(String, String), Box<dyn Error>>
{
let pos = s
.find('=')
.ok_or_else(|| format!("invalid KEY=value: no `=` found in `{}`", s))?;
Ok((s[..pos].to_string(), s[pos + 1..].to_string()))
}
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
#[arg(index = 1, value_name = "FILE")]
input: String,
#[arg(short, long)]
output: Option<String>,
#[arg(
short = 'r',
long = "run-py",
conflicts_with = "run_python_del",
default_value = "false"
)]
run_python: bool,
#[arg(
short = 'R',
long = "run-py-del",
conflicts_with = "run_python",
default_value = "false"
)]
run_python_del: bool,
#[arg(short, long, default_value = "4", value_name = "INT")]
tab_size: u32,
#[arg(short, long, default_value = "!", value_name = "STRING")]
magic: String,
#[arg(short, long = "var", value_name = "KEY=VAL")]
vars: Vec<String>,
#[arg(short, long = "preamble", value_name = "FILE")]
preamble_py: Option<String>
}
impl Config {
pub fn new(
magic_comment_str: String,
template_re: Regex,
run_python: bool,
delete_python: bool,
tab_size: u32,
) -> Config {
Config {
magic_comment_str,
template_re,
run_python,
delete_python,
tab_size,
}
}
pub fn from_args() -> (Config, FileOptions, Option<Vec<(String, String)>>, Option<String>) {
let args = Args::parse();
let vars = args
.vars
.iter()
.map(|s| parse_key_val(s))
.collect::<Result<Vec<(String, String)>, Box<dyn Error>>>();
if vars.is_err() {
eprintln!("Error: {}", vars.err().unwrap());
std::process::exit(1);
}
(
Self::new(
args.magic,
Self::default_template_re(),
args.run_python || args.run_python_del,
args.run_python_del && !args.run_python,
args.tab_size,
),
FileOptions {
input: args.input,
output: args.output,
},
vars.ok(),
args.preamble_py,
)
}
pub fn default_magic_comment_str() -> String {
"!".to_string()
}
pub fn default_template_re() -> Regex {
Regex::new(r"`([^`]+)`").unwrap()
}
}