Possible to use StructOpt or Clap parser to parse String?

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.

Cheers,
Tobias

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

structopt = "0.1.0"
structopt-derive = "0.1.0"

to my Cargo.toml file and added

extern crate structopt;
#[macro_use]
extern crate structopt_derive;

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

from_iter requires structopt 0.2 or higher. The lastest version is 0.3.

Oh wow, that's stupid, I copied that without thinking from the crate page... It works now! Thanks a bunch and have a great day! :slight_smile:

Btw, do you perhaps know whether it is possible to just pass vec!["a"] and get Foo::A back, in your example?

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.