TeXitoi/structopt

Ability to extract relative order across different options

Closed this issue · 2 comments

Currently, it does not seem possible to extract the relative order of different options. For example, if we have the following definition:

#[derive(Debug, StructOpt)]
pub struct Command {
    #[structopt(long = "some-option")]
    configs: Vec<String>,

    #[structopt(long = "related-option")]
    config_files: Vec<String>,
}

It might be required to know the relative order of elements between --some-option and --related-option.

I've also described the problem in more details on StackOverflow.

use structopt::StructOpt;

#[derive(Debug, StructOpt)]
pub struct Opt {
    #[structopt(long = "config")]
    configs: Vec<String>,

    #[structopt(long = "config-file")]
    config_files: Vec<String>,
}

fn with_indices<'a, I: IntoIterator + 'a>(
    collection: I,
    name: &str,
    matches: &'a structopt::clap::ArgMatches,
) -> impl Iterator<Item = (usize, I::Item)> + 'a {
    matches
        .indices_of(name)
        .into_iter()
        .flatten()
        .zip(collection)
}

fn main() {
    let clap = Opt::clap();
    let matches = clap.get_matches();
    let opt = Opt::from_clap(&matches);

    println!("configs:");
    for (i, c) in with_indices(&opt.configs, "configs", &matches) {
        println!("{}: {}", i, c);
    }

    println!("\nconfig-files:");
    for (i, c) in with_indices(&opt.config_files, "config-files", &matches) {
        println!("{}: {}", i, c);
    }
}

gives:

$ cargo run -- --config a --config-file filea --config b --config c --config-file filec
   Compiling test-rs v0.1.0 (.../test-rs)
    Finished dev [unoptimized + debuginfo] target(s) in 2.08s
     Running `target/debug/test-rs --config a --config-file filea --config b --config c --config-file filec`
configs:
2: a
6: b
8: c

config-files:
4: filea
10: filec

@TeXitoi Brilliant! I completely missed the ArgMatches::indices_of() function.