Structopt "enum like" args

I'm hoping to use the structopt crate to give the user a command line String argument that I can constrain to a simple list of strings for it's valid options. I'm hoping that structopt do it's usual great job of generating a nice help about them as well as detecting when a user attempts to provide a String value not in the acceptable set of options.

In short I want the command line String to behave logically like an enum does.

There's an enum_in_args.rs in the structopt examples that I hoped would do this but it sadly does not build.

I found this here: examples
That I found here: here: crates.io structopt page

fwiw/ here's the build error.


 --> src/main.rs:3:5
  |
3 | use clap::arg_enum;
  |     ^^^^ help: a similar path exists: `structopt::clap`

error: cannot determine resolution for the macro `arg_enum`
 --> src/main.rs:6:1
  |
6 | arg_enum! {
  | ^^^^^^^^
  |
  = note: import resolution is stuck, try simplifying macro imports

error[E0433]: failed to resolve: use of undeclared type `Baz`
  --> src/main.rs:18:36
   |
18 |     #[structopt(possible_values = &Baz::variants(), case_insensitive = true)]
   |                                    ^^^ use of undeclared type `Baz`

error[E0412]: cannot find type `Baz` in this scope
  --> src/main.rs:19:8
   |
19 |     i: Baz,
   |        ^^^ not found in this scope

error[E0282]: type annotations needed
  --> src/main.rs:19:8
   |
17 |     /// Important argument.
   |     ----------------------- this method call resolves to `T`
18 |     #[structopt(possible_values = &Baz::variants(), case_insensitive = true)]
19 |     i: Baz,
   |        ^^^ cannot infer type for type parameter `U` declared on the associated function `map`

Some errors have detailed explanations: E0282, E0412, E0432, E0433.
For more information about an error, try `rustc --explain E0282`.
error: could not compile `structopt` due to 5 previous errors


Here's my Cargo.toml dependency:

[dependencies]
structopt = "0.3.25"

Since structopt pulls in clap I don't think I should add that here. I tried and got even nastier build errors.

Any ideas on where I can actually find a working example would be great for this would be awesome!

Thanks so much!

I would use strum to automatically generate the FromStr impl and list of variants, then do something like this:

// src/main.rs

use structopt::StructOpt;
use strum::VariantNames;

fn main() {
    let args = Args::from_args();
    println!("{:?}", args);
}

#[derive(Debug, StructOpt)]
struct Args {
    #[structopt(long, possible_values = Enumerated::VARIANTS)]
    enumerated: Enumerated,
}

#[derive(Debug, strum::EnumString, strum::EnumVariantNames)]
#[strum(serialize_all = "kebab-case")]
enum Enumerated {
    First,
    Second,
    Third,
}
// Cargo.toml
[package]
name = "dummy"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
structopt = "0.3.25"
strum = { version = "0.22.0", features = ["derive"] }

Which generates the following output:

$ cargo run -- --help
dummy 0.1.0

USAGE:
    dummy --enumerated <enumerated>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --enumerated <enumerated>     [possible values: first, second, third]
1 Like

You can't use dependencies of dependencies like this. If you want to use clap::..., you must add clap to your Cargo.toml, even if it's already included in the project through some other crate. Structopt does re-export it under structopt::clap, so you can also fix the example by changing use clap::arg_enum; to use structopt::clap::arg_enum;

If you tried adding clap to Cargo.toml and got more errors as a result, you might have tried adding an incompatible version.

1 Like

Thank you very much.

Very interesting option. I need to learn more about strum. Looks very useful!

Thanks for the advice. That sounds like the problem.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.