Sorry, I don't understand your needs. Can you five a rough example of what you would like to do?
Something like the following:
#[macro_use]
extern crate structopt;
use std::path::PathBuf;
use structopt::StructOpt;
/// A basic example
#[derive(StructOpt, Debug)]
#[structopt(name = "basic")]
struct Opt {
/// Activate debug mode
#[structopt(short = "d", long = "debug")]
debug: bool,
/// Set speed
#[structopt(short = "s", long = "speed", default_value = "42")]
speed: f64,
}
fn main() {
let mut args = HashMap::new();
args.insert("debug", "true");
args.insert("speed", "24.55");
let opt = Opt::from_hashmap(&args);
println!("{:?}", opt);
}
Here's my original attempt (using serde) which fails:
https://play.rust-lang.org/?gist=541f423f06396570934b8bbaca05f549&version=stable
Ha, OK. This kind of features is more toward clap. You can also look at #72.
A dirty workaround would be something like that:
let mut v = vec["exec-name".to_string()];
v.extend(args.iter().map|(k, v)| format!("--{}={}", k, v);
let opt = Opt::from_iter(&v);
(not tested, for the idea)
Tested version:
#[macro_use]
extern crate structopt;
use std::collections::HashMap;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
struct Opt {
// you need parse for this field to be an option and not a flag
#[structopt(long = "debug", parse(try_from_str))]
debug: bool,
#[structopt(long = "speed")]
speed: f64,
}
fn main() {
let mut args = HashMap::new();
args.insert("debug", "true");
args.insert("speed", "24.55");
let mut v = vec!["exec-name".to_string()];
v.extend(args.iter().map(|(k, v)| format!("--{}={}", k, v)));
let opt = Opt::from_iter(&v);
println!("{:?}", opt);
}
Thanks!! Enhanced the example a bit using the new from_iter_safe (thanks @quodlibetor !!)
#[macro_use]
extern crate structopt;
use std::collections::HashMap;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
struct MyParams {
// you need parse for this field to be an option and not a flag
#[structopt(long = "debug", parse(try_from_str))]
debug: bool,
#[structopt(long = "speed")]
speed: f64,
#[structopt(long = "name")]
name: String,
}
macro_rules! structopt_from_map {
($map:expr, $type:ident) => {{
let mut v = vec!["exec-name".to_string()];
v.extend($map.iter().map(|(k, v)| format!("--{}={}", k, v)));
$type::from_iter_safe(&v)
}};
}
fn main() {
let mut args = HashMap::new();
args.insert("debug", "true");
args.insert("speed", "24.55");
args.insert("name", "sharksforarms");
let opt = structopt_from_map!(&args, MyParams);
println!("{:?}", opt);
}
You don't need macro:
#[macro_use]
extern crate structopt;
use std::collections::HashMap;
#[derive(StructOpt, Debug)]
struct MyParams {
// you need parse for this field to be an option and not a flag
#[structopt(long = "debug", parse(try_from_str))]
debug: bool,
#[structopt(long = "speed")]
speed: f64,
#[structopt(long = "name")]
name: String,
}
// Maybe overly generic
fn structopt_from_map<T, I, K, V>(args: I) -> Result<T, structopt::clap::Error>
where
T: structopt::StructOpt,
I: IntoIterator<Item=(K, V)>,
K: std::fmt::Display,
V: std::fmt::Display,
{
let mut v = vec!["exec-name".to_string()];
v.extend(args.into_iter().map(|(k, v)| format!("--{}={}", k, v)));
T::from_iter_safe(&v)
}
fn main() {
let mut args = HashMap::new();
args.insert("debug", "true");
args.insert("speed", "24.55");
args.insert("name", "sharksforarms");
let opt: Result<MyParams, _> = structopt_from_map(&args);
println!("{:?}", opt);
}
Most helpful comment
You don't need macro: