Code Monkey home page Code Monkey logo

structopt-toml's Introduction

structopt-toml

An default value loader from TOML for structopt. It combinates with structopt.

Actions Status Crates.io Docs.rs codecov

Usage

This crate must be used with serde, serde_derive, structopt, and toml explicitly.

[dependencies]
serde          = "1.0.104"
serde_derive   = "1.0.104"
structopt      = "0.3.11"
structopt-toml = "0.5.1"
toml           = "0.5.6"

Example

If derive(Deserialize), derive(StructOptToml) and serde(default) are added to the struct with derive(StructOpt), some functions like from_args_with_toml can be used.

use serde_derive::Deserialize;
use structopt::StructOpt;
use structopt_toml::StructOptToml;

#[derive(Debug, Deserialize, StructOpt, StructOptToml)]
#[serde(default)]
struct Opt {
    #[structopt(default_value = "0", short = "a")] a: i32,
    #[structopt(default_value = "0", short = "b")] b: i32,
}

fn main() {
    let toml_str = r#"
        a = 10
    "#;
    let opt = Opt::from_args_with_toml(toml_str).expect("toml parse failed");
    println!("a:{}", opt.a);
    println!("b:{}", opt.b);
}

The execution result is below.

$ ./example
a:10        // value from TOML string
b:0         // value from default_value of structopt

$ ./example -a 20
a:20        // value from command line argument
b:0

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

structopt-toml's People

Contributors

azriel91 avatar dalance avatar dependabot-preview[bot] avatar dovreshef avatar kngwyu avatar psiace avatar vaffeine avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

structopt-toml's Issues

Fields with underscore in there name are not supported

Hello,

This crate is extremely useful and works like charm, though I think I've found a bug. The default values are parsed from the TOML file fine until the field name has no underscore. In case any underscores, the default value given in the TOML file cannot be overridden from CLI.

For the dependencies I use the same dependencies you listed in the readme. Here is a code example, I think it's helpful:

use serde_derive::Deserialize;
use structopt::StructOpt;
use structopt_toml::StructOptToml;

#[derive(Debug, Deserialize, StructOpt, StructOptToml)]
#[serde(default)]
struct Opt {
    #[structopt(default_value="0", short)]
    a: u32,
    #[structopt(default_value="0", short)]
    b_a: u32,
}

fn main() {
    let toml_str = r#"
        a = 2
        b_a = 8
    "#;
    let opt = Opt::from_args_with_toml(toml_str).expect("toml parse failed");
    println!("a: {}", opt.a);
    println!("b_a: {}", opt.b_a);
}

Executing cargo run -- -a 10 -b 20 will print the following:
The problem is not with the short/long name of the option, I already checked that.

a: 10
b_a: 8

In case you need me for testing of further questions, feel free to ping me.
Thank you in advance.

subcommand support

I currently have a subcommand system, and I would like to be able to merge the entire command invocation with the output toml file's defaults.

I feel like there should be some way for me to automatically be able to have structopt-toml figure out where the args are in the command invocation that corresponds to the subcommand I am using structopt-toml on, otherwise I have to "guess" where the args start for the subcommand and pass them in as an iterator from there.

flatten with default raise error

since #7 , flatten is very useful, but i found follow code will raise error.

use serde_derive::Deserialize;
use structopt::StructOpt;
use structopt_toml::StructOptToml;

#[derive(Debug, Deserialize, StructOpt, StructOptToml)]
#[serde(default)]
struct Outer {
    #[structopt(long = "one", default_value = "1")]
    one: u32,
    #[structopt(flatten)]
    two: Inner,
}

#[derive(Debug, Deserialize, StructOpt, StructOptToml)]
#[serde(default)]
struct Inner {
    #[structopt(long = "three", default_value = "1")]
    three: u32,
    #[structopt(long = "four", default_value = "1")]
    four: u32,
}

fn main() {
    let toml_str = r#"
        one = 2
        two.three = 2
        two.four = 2
    "#;
    let test = Outer::from_args_with_toml(toml_str).unwrap();
    println!("{:?}", test);
}
[N] ❯ cargo run -- --one=3
   Compiling struct-default v0.1.0 (/private/tmp/struct-default)
    Finished dev [unoptimized + debuginfo] target(s) in 0.37s
     Running `target/debug/struct-default --one=3`
error: Found argument '--one' which wasn't expected, or isn't valid in this context

What is the Default implementation in the macro used for

Hi

From the impl_structopt_for_struct function the following Default trait implementation is generated:

        impl Default for #name {
            fn default() -> Self {
                let args = vec!["bin"];
                #name::from_iter(args.iter())
            }
        }

It is then called by serde if there is no value in the toml string.
But I don't understand why its implementation is the way it is.

It fails me in the following case:

use structopt::StructOpt;
use structopt_toml::StructOptToml;
use serde_derive::Deserialize;


#[derive(Debug, Deserialize, StructOpt, StructOptToml)]
#[serde(default)]
struct Cmdline {
    #[structopt(long = "url", required_unless = "path")]
    url: Option<String>,

    #[structopt(long = "path", conflicts_with = "url")]
    path: Option<String>,
}

fn main() {
    let data = String::new();

    // let opt = Cmdline::from_args();
    let opt = Cmdline::from_args_with_toml(&data).unwrap();
    println!("{:?}", opt);
}

Trying to run the example above while supplying any one of the two arguments will fail:

19:01 $ cargo run --  --url https://example.com
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/so --url 'https://example.com'`
error: The following required arguments were not provided:
    --url <url>

USAGE:
    bin [OPTIONS] --url <url>

For more information try --help

From the bin for the binary name I can see that's it's taken from the Default implementation. But I'm not clear to what purpose..

Derived `Default` implementation incorrect?

impl Default for #name {
fn default() -> Self {
#name::from_args()
}
}

Isn't it incorrect to call from_args when say from_clap_with_toml initiates a merge?

from_args assumes that all of the process arguments are being parsed. But from_clap_with_toml's ArgMatches argument could refer to only some of the process arguments.

I have so far been unsuccessful in figuring out how to fix this. Perhaps the solution will be obvious to you.

options without default-value

I'm not sure if this is possible with the approach the crate uses, but I think it would be nice if you could have options that must be specified at least either in the cli arguments or in the toml, but cannot be omitted entirely.

An exemplary use-case would be a hostname, which should not have any default-value, but could be configured in either the config or overwritten in the arguments (and would also work without being specified in the config).

Currently, this doesn't work as structopt instantly errors with The following required arguments were not provided: without even checking the config.toml.

Doesn't work with enums (subcommands), only uses values from toml file, not from CLI

Hi, thanks for this crate, its premise seems very useful :)
I'm running into an issue though:
from_args_with_toml doesn't seem to overwrite toml-specified field values with cli-specified values when the field occurs within an enum variant that represents a #[structopt(subcommand)], e.g.:

#[derive(Debug, Deserialize, StructOpt, StructOptToml)]
#[structopt(setting(AppSettings::DeriveDisplayOrder))]
struct Args {
	#[structopt(subcommand)]
	cmd: Command,
}

#[derive(Debug, Deserialize, StructOpt)]
enum Command {
	Foo {
		#[structopt(short, long, default_value = "0")]
		#[serde(default)]
		bar: usize,
	},
}

It always uses the toml-specified value for bar, ignoring the cli-specified value for `bar!

Also if the cmd is not toml-specified but cli-specified, it returns an error saying that cmd is missing:

missing field cmd at line 1 column 1

Ideally it would merge both toml and CLI values before checking if something is missing. And CLI-specified values for a field should take priority over toml-specified values.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.