1use regex::Regex;
2use std::{error::Error, path::PathBuf};
3use structopt::StructOpt;
4
5fn parse_pattern(s: &str) -> Result<(Regex, String), Box<dyn Error>> {
8 let pos = s
9 .find('=')
10 .ok_or_else(|| format!("invalid REGEX=REPLACEMENT: no `=` found in `{}`", s))?;
11
12 let pattern = Regex::new(&s[..pos])?;
13
14 Ok((pattern, s[pos + 1..].parse()?))
15}
16
17fn parse_increment(s: &str) -> Result<Increment, Box<dyn Error>> {
18 Ok(Increment {
19 width: s.len(),
20 start: s.parse()?,
21 })
22}
23
24#[derive(Debug, Copy, Clone)]
26pub struct Increment {
27 pub width: usize,
28 pub start: usize,
29}
30
31#[derive(Debug, StructOpt)]
32#[structopt(author, about)]
33pub struct Options {
34 #[structopt(short, long)]
36 pub global: bool,
37
38 #[structopt(short, long)]
40 pub dry_run: bool,
41
42 #[structopt(short, long)]
44 pub verbose: bool,
45
46 #[structopt(short, long)]
48 pub force: bool,
49
50 #[structopt(short, long)]
52 pub interactive: bool,
53
54 #[structopt(long)]
56 pub ignore_invalid_files: bool,
57
58 #[structopt(long, parse(try_from_str = parse_increment))]
60 pub prefix_increment: Option<Increment>,
61
62 #[structopt(long, parse(try_from_str = parse_increment))]
64 pub suffix_increment: Option<Increment>,
65
66 #[structopt(required = true, parse(try_from_str = parse_pattern))]
68 pub pattern: (Regex, String),
69
70 #[structopt(short = "e", long = "regexp", parse(try_from_str = parse_pattern), number_of_values = 1)]
72 pub patterns: Vec<(Regex, String)>,
73
74 #[structopt(required = true)]
76 pub files: Vec<PathBuf>,
77}