I use StructOpt to parse my command line arguments and now I'm wondering if it's possible to use the constructed parser (by StructOpt or Clap) to parse a String into one of the structs that derives StructOpt.
What I want to do: I would like to parse a config file (not really command line arguments, so just running a command line parser on it wouldn't work) and most of it is very basic, so I do these using simple line splits and such, but I also would like to parse a line with structs into these structs. As StructOpt already parses Strings into structs, I was wondering if I could re-use that parser to parse this String.
I saw somebody using from_iter to parse Strings, but then I get an error
"error[E0599]: no variant or associated item named from_iter found for enum CodomainFunction in the current scope
--> src/codomain.rs:132:27
|
15 | pub enum CodomainFunction {
| ------------------------- variant or associated item from_iter not found here
...
132 | CodomainFunction::from_iter(codomain_function_string);
| ^^^^^^^^^ variant or associated item not found in CodomainFunction
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item from_iter, perhaps you need to implement it:
candidate #1:FromIterator"
Does anybody know how to do this by chance or have a pointer in the right direction? Thanks in advance.
from_iter is a method of the StructOpt trait. Does your enum implement that trait, and have you imported the trait (use structopt::StructOpt;) in the module where you're calling the method?
Edit: Here's a short example program that works.
use structopt::StructOpt;
#[derive(StructOpt, PartialEq, Debug)]
enum Foo {
A,
B,
}
fn main() {
let f = Foo::from_iter(vec!["foo", "a"]);
assert_eq!(f, Foo::A)
}
Thanks for your quick response. Compiling your example program results in the same error (see below), and I have indeed derived the trait in my program as in your example. So, I'm guessing I'm doing something wrong here. To make this example work, I added
to the top of src/main.rs, as otherwise I get an error that the derive macro StructOpt can't be found. I'm running the latest nightly btw.
The error and a warning that seems weird to me, as we are using it do a derivation:
warning: unused import: structopt::StructOpt
--> src/main.rs:5:5
|
5 | use structopt::StructOpt;
| ^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
error[E0599]: no variant or associated item named from_iter found for enum Foo in the current scope
--> src/main.rs:14:18
|
8 | enum Foo {
| -------- variant or associated item from_iter not found here
...
14 | let f = Foo::from_iter(vec!["foo", "a"]);
| ^^^^^^^^^ variant or associated item not found in Foo
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item from_iter, perhaps you need to implement it:
candidate #1:FromIterator
Normally, clap/structopt ignore the first argument, because that's where the name of the executable goes. So you could pass something like vec!["", "a"] instead. (It doesn't matter what you put in the first argument.)
Or you can use the NoBinaryName setting:
use structopt::StructOpt;
use structopt::clap::AppSettings;
#[derive(StructOpt, PartialEq, Debug)]
#[structopt(setting(AppSettings::NoBinaryName))]
enum Foo {
A,
B,
}
fn main() {
let f = Foo::from_iter(vec!["a"]);
assert_eq!(f, Foo::A)
}
NoBinaryName will break the normal from_args method. If you use it, then you'll need to manually skip the first argument when parsing args from the command line:
let foo = Foo::from_iter(std::env::args_os().skip(1));
Ah, great to know! Cheers for the extensive answer. In my case, I want to keep the regular command line argument parsing untouched, so I'll use your trick of just inserting something in the vector instead.