1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! `structopt-toml` is an default value loader from TOML for structopt.
//!
//! ## Examples
//!
//! The following example show a quick example of `structopt-toml`.
//!
//! 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.
//!
//! ```
//! #[macro_use]
//! extern crate serde_derive;
//! #[macro_use]
//! extern crate structopt;
//! #[macro_use]
//! extern crate structopt_toml;
//! extern crate toml;
//! 
//! 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 of the above example is below.
//!
//! ```ignore
//! $ ./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
//! ```

#[macro_use]
extern crate error_chain;
extern crate clap as _clap;
extern crate serde as _serde;
extern crate structopt as _structopt;
extern crate toml as _toml;

#[allow(unused_imports)]
#[macro_use]
extern crate structopt_toml_derive;

#[doc(hidden)]
pub use structopt_toml_derive::*;

use std::ffi::OsString;

/// Re-export of clap
pub mod clap {
    pub use _clap::*;
}
/// Re-export of serde
pub mod serde {
    pub use _serde::*;
}
/// Re-export of structopt
pub mod structopt {
    pub use _structopt::*;
}

error_chain! {
    foreign_links {
        Toml(::_toml::de::Error);
    }
}

pub trait StructOptToml {
    /// Merge the struct from TOML and the struct from args
    fn merge<'a>(from_toml: Self, from_args: Self, args: &_clap::ArgMatches) -> Self
    where
        Self: Sized,
        Self: _structopt::StructOpt,
        Self: _serde::de::Deserialize<'a>;

    /// Creates the struct from `clap::ArgMatches` with initial values from TOML.
    fn from_clap_with_toml<'a>(toml_str: &'a str, args: &_clap::ArgMatches) -> Result<Self>
    where
        Self: Sized,
        Self: _structopt::StructOpt,
        Self: _serde::de::Deserialize<'a>,
    {
        let from_args: Self = _structopt::StructOpt::from_clap(&args);
        let from_toml: Self = _toml::from_str(toml_str)?;
        Ok(Self::merge(from_toml, from_args, &args))
    }

    /// Creates the struct from command line arguments with initial values from TOML.
    fn from_args_with_toml<'a>(toml_str: &'a str) -> Result<Self>
    where
        Self: Sized,
        Self: _structopt::StructOpt,
        Self: _serde::de::Deserialize<'a>,
    {
        let clap = Self::clap();
        let args = clap.get_matches();
        Self::from_clap_with_toml(toml_str, &args)
    }

    /// Creates the struct from iterator with initial values from TOML.
    fn from_iter_with_toml<'a, I>(toml_str: &'a str, iter: I) -> Result<Self>
    where
        Self: Sized,
        Self: _structopt::StructOpt,
        Self: _serde::de::Deserialize<'a>,
        I: IntoIterator,
        I::Item: Into<OsString> + Clone,
    {
        let clap = Self::clap();
        let args = clap.get_matches_from(iter);
        Self::from_clap_with_toml(toml_str, &args)
    }
}