0

I am new to Rust and clap, so I apologize if some of the terminology I use in my question isn't correct.

I am writing a CLI tool in Rust which takes a parameter called property_name. This property_name has a list of possible values, and I want clap to only allow these possible values and reject anything else.

My code builds a vector of these values from other data. For simplicity, I've replaced that code with just a simple vector declaration to illustrate my issue. Here is the code:

    let property_values = vec!["one", "two", "three"];

    #[derive(Parser, Debug)]
    #[clap(author, version, about, long_about = None)]
    struct Args {
       #[structopt(short('n'), long, required=true, value_parser, possible_values=property_values)]
       property_name: Option<String> 
    }

This produces the following error:

error[E0434]: can't capture dynamic environment in a fn item
   --> src\main.rs:114:83
    |
114 |        #[structopt(short('n'), long, required=true, value_parser, possible_values=property_values)]
    |                                                                                   ^^^^^^^^^^^^^^^
    |
    = help: use the `|| { ... }` closure form instead

After reading about the error message and using Google searches, I haven't been able to understand the proper fix. The example fixes given don't seem to help, like using a closure (this is likely not quite the right syntax?):

#[structopt(short('n'), long, required=true, value_parser, possible_values=|property_values|property_values)]

This led to different compiler errors:

    --> src\main.rs:114:67
     |
114  |        #[structopt(short('n'), long, required=true, value_parser, possible_values=|property_values|property_values)]
     |                                                                   ^^^^^^^^^^^^^^^ ----------------- consider calling this closure
     |                                                                   |
     |                                                                   `[closure@src\main.rs:114:83: 114:100]` is not an iterator
     |
     = help: the trait `Iterator` is not implemented for `[closure@src\main.rs:114:83: 114:100]`
     = note: required because of the requirements on the impl of `IntoIterator` for `[closure@src\main.rs:114:83: 114:100]`

I could investigate iterators, and maybe that is the proper fix, but I decided to ask my question here before going further down that path.

Also, if I put the possible values directly into the declaration as an array, like this, it all works as expected:

#[structopt(short('n'), long, required=true, value_parser, possible_values=["one", "two", "three"])]

However, since I am building this vector dynamically at run-time, I can't use this solution.

I'm sure that there's something fundamental that I'm missing, but I don't have enough experience and knowledge with Rust to know where to look to learn how to do this. Would a kind soul point me toward a blog post, documentation, or code sample that could help me understand how to do this?

DanzanRyu
  • 1
  • 2
  • This probably isn't possible. Also FYI: structopt is in maintenance and it's recommended you use `clap`'s derive feature instead. – PitaJ Nov 08 '22 at 21:58
  • It seems as though `possible_values` has been deprecated by clap since 3.2, which absorbed structopt's functionality. This discussion may be informative for you: https://github.com/clap-rs/clap/discussions/3855 – James Williams Nov 08 '22 at 21:59

0 Answers0