1#![doc = include_str!("../README.md")]
2pub mod _reference;
3pub(crate) mod help;
4pub(crate) mod infer;
5pub(crate) mod meta;
6pub(crate) mod parser;
7pub(crate) mod rctx;
8pub(crate) mod value;
9
10pub mod valid;
11
12pub use aopt;
13use aopt::set::Set;
14pub use aopt::Error;
15pub use aopt_help;
16pub use cote_derive;
17
18pub type Result<T> = std::result::Result<T, Error>;
19
20pub mod prelude {
21 pub use aopt::opt::AnyOpt;
22 pub use aopt::opt::Cmd;
23 pub use aopt::opt::Main;
24 pub use aopt::opt::MutOpt;
25 pub use aopt::opt::Pos;
26 pub use aopt::parser::UserStyle;
27 pub use aopt::prelude::ctor_default_name;
28 pub use aopt::prelude::AOpt;
29 pub use aopt::prelude::ARef;
30 pub use aopt::prelude::Action;
31 pub use aopt::prelude::AppServices;
32 pub use aopt::prelude::AppStorage;
33 pub use aopt::prelude::Args;
34 pub use aopt::prelude::Commit;
35 pub use aopt::prelude::ConfigBuild;
36 pub use aopt::prelude::ConfigBuildInfer;
37 pub use aopt::prelude::ConfigBuildWith;
38 pub use aopt::prelude::ConfigBuilder;
39 pub use aopt::prelude::ConfigBuilderWith;
40 pub use aopt::prelude::ConfigValue;
41 pub use aopt::prelude::Ctor;
42 pub use aopt::prelude::Ctx;
43 pub use aopt::prelude::DefaultSetChecker;
44 pub use aopt::prelude::ErasedTy;
45 pub use aopt::prelude::ErasedValue;
46 pub use aopt::prelude::FilterMatcher;
47 pub use aopt::prelude::HandlerCollection;
48 pub use aopt::prelude::Index;
49 pub use aopt::prelude::Infer;
50 pub use aopt::prelude::Information;
51 pub use aopt::prelude::InitializeValue;
52 pub use aopt::prelude::Invoker;
53 pub use aopt::prelude::Opt;
54 pub use aopt::prelude::OptParser;
55 pub use aopt::prelude::OptValidator;
56 pub use aopt::prelude::OptValueExt;
57 pub use aopt::prelude::Policy;
58 pub use aopt::prelude::PolicyParser;
59 pub use aopt::prelude::PolicySettings;
60 pub use aopt::prelude::PrefixOptValidator;
61 pub use aopt::prelude::PrefixedValidator;
62 pub use aopt::prelude::RawValParser;
63 pub use aopt::prelude::Return;
64 pub use aopt::prelude::Set;
65 pub use aopt::prelude::SetCfg;
66 pub use aopt::prelude::SetChecker;
67 pub use aopt::prelude::SetExt;
68 pub use aopt::prelude::SetValueFindExt;
69 pub use aopt::prelude::Store;
70 pub use aopt::prelude::Style;
71 pub use aopt::prelude::ValInitializer;
72 pub use aopt::prelude::ValStorer;
73 pub use aopt::prelude::ValValidator;
74 pub use aopt::prelude::VecStore;
75 pub use aopt::raise_error;
76 pub use aopt::raise_failure;
77 pub use aopt::value::raw2str;
78 pub use aopt::value::Placeholder;
79 pub use aopt::value::Stop;
80 pub use aopt::GetoptRes;
81 pub use aopt::Uid;
82 pub use cote_derive::Cote;
83 pub use cote_derive::CoteOpt;
84 pub use cote_derive::CoteVal;
85
86 pub use crate::help::display_set_help;
87 pub use crate::help::HelpContext;
88 pub use crate::help::HelpDisplay;
89 pub use crate::help::DEFAULT_OPTION_WIDTH;
90 pub use crate::help::DEFAULT_USAGE_WIDTH;
91 pub use crate::infer::InferOverride;
92 pub use crate::meta::OptionMeta;
93 pub use crate::parser::Parser;
94 pub use crate::rctx::Failure;
95 pub use crate::rctx::Frame;
96 pub use crate::rctx::HideValue;
97 pub use crate::rctx::RunningCtx;
98 pub use crate::valid;
99 pub use crate::value::fetch_uid_impl;
100 pub use crate::value::fetch_vec_uid_impl;
101 pub use crate::value::Fetch;
102 pub use crate::CoteRes;
103 pub use crate::ExtractFromSetDerive;
104 pub use crate::IntoParserDerive;
105 pub use crate::NullPolicy;
106 pub use crate::Status;
107 pub use aopt::prelude::ASet as CoteSet;
108
109 pub type FwdPolicy<'inv, S> =
110 aopt::prelude::FwdPolicy<Parser<'inv, S>, DefaultSetChecker<Parser<'inv, S>>>;
111
112 pub type DelayPolicy<'inv, S> =
113 aopt::prelude::DelayPolicy<Parser<'inv, S>, DefaultSetChecker<Parser<'inv, S>>>;
114
115 pub type SeqPolicy<'inv, S> =
116 aopt::prelude::SeqPolicy<Parser<'inv, S>, DefaultSetChecker<Parser<'inv, S>>>;
117}
118
119use std::marker::PhantomData;
120
121use aopt::args::Args;
122use aopt::ctx::Invoker;
123use aopt::parser::Policy;
124use aopt::parser::PolicySettings;
125use aopt::parser::Return;
126use aopt::parser::UserStyle;
127use aopt::prelude::ConfigValue;
128use aopt::prelude::OptParser;
129use aopt::prelude::OptStyleManager;
130use aopt::prelude::OptValidator;
131use aopt::prelude::SetCfg;
132use aopt::prelude::SetValueFindExt;
133
134use crate::prelude::Parser;
135
136pub trait IntoParserDerive<'inv, S>
137where
138 SetCfg<S>: ConfigValue + Default,
139 S: Set + OptParser + OptValidator + Default,
140{
141 fn into_parser() -> Result<Parser<'inv, S>> {
142 let mut parser = Parser::default();
143 Self::update(&mut parser)?;
144 Ok(parser)
145 }
146 fn update(parser: &mut Parser<'inv, S>) -> Result<()>;
147}
148
149pub trait ExtractFromSetDerive<'set, S: SetValueFindExt>
150where
151 SetCfg<S>: ConfigValue + Default,
152{
153 fn try_extract(set: &'set mut S) -> Result<Self>
154 where
155 Self: Sized;
156}
157
158#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
159pub struct CoteRes<P, Policy>
160where
161 Policy: crate::prelude::Policy,
162{
163 pub policy: P,
164
165 pub ret: Policy::Ret,
166
167 pub parser: Policy::Set,
168}
169
170pub trait Status {
171 fn status(&self) -> bool;
172}
173
174impl Status for Return {
175 fn status(&self) -> bool {
176 Return::status(self)
177 }
178}
179
180#[derive(Debug, Clone)]
181pub struct NullPolicy<'inv, S> {
182 style_manager: OptStyleManager,
183
184 marker: PhantomData<(S, &'inv ())>,
185}
186
187impl<S> Default for NullPolicy<'_, S> {
188 fn default() -> Self {
189 Self {
190 style_manager: OptStyleManager::default(),
191 marker: Default::default(),
192 }
193 }
194}
195
196impl<'inv, S> Policy for NullPolicy<'inv, S> {
197 type Ret = Return;
198
199 type Set = Parser<'inv, S>;
200
201 type Inv<'a> = Invoker<'a, Parser<'inv, S>>;
202
203 type Error = crate::Error;
204
205 fn parse(&mut self, _: &mut Self::Set, _: &mut Self::Inv<'_>, _: Args) -> Result<Self::Ret> {
206 Ok(Return::default())
207 }
208}
209
210impl<S> PolicySettings for NullPolicy<'_, S> {
211 fn style_manager(&self) -> &OptStyleManager {
212 &self.style_manager
213 }
214
215 fn style_manager_mut(&mut self) -> &mut OptStyleManager {
216 &mut self.style_manager
217 }
218
219 fn strict(&self) -> bool {
220 false
221 }
222
223 fn styles(&self) -> &[UserStyle] {
224 &self.style_manager
225 }
226
227 fn no_delay(&self) -> Option<&[String]> {
228 None
229 }
230
231 fn overload(&self) -> bool {
232 false
233 }
234
235 fn prepolicy(&self) -> bool {
236 false
237 }
238
239 fn set_strict(&mut self, _: bool) -> &mut Self {
240 self
241 }
242
243 fn set_styles(&mut self, _: Vec<UserStyle>) -> &mut Self {
244 self
245 }
246
247 fn set_no_delay(&mut self, _: impl Into<String>) -> &mut Self {
248 self
249 }
250
251 fn set_overload(&mut self, _: bool) -> &mut Self {
252 self
253 }
254
255 fn set_prepolicy(&mut self, _: bool) -> &mut Self {
256 self
257 }
258}
259
260#[cfg(test)]
261mod test {
262 #[test]
263 fn test_example_simple() {
264 use crate as cote;
265 use crate::prelude::*;
266 use aopt::opt::Pos;
268
269 #[derive(Debug, Cote)]
270 pub struct Example {
271 foo: bool,
273
274 #[arg(index = "1")]
276 bar: Pos<usize>,
277 }
278
279 let example = Example::parse(Args::from(["app", "--foo", "42"]));
280
281 assert!(example.is_ok());
282
283 let example = example.unwrap();
284
285 assert!(example.foo);
286 assert_eq!(example.bar.0, 42);
287
288 let parser = Example::into_parser().unwrap();
289
290 assert_eq!(parser["--foo"].help(), "a flag argument");
291 assert_eq!(parser["bar"].help(), "a position argument");
292 }
293
294 #[test]
295 fn test_multiple_pos_arguments() {
296 use crate::prelude::*;
297 use crate as cote;
299 use aopt::opt::Pos;
300 use std::path::PathBuf;
301
302 #[derive(Debug, Cote)]
303 #[cote(help)]
304 pub struct CopyTool {
305 #[arg(alias = "-f")]
306 force: bool,
307
308 #[arg(alias = "-r")]
310 recursive: bool,
311
312 #[arg(index = "1", help = "The copy destination")]
313 destination: Pos<String>,
314
315 #[arg(index = 2..)]
317 sources: Vec<Pos<PathBuf>>,
318 }
319
320 let example = CopyTool::parse(Args::from(["app", "--force"]));
321
322 assert!(example.is_err());
323
324 let example = CopyTool::parse(Args::from([
325 "app", "--force", ".", "../foo", "../bar/", "other",
326 ]))
327 .unwrap();
328
329 assert!(example.force);
330 assert!(!example.recursive);
331 assert_eq!(example.destination.0, String::from("."));
332 assert_eq!(
333 example.sources,
334 ["../foo", "../bar/", "other"]
335 .into_iter()
336 .map(|v| Pos::new(PathBuf::from(v)))
337 .collect::<Vec<_>>()
338 );
339 }
340
341 #[test]
342 fn test_fallback() {
343 use crate::prelude::*;
344 use crate as cote;
346 use aopt::opt::Pos;
347
348 #[derive(Debug, Cote)]
349 #[cote(policy = delay, help, on = find_main, name = "find")]
350 pub struct Find {
351 #[arg(name = "-H", nodelay)]
353 hard: bool,
354
355 #[arg(name = "-L", nodelay)]
357 symbol: bool,
358
359 #[arg(name = "-P", nodelay, value = true)]
360 never: bool,
361
362 #[arg(name = "-name", help = "Search the file base on file name")]
363 name: Option<String>,
364
365 #[arg(name = "-size")]
367 size: Option<usize>,
368
369 #[arg(index = "1", help = "Search starting point", fallback = search, then = VecStore)]
370 destination: Vec<Pos<String>>,
371 }
372
373 #[allow(dead_code)]
374 fn search<Set>(_: &mut Set, _: &mut Ctx) -> Result<Option<Vec<String>>, aopt::Error> {
375 Ok(Some(
376 ["file1", "file2", "dir1", "dir2"]
377 .into_iter()
378 .map(|v| v.to_string())
379 .collect(),
380 ))
381 }
382
383 fn find_main<Set>(set: &mut Set, _: &mut Ctx) -> Result<Option<()>, aopt::Error>
384 where
385 Set: SetValueFindExt,
386 SetCfg<Set>: ConfigValue + Default,
387 {
388 let tool = Find::try_extract(set)?;
389
390 assert!(tool.hard,);
391 assert!(!tool.symbol);
392 assert!(tool.never);
393 assert_eq!(tool.name, Some("foo".to_owned()));
394 assert_eq!(tool.size, Some(42));
395 assert_eq!(
396 tool.destination,
397 ["file1", "file2", "dir1", "dir2"]
398 .into_iter()
399 .map(|v| Pos::new(v.to_string()))
400 .collect::<Vec<_>>()
401 );
402
403 Ok(Some(()))
404 }
405
406 let args = Args::from(["app", ".", "-H", "-name=foo", "-size", "42"]);
407
408 let CoteRes { ret, .. } = Find::parse_args(args).unwrap();
409
410 ret.ok().unwrap();
411 }
412
413 #[test]
414 fn sub_test() {
415 assert!(sub_test_impl().is_ok());
416 }
417
418 fn sub_test_impl() -> Result<(), aopt::Error> {
419 use crate::prelude::*;
420 use crate as cote;
422 use std::path::PathBuf;
423
424 #[derive(Debug, Cote, PartialEq, Default)]
425 #[cote(prepolicy, help, name = "app")]
426 pub struct App {
427 #[arg(values = [1usize, 2, 3])]
429 count: Option<Vec<usize>>,
430
431 #[sub(alias = "ls", help = "list subcommand list file of given path")]
432 list: Option<List>,
433
434 #[sub(help = "find something under directory")]
435 find: Option<Find>,
436 }
437
438 #[derive(Debug, Cote, PartialEq)]
439 #[cote(help)]
440 pub struct List {
441 #[arg(help = "list all the file")]
442 all: bool,
443
444 #[arg(valid = valid!([1, 42, 68]))]
445 depth: usize,
446
447 #[arg(index = "1")]
448 path: Pos<PathBuf>,
449 }
450
451 #[derive(Debug, Cote, PartialEq)]
452 #[cote(help)]
453 pub struct Find {
454 recursive: bool,
455
456 #[arg(index = "1")]
457 path: Pos<PathBuf>,
458 }
459
460 let args = Args::from(["app", "ls", "--all", "--depth=42", "."]);
461
462 let app = App::parse(args)?;
463
464 assert_eq!(
465 app,
466 App {
467 count: Some(vec![1, 2, 3]),
468 list: Some(List {
469 all: true,
470 depth: 42,
471 path: Pos(PathBuf::from("."))
472 }),
473 find: None,
474 }
475 );
476
477 let args = Args::from(["app", "list", "--all", "--depth=6", "."]);
478
479 let app = App::parse(args);
480
481 assert!(app.is_err());
482
483 let args = Args::from(["app", "--count=8", "find", "something"]);
484
485 let app = App::parse(args)?;
486
487 assert_eq!(
488 app,
489 App {
490 count: Some(vec![1, 2, 3, 8]),
491 list: None,
492 find: Some(Find {
493 recursive: false,
494 path: Pos(PathBuf::from("something")),
495 }),
496 }
497 );
498
499 let args = Args::from(["app", "--count", "42"]);
500
501 let app = App::parse(args);
502
503 assert!(app.is_err());
504
505 let args = Args::from(["app", "--count=42", "list"]);
506
507 let CoteRes {
508 ret,
509 parser: mut app,
510 ..
511 } = App::parse_args(args)?;
512
513 assert!(!ret.status());
514 assert_eq!(
515 app.extract_type::<App>()?,
516 App {
517 count: Some(vec![1, 2, 3, 42]),
518 list: None,
519 find: None,
520 }
521 );
522
523 Ok(())
524 }
525}