Skip to main content

renamer/
args.rs

1use regex::Regex;
2use std::{error::Error, path::PathBuf};
3use structopt::StructOpt;
4
5/// Parse a single key-value pair
6// https://github.com/TeXitoi/structopt/blob/master/examples/keyvalue.rs
7fn 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// TODO: string patterns (like "005-" or "_01") around increment.
25#[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    /// Test the regular expression against all possible matches instead of only the first.
35    #[structopt(short, long)]
36    pub global: bool,
37
38    /// Perform a dry-run. Do everything but the actual renaming. Implies verbose.
39    #[structopt(short, long)]
40    pub dry_run: bool,
41
42    /// Print operations as they are being performed.
43    #[structopt(short, long)]
44    pub verbose: bool,
45
46    /// Do not exit or ask for confirmation when overwriting files.
47    #[structopt(short, long)]
48    pub force: bool,
49
50    /// Ask for confirmation before overwrite. The program will otherwise exit unless --force is passed.
51    #[structopt(short, long)]
52    pub interactive: bool,
53
54    /// Ignores directories passed to the program as files. Useful for shell globbing.
55    #[structopt(long)]
56    pub ignore_invalid_files: bool,
57
58    /// Prefix files with an increasing counter in the specified format. E.g. 0501 => 0501filename, 0502filename.
59    #[structopt(long, parse(try_from_str = parse_increment))]
60    pub prefix_increment: Option<Increment>,
61
62    /// See --prefix-increment. Will try to insert suffix before the file extension.
63    #[structopt(long, parse(try_from_str = parse_increment))]
64    pub suffix_increment: Option<Increment>,
65
66    /// Regex pattern to match and the string to replace it with. (REGEX=REPLACEMENT)
67    #[structopt(required = true, parse(try_from_str = parse_pattern))]
68    pub pattern: (Regex, String),
69
70    /// Additional patterns. These can be supplied multiple times. Patterns are executed in the order they are passed, starting with the mandatory pattern.
71    #[structopt(short = "e", long = "regexp", parse(try_from_str = parse_pattern), number_of_values = 1)]
72    pub patterns: Vec<(Regex, String)>,
73
74    /// Files to rename.
75    #[structopt(required = true)]
76    pub files: Vec<PathBuf>,
77}