clap_conf/
lib.rs

1//! Clap Conf
2//! =========
3//!
4//! Use this library to unify how you get configuration options from
5//!
6//! * The command line arguments
7//! * Config Files
8//! * Environmant Variables
9//!
10//!
11//! Basic Usage
12//! ----------
13//!
14//! ```
15//! use clap_conf::prelude::*;
16//!
17//! let matches = clap_app!(my_app=>
18//!     (@arg filename:-f +takes_value "the input filename")
19//!     //...
20//! ).get_matches();
21//!
22//! let cfg = with_toml_env(&matches,&["toml/config/locations"]);
23//!
24//! //the result must be a String as std::env::var has to return a String not a pointer
25//! let filename =
26//! cfg.grab().arg("filename").conf("input.filename").env("MY_APP_INPUT_FILE").def("default.file");
27//!
28//! //if the arguments were supplied this would return something else.
29//! assert_eq!(filename,"default.file".to_string());
30//!
31//! ```
32
33pub mod clapget;
34pub mod convert;
35pub mod env;
36pub mod grabber;
37pub mod prelude;
38pub mod replace;
39pub mod tomlget;
40
41use crate::convert::Holder;
42use crate::convert::Localizer;
43use crate::replace::replace_env;
44use std::path::PathBuf;
45
46pub use clap::{clap_app, crate_version, ArgMatches, Values};
47
48pub fn clap_env<'a, G: Getter<'a>>(a: G) -> Holder<env::Enver, G>
49where
50    String: From<G::Out>,
51{
52    //a.wrap(|v|v.to_string()).hold(env::Enver{})
53    env::Enver {}.hold(a)
54}
55
56pub fn with_toml_env<'a, G, S, IT>(
57    a: G,
58    it: IT,
59) -> Holder<Holder<env::Enver, G>, Localizer<toml::Value>>
60where
61    G: Getter<'a, Out = &'a str>,
62    S: AsRef<str>,
63    IT: IntoIterator<Item = S>,
64{
65    let tml = tomlget::load_first_toml(a.value("config", Filter::Arg), it)
66        .unwrap_or(Localizer::new(toml::Value::Boolean(false), ""));
67    env::Enver {}.hold(a).hold(tml)
68}
69
70#[derive(Clone, Copy, Debug, PartialEq)]
71pub enum Filter {
72    Conf,
73    Arg,
74    Env,
75    Other(char),
76}
77
78pub trait Getter<'a>: Sized {
79    type Iter: Iterator<Item = Self::Out>;
80    type Out: PartialEq + std::fmt::Debug + std::fmt::Display;
81    fn value<S: AsRef<str>>(&self, s: S, f: Filter) -> Option<Self::Out>;
82    fn values<S: AsRef<str>>(&self, s: S, f: Filter) -> Option<Self::Iter>;
83
84    fn local_value<S: AsRef<str>>(&self, s: S, f: Filter) -> Option<PathBuf> {
85        let v = self.value(s, f)?;
86        let s = replace_env(&v.to_string()).ok()?;
87        Some(PathBuf::from(s))
88    }
89
90    fn bool_flag<S: AsRef<str>>(&self, s: S, f: Filter) -> bool {
91        self.value(s, f).is_some()
92    }
93
94    fn sub<S: AsRef<str>>(&self, _: S, _: Filter) -> bool {
95        return false;
96    }
97
98    fn wrap<R2, F: Fn(Self::Out) -> R2>(self, f: F) -> convert::Wrapper<Self, F> {
99        convert::Wrapper::new(self, f)
100    }
101
102    fn hold<B>(self, b: B) -> convert::Holder<Self, B>
103    where
104        B: Getter<'a>,
105        Self::Out: std::convert::From<B::Out>,
106        B::Out: PartialEq + std::fmt::Debug + std::fmt::Display,
107    {
108        convert::Holder::new(self, b)
109    }
110
111    fn grab(&'a self) -> grabber::Grabber<'a, Self> {
112        grabber::Grabber::new(self)
113    }
114
115    fn grab_local(&'a self) -> grabber::LocalGrabber<'a, Self> {
116        grabber::LocalGrabber::new(self)
117    }
118
119    fn grab_multi(&'a self) -> grabber::MultiGrabber<'a, Self> {
120        grabber::MultiGrabber::new(self)
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127    #[test]
128    fn try_holder() {
129        let a = ArgMatches::new();
130        let tml: toml::Value = "[a]\ncar=\"red\"".parse().unwrap();
131        //        let tml2 = (&tml).wrap(|r| r.as_str().unwrap());
132        let ce = clap_env(&a).hold(tml);
133        //let e = env::Enver {};
134        //let ce = e.hold(&a).hold(tml);
135
136        assert_eq!(ce.value("ss", Filter::Arg), None);
137        assert_eq!(
138            ce.value("PWD", Filter::Env),
139            Some("/home/matthew/scripts/rust/mlibs/clap_conf".to_string())
140        );
141
142        assert_eq!(
143            ce.grab().env("PWD").done(),
144            Some("/home/matthew/scripts/rust/mlibs/clap_conf".to_string())
145        );
146
147        assert_eq!(ce.grab().conf("a.car").done(), Some("red".to_string()));
148
149        /* assert_eq!(
150            g.env("PWD").done(),
151            Some("/home/matthew/scripts/rust/mlibs/clap_conf")
152        );
153        */
154    }
155
156    #[test]
157    fn test_grab() {
158        let a = ArgMatches::new();
159        let r = with_toml_env(&a, &["test_data/test1.toml"]);
160        assert_eq!(r.grab().conf("a.b.c").done(), Some("hello".to_string()));
161    }
162}