aopt/
lib.rs

1#![doc = include_str!("../README.md")]
2pub mod ctx;
3pub mod guess;
4pub mod opt;
5pub mod parser;
6pub mod set;
7#[cfg(feature = "shell")]
8pub mod shell;
9pub mod value;
10
11pub use crate::acore::args;
12pub use crate::acore::err;
13pub use crate::acore::error;
14pub use crate::acore::failure;
15pub use crate::acore::map;
16pub use crate::acore::str;
17pub use crate::acore::trace;
18pub use crate::acore::ARef;
19pub use crate::acore::HashMap;
20pub use crate::acore::Uid;
21
22pub(crate) use aopt_core as acore;
23
24#[cfg(feature = "shell")]
25pub(crate) use aopt_shell as ashell;
26
27pub use crate::err::Error;
28pub use crate::err::Result;
29
30/// Get the [`TypeId`](std::any::TypeId) of type `T`.
31pub(crate) fn typeid<T: ?Sized + 'static>() -> std::any::TypeId {
32    std::any::TypeId::of::<T>()
33}
34
35#[derive(Debug)]
36pub struct GetoptRes<R, T> {
37    pub ret: R,
38
39    pub parser: T,
40}
41
42/// Parse the string sequence with given [`Parser`](crate::parser::Parser).
43///
44/// # Returns
45///
46/// For style `getopt!(..., &mut parser1, &mut parser2)`,
47/// will return an Ok([`GetoptRes`]\(T is the type of matched [`Parser`](crate::parser::Parser)\)) if any [`Parser`](crate::parser::Parser) parsing successed.
48/// For style `getopt!(..., "first" => &mut parser1, "second" => &mut parser2)`,
49/// will return an Ok([`GetoptRes`]\(T is the literal type\)) if any [`Parser`](crate::parser::Parser) parsing successed.
50///
51/// Will return Err([`Error::no_parser_matched()`]) if all [`Parser`](crate::parser::Parser) parsing failed, otherwise return Err(_).
52/// # Example
53///
54/// ```rust
55/// # use aopt::err::Result;
56/// # use aopt::prelude::*;
57/// #
58/// # fn main() -> Result<()> {
59/// let mut parser = AFwdParser::default();
60/// let mut pre_parser = AFwdParser::default();
61///
62/// pre_parser.set_prepolicy(true);
63/// {
64///     parser.add_opt("-a=b!")?;
65///     parser.add_opt("--bopt=i")?;
66///     parser.add_opt("c=p@-0")?.on(
67///         |_, ctx: &mut Ctx| {
68///             let val = ctx.value::<String>()?;
69///             let args = ctx.args();
70///             assert_eq!(args[0], OsStr::new("foo"));
71///             Ok(Some(val))
72///         },
73///     )?;
74///
75///     assert!(getopt!(Args::from(["-a", "--bopt=42", "foo"]), &mut parser).is_ok());
76///     assert_eq!(parser.find_val::<bool>("-a")?, &true);
77///     assert_eq!(parser.find_val::<i64>("--bopt")?, &42i64);
78/// }
79/// {
80///     pre_parser.add_opt("-d".infer::<String>())?.set_values(vec![]);
81///     pre_parser.add_opt("--eopt=s")?;
82///
83///     let ret = getopt!(
84///         Args::from(["-dbar", "-d", "foo", "--eopt=pre", "foo"]),
85///         &mut pre_parser
86///     )?;
87///     let args = ret.ret.clone_args();
88///     let parser = ret.parser;
89///
90///     assert_eq!(
91///         parser.find_vals::<String>("-d")?,
92///         &vec!["bar".to_owned(), "foo".to_owned()],
93///     );
94///     assert_eq!(parser.find_val::<String>("--eopt")?, &String::from("pre"));
95///     assert_eq!(args, vec![OsStr::new("foo")] );
96/// }
97///
98/// parser.reset()?;
99/// pre_parser.reset()?;
100///
101/// {
102///     let ret = getopt!(
103///         Args::from(["-a", "--bopt=42", "foo"]),
104///         "parser" => &mut parser,
105///         "pre" => &mut pre_parser
106///     )?;
107///
108///     assert_eq!(ret.parser, "parser");
109///     assert_eq!(parser.find_val::<bool>("-a")?, &true);
110///     assert_eq!(parser.find_val::<i64>("--bopt")?, &42i64);
111/// }
112/// {
113///     let res = getopt!(
114///         Args::from(["-dbar", "-d", "foo", "--eopt=pre", "foo"]),
115///         "parser" => &mut parser,
116///         "pre" => &mut pre_parser
117///     )?;
118///     let args = res.ret.clone_args();
119///
120///     assert_eq!(res.parser, "pre");
121///     assert_eq!(
122///         pre_parser.find_vals::<String>("-d")?,
123///         &vec!["bar".to_owned(), "foo".to_owned()],
124///     );
125///     assert_eq!(pre_parser.find_val::<String>("--eopt")?, &String::from("pre"));
126///     assert_eq!(args, vec![OsStr::new("foo")]);
127/// }
128/// # Ok(())
129/// # }
130///```
131#[macro_export]
132macro_rules! getopt {
133    ($args:expr, $($parser_left:path),+) => {
134        getopt!($args, $(&mut $parser_left)+)
135    };
136    ($args:expr, $(&mut $parser_left:path),+) => {
137        {
138            fn __check_p<'b, S: $crate::prelude::Set, P: $crate::prelude::Policy<Set = S, Error = $crate::Error>>
139                (p: &'b mut $crate::prelude::Parser<S, P>) -> &'b mut $crate::prelude::Parser<S, P>
140                { p }
141            fn __check_a(a: $crate::prelude::Args) -> $crate::prelude::Args { a }
142
143            let mut ret = $crate::Error::no_parser_matched();
144            let args = __check_a($args);
145
146            loop {
147                $(
148                    let parser = __check_p(&mut $parser_left);
149
150                    match $crate::parser::Parser::parse(parser, args.clone()) {
151                        Ok(mut parser_ret) => {
152                            if let Some(error) = parser_ret.take_failure() {
153                                ret = error;
154                            }
155                            else {
156                                break Ok($crate::GetoptRes {
157                                    ret: parser_ret,
158                                    parser: parser,
159                                });
160                            }
161                        }
162                        Err(e) => {
163                            ret = e;
164                        }
165                    }
166                )+
167                break Err(ret);
168            }
169        }
170    };
171    ($args:expr, $($parser_name:literal => $parser_left:path),+) => {
172        getopt!($args, $($parser_name => &mut $parser_left)+)
173    };
174    ($args:expr, $($parser_name:literal => &mut $parser_left:path),+) => {
175        {
176            fn __check_p<'b, S: $crate::prelude::Set, P: $crate::prelude::Policy<Set = S, Error = $crate::Error>>
177                (p: &'b mut $crate::prelude::Parser<S, P>) -> &'b mut $crate::prelude::Parser<S, P>
178                { p }
179            fn __check_a(a: $crate::prelude::Args) -> $crate::prelude::Args { a }
180
181            let mut ret = $crate::Error::no_parser_matched();
182            let args = __check_a($args);
183
184            loop {
185                $(
186                    let parser = __check_p(&mut $parser_left);
187
188                    match $crate::parser::Parser::parse(parser, args.clone()) {
189                        Ok(mut parser_ret) => {
190                            if let Some(error) = parser_ret.take_failure() {
191                                ret = error;
192                            }
193                            else {
194                                break Ok($crate::GetoptRes {
195                                    ret: parser_ret,
196                                    parser: $parser_name,
197                                });
198                            }
199                        }
200                        Err(e) => {
201                            ret = e;
202                        }
203                    }
204                )+
205                break Err(ret);
206            }
207        }
208    };
209}
210
211pub mod prelude {
212    pub use crate::args::Args;
213    pub use crate::ctx::wrap_handler;
214    pub use crate::ctx::wrap_handler_action;
215    pub use crate::ctx::wrap_handler_fallback_action;
216    pub use crate::ctx::Ctx;
217    pub use crate::ctx::HandlerCollection;
218    pub use crate::ctx::InnerCtx;
219    pub use crate::ctx::Invoker;
220    pub use crate::ctx::NullStore;
221    pub use crate::ctx::Store;
222    pub use crate::ctx::VecStore;
223    pub use crate::getopt;
224    pub use crate::map::ErasedTy;
225    pub use crate::opt::AOpt;
226    pub use crate::opt::Action;
227    pub use crate::opt::Cmd;
228    pub use crate::opt::ConfigBuild;
229    pub use crate::opt::ConfigBuildInfer;
230    pub use crate::opt::ConfigBuildMutable;
231    pub use crate::opt::ConfigBuildWith;
232    pub use crate::opt::ConfigBuilder;
233    pub use crate::opt::ConfigBuilderWith;
234    pub use crate::opt::ConfigValue;
235    pub use crate::opt::ConstrctInfo;
236    pub use crate::opt::Creator;
237    pub use crate::opt::Help;
238    pub use crate::opt::Index;
239    pub use crate::opt::Information;
240    pub use crate::opt::Main;
241    pub use crate::opt::MutOpt;
242    pub use crate::opt::Opt;
243    pub use crate::opt::OptConfig;
244    pub use crate::opt::OptParser;
245    pub use crate::opt::OptValueExt;
246    pub use crate::opt::Pos;
247    #[cfg(feature = "serde")]
248    pub use crate::opt::Serde;
249    pub use crate::opt::StrParser;
250    pub use crate::opt::Style;
251    pub use crate::parser::AppServices;
252    pub use crate::parser::AppStorage;
253    pub use crate::parser::DefaultSetChecker;
254    pub use crate::parser::DelayPolicy;
255    pub use crate::parser::FwdPolicy;
256    pub use crate::parser::HCOptSet;
257    pub use crate::parser::OptStyleManager;
258    pub use crate::parser::Parser;
259    pub use crate::parser::ParserCommit;
260    pub use crate::parser::ParserCommitWithValue;
261    pub use crate::parser::Policy;
262    pub use crate::parser::PolicyParser;
263    pub use crate::parser::PolicySettings;
264    pub use crate::parser::Return;
265    pub use crate::parser::SeqPolicy;
266    pub use crate::parser::UserStyle;
267    pub use crate::parser::UsrValService;
268    pub use crate::set::ctor_default_name;
269    pub use crate::set::Commit;
270    pub use crate::set::Ctor;
271    pub use crate::set::Filter;
272    pub use crate::set::FilterMatcher;
273    pub use crate::set::FilterMut;
274    pub use crate::set::OptSet;
275    pub use crate::set::OptValidator;
276    pub use crate::set::PrefixOptValidator;
277    pub use crate::set::PrefixedValidator;
278    pub use crate::set::Set;
279    pub use crate::set::SetCfg;
280    pub use crate::set::SetChecker;
281    pub use crate::set::SetCommit;
282    pub use crate::set::SetCommitWithValue;
283    pub use crate::set::SetExt;
284    pub use crate::set::SetOpt;
285    pub use crate::set::SetValueFindExt;
286    pub use crate::value::AnyValue;
287    pub use crate::value::ErasedValue;
288    pub use crate::value::Infer;
289    pub use crate::value::InitializeValue;
290    pub use crate::value::RawValParser;
291    pub use crate::value::ValAccessor;
292    pub use crate::value::ValInitializer;
293    pub use crate::value::ValStorer;
294    pub use crate::value::ValValidator;
295    pub use crate::ARef;
296    pub use crate::GetoptRes;
297    pub use crate::Uid;
298    pub use std::ffi::OsStr;
299
300    pub type ACreator = Creator<AOpt, OptConfig, crate::Error>;
301
302    pub type ASet = OptSet<StrParser, ACreator, PrefixOptValidator>;
303
304    pub type AHCSet<'a> = HCOptSet<'a, ASet>;
305
306    pub type AInvoker<'a> = Invoker<'a, AHCSet<'a>>;
307
308    pub type AFwdPolicy<'a> = FwdPolicy<AHCSet<'a>, DefaultSetChecker<AHCSet<'a>>>;
309
310    pub type ADelayPolicy<'a> = DelayPolicy<AHCSet<'a>, DefaultSetChecker<AHCSet<'a>>>;
311
312    pub type ASeqPolicy<'a> = SeqPolicy<AHCSet<'a>, DefaultSetChecker<AHCSet<'a>>>;
313
314    pub type AFwdParser<'a> = Parser<AHCSet<'a>, AFwdPolicy<'a>>;
315
316    pub type ADelayParser<'a> = Parser<AHCSet<'a>, ADelayPolicy<'a>>;
317
318    pub type ASeqParser<'a> = Parser<AHCSet<'a>, ASeqPolicy<'a>>;
319}