1extern crate clap;
267
268#[doc(hidden)]
269pub mod clap_export {
270 pub use ::clap::{App,AppSettings,Arg,ArgMatches,SubCommand};
271}
272
273#[doc(hidden)]
274#[macro_export]
275macro_rules! typeparam_sanatize_struct_param {
276 ({$($data:tt)*} {{} {$($long:tt)*} {$($value:tt)*}} -$s:ident $($tail:tt)*) => {
277 typeparam_sanatize_struct_param!{
278 {$($data)*}
279 {{$s} {$($long)*} {$($value)*}}
280 $($tail)*
281 }
282 };
283 ({$($data:tt)*} {{$($short:tt)*} {} {$($value:tt)*}} --$l:ident $($tail:tt)*) => {
284 typeparam_sanatize_struct_param!{
285 {$($data)*}
286 {{$($short)*} {$l} {$($value)*}}
287 $($tail)*
288 }
289 };
290 ({$($data:tt)*} {{$($short:tt)*} {$($long:tt)*} {}} (value: flag) $($tail:tt)*) => {
291 typeparam_sanatize_struct_param!{
292 {$($data)*}
293 {{$($short)*} {$($long)*} {flag}}
294 $($tail)*
295 }
296 };
297 ({$($data:tt)*} {{$($short:tt)*} {$($long:tt)*} {}} (value: default $E:expr) $($tail:tt)*) => {
298 typeparam_sanatize_struct_param!{
299 {$($data)*}
300 {{$($short)*} {$($long)*} {default $E}}
301 $($tail)*
302 }
303 };
304 ({$($data:tt)*} {{$($short:tt)*} {$($long:tt)*} {}} (value: required) $($tail:tt)*) => {
305 typeparam_sanatize_struct_param!{
306 {$($data)*}
307 {{$($short)*} {$($long)*} {required}}
308 $($tail)*
309 }
310 };
311 ({$($data:tt)*} {{$($short:tt)*} {$($long:tt)*} {}} (value: optional) $($tail:tt)*) => {
312 typeparam_sanatize_struct_param!{
313 {$($data)*}
314 {{$($short)*} {$($long)*} {optional}}
315 $($tail)*
316 }
317 };
318 ({$($data:tt)*} {{$($short:tt)*} {$($long:tt)*} {}} (value: option map $E:expr) $($tail:tt)*) => {
319 typeparam_sanatize_struct_param!{
320 {$($data)*}
321 {{$($short)*} {$($long)*} {option map $E}}
322 $($tail)*
323 }
324 };
325 ({$($data:tt)*} {{$($short:tt)*} {$($long:tt)*} {}} (value: map $E:expr) $($tail:tt)*) => {
326 typeparam_sanatize_struct_param!{
327 {$($data)*}
328 {{$($short)*} {$($long)*} {map $E}}
329 $($tail)*
330 }
331 };
332 ({$($data:tt)*} {{$($short:tt)*} {$($long:tt)*} {}}) => {
333 typeparam_sanatize_struct_param_finish!{$($data)* [{$($short)*} {$($long)*} {flag}]}
334 };
335 ({$($data:tt)*} {{$($short:tt)*} {$($long:tt)*} {$($value:tt)*}}) => {
336 typeparam_sanatize_struct_param_finish!{$($data)* [{$($short)*} {$($long)*} {$($value)*}]}
337 };
338}
339
340#[doc(hidden)]
341#[macro_export]
342macro_rules! typeparam_sanatize_struct_param_finish {
343 (
344 [$acc:ident struct $N:ident [$($md:tt)*] {
345 $($tail:tt)*
346 }]
347 [$($prefix:tt)*]
348 [$($suffix:tt)*]
349 $facc:ident $F:ident $n:ident $T:ty
350 {$($params:tt)*}
351 [{$($short:tt)*} {$($long:tt)*} {$($value:tt)*}]
352 ) => {
353 typeparam_sanatize_struct!{
354 $acc struct $N [$($md)*] {
355 $($tail)*
356 } [
357 $($prefix)*
358 params => {$($params)* ($facc $F $n $T {$($short)*} {$($long)*} {$($value)*})}
359 $($suffix)*
360 ]
361 }
362 };
363}
364
365#[doc(hidden)]
366#[macro_export]
367macro_rules! typeparam_sanatize_struct_subcommand {
368 ({$($data:tt)*} {{} {$($params:tt)*}} $param:ident => $en:ident, $($tail:tt)*) => {
369 typeparam_sanatize_struct_subcommand!{{$($data)*} {{} {$($params)* (@subcmd $param ($en) ($crate::EmptySubcommand))}} $($tail)*}
370 };
371 ({$($data:tt)*} {{} {$($params:tt)*}} $param:ident => $en:ident($typ:ty), $($tail:tt)*) => {
372 typeparam_sanatize_struct_subcommand!{{$($data)*} {{} {$($params)* (@subcmd $param ($en($typ)) ($typ))}} $($tail)*}
373 };
374 ({$($data:tt)*} {{} {$($params:tt)*}} $param:ident => $en:ident: $($tail:tt)*) => {
375 typeparam_sanatize_struct_subcommand!{{$($data)*} {{} {$($params)* (@subcmd $param ($en) ($crate::EmptySubcommand))}} : $($tail)*}
376 };
377 ({$($data:tt)*} {{} {$($params:tt)*}} $param:ident => $en:ident($typ:ty): $($tail:tt)*) => {
378 typeparam_sanatize_struct_subcommand!{{$($data)*} {{} {$($params)* (@subcmd $param ($en($typ)) ($typ))}} : $($tail)*}
379 };
380 ({$($data:tt)*} {{} {$($params:tt)*}} $param:ident => $en:ident) => {
381 typeparam_sanatize_struct_subcommand!{{$($data)*} {{} {$($params)* (@subcmd $param ($en) ($crate::EmptySubcommand))}}}
382 };
383 ({$($data:tt)*} {{} {$($params:tt)*}} $param:ident => $en:ident($typ:ty)) => {
384 typeparam_sanatize_struct_subcommand!{{$($data)*} {{} {$($params)* (@subcmd $param ($en($typ)) ($typ))}}}
385 };
386 ({$($data:tt)*} {{} {$($params:tt)*}} : (default = $def:ident) $($tail:tt)*) => {
387 typeparam_sanatize_struct_subcommand!{{$($data)*} {{$def} {$($params)*}} : $($tail)*}
388 };
389 ({$($data:tt)*} {{$($def:tt)*} {$($params:tt)*}}) => {
390 typeparam_sanatize_struct_subcommand!{{$($data)*} {{$($def)*} {$($params)*}} :}
391 };
392 (
393 {
394 [$acc:ident struct $N:ident [$($md:tt)*] {
395 $($tail:tt)*
396 }]
397 [$($prefix:tt)*]
398 [$($suffix:tt)*]
399 $facc:ident $F:ident $T:ident
400 }
401 {{$($def:tt)*} {$($params:tt)*}}
402 :
403 ) => {
404 typeparam_sanatize_struct!{
405 $acc struct $N [$($md)*] {
406 $($tail)*
407 } [
408 $($prefix)*
409 subcommands => {$facc $F $T {$($def)*} {$($params)*}}
410 $($suffix)*
411 ]
412 }
413 };
414}
415
416#[doc(hidden)]
417#[macro_export]
418macro_rules! typeparam_sanatize_struct {
419 ($acc:ident struct $N:ident [$($md:tt)*] { } [$($map:tt)*]) => {
420 typeparam_gen_struct!{$acc struct $N [$($md)*] [$($map)*]}
421 };
422 ($acc:ident struct $N:ident [$($md:tt)*] { , } [$($map:tt)*]) => {
423 typeparam_sanatize_struct!($acc struct $N [$($md)*] { } [$($map)*]);
424 };
425 (
426 $acc:ident struct $N:ident [$($md:tt)*] {
427 $F:ident : $T:ty [$n:ident: $($settings:tt)*],
428 $($tail:tt)*
429 } [
430 subcommands => { $($subcommands:tt)* }
431 params => { $($params:tt)* }
432 fields => { $($fields:tt)* }
433 ]
434 ) => {
435 typeparam_sanatize_struct_param!{
436 {
437 [$acc struct $N [$($md)*] {
438 $($tail)*
439 }]
440 [subcommands => { $($subcommands)* }]
441 [fields => {$($fields)* $F: $T,}]
442 PRIV $F $n $T
443 {$($params)*}
444 }
445 { {} {} {} }
446 $($settings)*
447 }
448 };
449 (
450 $acc:ident struct $N:ident [$($md:tt)*] {
451 pub $F:ident : $T:ty [$n:ident: $($settings:tt)*],
452 $($tail:tt)*
453 } [
454 subcommands => { $($subcommands:tt)* }
455 params => { $($params:tt)* }
456 fields => { $($fields:tt)* }
457 ]
458 ) => {
459 typeparam_sanatize_struct_param!{
460 {
461 [$acc struct $N [$($md)*] {
462 $($tail)*
463 }]
464 [subcommands => { $($subcommands)* }]
465 [fields => {$($fields)* pub $F: $T,}]
466 PUB $F $n $T
467 {$($params)*}
468 }
469 { {} {} {} }
470 $($settings)*
471 }
472 };
473 (
474 $acc:ident struct $N:ident [$($md:tt)*] {
475 $F:ident : @SUBCOMMANDS<$T:ident> [$($settings:tt)*],
476 $($tail:tt)*
477 } [
478 subcommands => { }
479 params => { $($params:tt)* }
480 fields => { $($fields:tt)* }
481 ]
482 ) => {
483 typeparam_sanatize_struct_subcommand!{
484 {
485 [$acc struct $N [$($md)*] {
486 $($tail)*
487 }]
488 []
489 [params => { $($params)* } fields => {$($fields)* $F: $T,}]
490 PRIV $F $T
491 }
492 {{} {}}
493 $($settings)*
494 }
495 };
496 (
497 $acc:ident struct $N:ident [$($md:tt)*] {
498 $F:ident : @SUBCOMMANDS<$T:ident> [$($settings:tt)*],
499 $($tail:tt)*
500 } [
501 subcommands => { }
502 params => { $($params:tt)* }
503 fields => { $($fields:tt)* }
504 ]
505 ) => {
506 typeparam_sanatize_struct_subcommand!{
507 {
508 [$acc struct $N [$($md)*] {
509 $($tail)*
510 }]
511 []
512 [params => { $($params)* } fields => {$($fields)* pub $F: $T,}]
513 PUB $F $T
514 }
515 {{} {}}
516 $($settings)*
517 }
518 };
519}
520
521#[doc(hidden)]
522#[macro_export]
523macro_rules! typeparam_gen_enum {
524 () => {};
525 (PRIV $F:ident $T:ident { $def:ident } {$((@subcmd $param:ident ($($el:tt)*) ($typ:ty)))*}) => {
526 #[derive(Debug)]
527 enum $T {
528 $def,
529 $($($el)*),*
530 }
531 };
532 (PRIV $F:ident $T:ident { } {$((@subcmd $param:ident ($($el:tt)*) ($typ:ty)))*}) => {
533 #[derive(Debug)]
534 enum $T {
535 $($($el)*),*
536 }
537 };
538 (PUB $F:ident $T:ident { $def:ident } {$((@subcmd $param:ident ($($el:tt)*) ($typ:ty)))*}) => {
539 #[derive(Debug)]
540 pub enum $T {
541 $def,
542 $($($el)*),*
543 }
544 };
545 (PUB $F:ident $T:ident { } {$((@subcmd $param:ident ($($el:tt)*) ($typ:ty)))*}) => {
546 #[derive(Debug)]
547 pub $facc enum $T {
548 $($($el)*),*
549 }
550 };
551}
552
553#[doc(hidden)]
554#[macro_export]
555macro_rules! typeparam_gen_struct_hlp {
556 (PRIV struct $N:ident {$($fields:tt)*}) => {
557 struct $N {
558 $($fields)*
559 }
560 };
561 (PUB struct $N:ident {$($fields:tt)*}) => {
562 pub struct $N {
563 $($fields)*
564 }
565 };
566}
567
568#[doc(hidden)]
569#[macro_export]
570macro_rules! typeparam_gen_commands {
571 (($app:expr)) => {$app};
572 (($app:expr) $facc:ident $F:ident $T:ident { $($def:tt)+ } { }) => {$app};
573 (($app:expr) $facc:ident $F:ident $T:ident { } { }) => {
574 $app.setting($crate::clap_export::AppSettings::SubcommandRequired)
575 };
576 (($app:expr) $facc:ident $F:ident $T:ident { $($def:tt)* } {(@subcmd $subcmd:ident ($($fld:tt)*) ($t:ty)) $($tail:tt)*}) => {{
577 fn subcommand<T : $crate::SubCommand>(name: &'static str) -> $crate::clap_export::App<'static, 'static> {
578 T::subcommand(name)
579 }
580 let app = $app.subcommand(subcommand::<$t>(stringify!($subcmd)));
581 typeparam_gen_commands!((app) $facc $F $T { $($def)* } {$($tail)*})
582 }}
583}
584
585#[doc(hidden)]
586#[macro_export]
587macro_rules! typeparam_gen_params_flg {
588 (($arg:expr) {$short:ident} {$($long:tt)*}) => {{
589 let arg = $arg.short(stringify!($short));
590 typeparam_gen_params_flg!((arg) {} {$($long)*})
591 }};
592 (($arg:expr) {} {$long:ident}) => {{
593 let arg = $arg.long(stringify!($long));
594 typeparam_gen_params_flg!((arg) {} {})
595 }};
596 (($arg:expr) {} {}) => {
597 $arg
598 };
599}
600
601#[doc(hidden)]
602#[macro_export]
603macro_rules! typeparam_gen_params {
604 (($app:expr) ($facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {flag}) $($tail:tt)*) => {{
605 let arg = typeparam_gen_params_flg!((::clap::Arg::with_name(stringify!($n))) {$($short)*} {$($long)*});
606 typeparam_gen_params!(($app.arg(arg.takes_value(false).required(false))) $($tail)*)
607 }};
608 (($app:expr) ($facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {default $E:expr}) $($tail:tt)*) => {{
609 let arg = typeparam_gen_params_flg!((::clap::Arg::with_name(stringify!($n))) {$($short)*} {$($long)*});
610 typeparam_gen_params!(($app.arg(arg.takes_value(true).required(false))) $($tail)*)
611 }};
612 (($app:expr) ($facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {optional}) $($tail:tt)*) => {{
613 let arg = typeparam_gen_params_flg!((::clap::Arg::with_name(stringify!($n))) {$($short)*} {$($long)*});
614 typeparam_gen_params!(($app.arg(arg.takes_value(true).required(false))) $($tail)*)
615 }};
616 (($app:expr) ($facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {required}) $($tail:tt)*) => {{
617 let arg = typeparam_gen_params_flg!((::clap::Arg::with_name(stringify!($n))) {$($short)*} {$($long)*});
618 typeparam_gen_params!(($app.arg(arg.takes_value(true).required(true))) $($tail)*)
619 }};
620 (($app:expr) ($facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {option map $E:expr}) $($tail:tt)*) => {{
621 let arg = typeparam_gen_params_flg!((::clap::Arg::with_name(stringify!($n))) {$($short)*} {$($long)*});
622 typeparam_gen_params!(($app.arg(arg.takes_value(true).required(false))) $($tail)*)
623 }};
624 (($app:expr) ($facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {map $E:expr}) $($tail:tt)*) => {{
625 let arg = typeparam_gen_params_flg!((::clap::Arg::with_name(stringify!($n))) {$($short)*} {$($long)*});
626 typeparam_gen_params!(($app.arg(arg.takes_value(true).required(true))) $($tail)*)
627 }};
628 (($app:expr)) => {$app};
629}
630
631#[derive(Copy, Clone, Debug)]
632#[doc(hidden)]
633pub struct Res<T, E>(pub Result<T, E>);
634
635impl<T, E> From<T> for Res<T, E> {
636 fn from(t: T) -> Res<T, E> {
637 Res(Ok(t))
638 }
639}
640
641impl<T, E2, E : Into<E2>> From<Result<T, E>> for Res<T, E2> {
642 fn from(r: Result<T, E>) -> Res<T, E2> {
643 match r {
644 Ok(t) => Res(Ok(t)),
645 Err(e) => Res(Err(E::into(e)))
646 }
647 }
648}
649
650#[doc(hidden)]
651#[macro_export]
652macro_rules! typeparam_gen_new_param_get {
653 (($match:expr) ($err:ty) $facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {flag}) => {
654 $match.is_present(stringify!($n))
655 };
656 (($match:expr) ($err:ty) $facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {default $E:expr}) => {
657 $match.value_of(stringify!($n)).map_or_else(|| Ok($E), |val| val.parse::<$T>(),)?
658 };
659 (($match:expr) ($err:ty) $facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {required}) => {
660 $match.value_of(stringify!($n)).map(|val| val.parse::<$T>()).unwrap()?
661 };
662 (($match:expr) ($err:ty) $facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {optional}) => {{
663 use std::str::FromStr;
664 trait OptionParse where Self : Sized {
665 type Error;
666 fn parse(string: Option<&str>) -> Result<Self, Self::Error>;
667 }
668 impl<T : FromStr> OptionParse for Option<T> {
669 type Error = T::Err;
670 fn parse(string: Option<&str>) -> Result<Self, Self::Error> {
671 match string {
672 Some(ref val) => Ok(Some(val.parse::<T>()?)),
673 None => Ok(None)
674 }
675 }
676 }
677 fn parse<T : OptionParse>(val: Option<&str>) -> Result<T, T::Error> {
678 T::parse(val)
679 }
680 parse::<$T>($match.value_of(stringify!($n)))?
681 }};
682 (($match:expr) ($err:ty) $facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {option map $E:expr}) => {{
683 fn coerce<R : Into<$crate::Res<$T, $err>>, F : FnOnce(Option<&str>) -> R>(f: F, val: Option<&str>) -> Result<$T, $err> {
684 R::into(f(val)).0
685 }
686 coerce($E, $match.value_of(stringify!($n)))?
687 }};
688 (($match:expr) ($err:ty) $facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {map $E:expr}) => {{
689 fn coerce<R : Into<$crate::Res<$T, $err>>, F : FnOnce(&str) -> R>(f: F, val: &str) -> Result<$T, $err> {
690 R::into(f(val)).0
691 }
692 coerce($E, $match.value_of(stringify!($n)).unwrap())?
693 }};
694}
695
696#[doc(hidden)]
697#[macro_export]
698macro_rules! typeparam_gen_new_command_get {
699 (($match:expr) $T:ident { $($def:tt)* } { (@subcmd $subcmd:ident ($fld:ident($typ:ty)) ( $typ2:ty)) $($tail:tt)* }) => {{
700 let mch = $match;
701 if let Some(submatch) = mch.subcommand_matches(stringify!($subcmd)) {
702 fn gen_subcmd<T : $crate::SubCommand>(am: &$crate::clap_export::ArgMatches) -> Result<T, T::Error> {
703 T::new(am)
704 }
705 $T::$fld(gen_subcmd::<$typ>(submatch)?)
706 } else {
707 typeparam_gen_new_command_get!((mch) $T { $($def)* } { $($tail)* })
708 }
709 }};
710 (($match:expr) $T:ident { $($def:tt)* } { (@subcmd $subcmd:ident ($fld:ident) ( $typ2:ty)) $($tail:tt)* }) => {{
711 let mch = $match;
712 if mch.subcommand_name() == Some(stringify!($subcmd)) {
713 $T::$fld
714 } else {
715 typeparam_gen_new_command_get!((mch) $T { $($def)* } { $($tail)* })
716 }
717 }};
718 (($match:expr) $T:ident { $def:ident } { }) => {
719 $T::$def
720 };
721 (($match:expr) $T:ident { } { }) => {
722 panic!("No command given")
723 };
724}
725
726#[doc(hidden)]
727#[macro_export]
728macro_rules! typeparam_gen_new {
729 (($match:expr) $N:ident $err:ty {$($gen:tt)*} [subcommands => {$facc:ident $F:ident $T:ident { $($def:tt)* } { $($subcmd:tt)*} } params => {$($params:tt)*}]) => {{
730 let mch = $match;
731 let val: $T = typeparam_gen_new_command_get!((mch) $T { $($def)* } { $($subcmd)*});
732 typeparam_gen_new!((mch) $N $err {$($gen)* $F: val,} [params => { $($params)* }])
733 }};
734 (($match:expr) $N:ident $err:ty {$($gen:tt)*} [subcommands => {} params => {$($params:tt)*}]) => {
735 typeparam_gen_new!(($match) $N $err {$($gen)*} [params => { $($params)* }])
736 };
737 (($match:expr) $N:ident $err:ty {$($gen:tt)*} [params => { ($facc:ident $F:ident $n:ident $T:ty {$($short:tt)*} {$($long:tt)*} {$($value:tt)*}) $($params:tt)*}]) => {{
738 let mch = $match;
739 let val: $T = typeparam_gen_new_param_get!((mch) ($err) $facc $F $n $T {$($short)*} {$($long)*} {$($value)*});
740 typeparam_gen_new!((mch) $N $err {$($gen)* $F: val,} [params => { $($params)* }])
741 }};
742 (($match:expr) $N:ident $err:ty {$($gen:tt)*} [params => {}]) => {{
743 Ok($N {
744 $($gen)*
745 })
746 }}
747}
748
749#[doc(hidden)]
750#[macro_export]
751macro_rules! typeparam_gen_impl {
752 ($acc:ident struct $N:ident [@app $app:ident $err:ty] [subcommands => { $($subcmd:tt)* } params => { $($params:tt)* }]) => {
753 impl $crate::Command for $N {
754 type Error = $err;
755 fn command() -> $crate::clap_export::App<'static, 'static> {
756 let app = $crate::clap_export::App::new(stringify!($app));
757 let app = app.settings(&[
758 $crate::clap_export::AppSettings::StrictUtf8
759 ]);
760 let app = typeparam_gen_commands!((app) $($subcmd)*);
761 let app = typeparam_gen_params!((app) $($params)*);
762 app
763 }
764 fn new(matches: &$crate::clap_export::ArgMatches) -> Result<Self, Self::Error> {
765 typeparam_gen_new!((&matches) $N $err {} [subcommands => { $($subcmd)* } params => { $($params) * }])
766 }
767 }
768 };
769 ($acc:ident struct $N:ident [@subcommand $err:ty] [subcommands => { $($subcmd:tt)* } params => { $($params:tt)* }]) => {
770 impl $crate::SubCommand for $N {
771 type Error = $err;
772 fn subcommand(name: &'static str) -> $crate::clap_export::App<'static, 'static> {
773 let app = $crate::clap_export::SubCommand::with_name(name);
774 let app = typeparam_gen_commands!((app) $($subcmd)*);
775 let app = typeparam_gen_params!((app) $($params)*);
776 app
777 }
778 fn new(_am: &$crate::clap_export::ArgMatches) -> Result<Self, Self::Error> {
779 typeparam_gen_new!((&_am) $N $err {} [subcommands => { $($subcmd)* } params => { $($params) * }])
780 }
781 }
782 };
783}
784
785#[doc(hidden)]
786#[macro_export]
787macro_rules! typeparam_gen_struct {
788 ($acc:ident struct $N:ident [$($md:tt)*] [subcommands => { $($subcmd:tt)* } params => { $($params:tt)* } fields => { $($fields:tt)* }]) => {
789 typeparam_gen_enum!($($subcmd)*);
790 typeparam_gen_struct_hlp!($acc struct $N { $($fields)* });
791 typeparam_gen_impl!($acc struct $N [$($md)*] [subcommands => { $($subcmd)* } params => { $($params)* }]);
792 };
793}
794
795#[macro_export]
796macro_rules! typeparam {
797 (struct $N:ident [$($md:tt)*] { $($struct:tt)+ } $($tail:tt)*) => {
798 typeparam_sanatize_struct!{
799 PRIV struct $N [$($md)*] {
800 $($struct)*,
801 } [
802 subcommands => { }
803 params => { }
804 fields => { }
805 ]
806 }
807 typeparam!{$($tail)*}
808 };
809 (struct $N:ident [$($md:tt)*]; $($tail:tt)*) => {
810 typeparam_sanatize_struct!{
811 PRIV struct $N [$($md)*] { } [
812 subcommands => { }
813 params => { }
814 fields => { }
815 ]
816 }
817 typeparam!{$($tail)*}
818 };
819 () => {};
820}
821
822#[derive(Debug)]
823pub enum Error<T> {
824 Parse(clap::Error),
825 Command(T)
826}
827
828pub trait Command where Self : Sized {
830 type Error;
832 fn parse<I : IntoIterator<Item = T>, T : Into<std::ffi::OsString> + Clone>(itr: I) -> Result<Self, Error<Self::Error>> {
839 Self::new(&Self::command().get_matches_from_safe(itr).map_err(|e| Error::Parse(e))?).map_err(|e| Error::Command(e))
840 }
841 fn parse_args() -> Result<Self, Error<Self::Error>> {
847 Self::parse(std::env::args())
848 }
849 fn parse_any<I : IntoIterator<Item = T>, T : Into<std::ffi::OsString> + Clone, E : From<Self::Error> + From<clap::Error>>(itr: I) -> Result<Self, E> {
856 match Self::parse(itr) {
857 Ok(res) => Ok(res),
858 Err(Error::Parse(e)) => Err(E::from(e)),
859 Err(Error::Command(e)) => Err(E::from(e))
860 }
861 }
862 fn parse_any_args<E : From<Self::Error> + From<clap::Error>>() -> Result<Self, E> {
868 Self::parse_any(std::env::args())
869 }
870 fn parse_or_exit<I : IntoIterator<Item = T>, T : Into<std::ffi::OsString> + Clone>(itr: I) -> Self where Self::Error : std::fmt::Display {
875 let mut app = Self::command();
876 let res = app.get_matches_from_safe_borrow(itr).map_err(|e| Error::Parse(e)).and_then(|mch| {
877 Self::new(&mch).map_err(|e| Error::Command(e))
878 });
879 match res {
880 Ok(res) => res,
881 Err(Error::Parse(e)) => e.exit(),
882 Err(Error::Command(e)) => {
883 use std::io::Write;
884 let stderr = std::io::stderr();
885 writeln!(&mut stderr.lock(), "{:}", e).unwrap();
886 std::process::exit(1)
887 }
888 }
889 }
890 fn parse_args_or_exit() -> Self where Self::Error : std::fmt::Display {
895 Self::parse_or_exit(std::env::args())
896 }
897 fn command() -> clap::App<'static, 'static>;
899 fn new(mch: &clap::ArgMatches) -> Result<Self, Self::Error>;
901}
902
903#[doc(hidden)]
904pub trait SubCommand where Self : Sized {
905 type Error;
906 fn subcommand(name: &'static str) -> clap::App<'static, 'static>;
907 fn new(mch: &clap::ArgMatches) -> Result<Self, Self::Error>;
908}
909
910#[derive(Copy, Clone, Debug)]
911#[doc(hidden)]
912pub enum EmptySubcommand {}
913
914impl SubCommand for EmptySubcommand {
915 type Error = std::string::ParseError;
916 fn subcommand(name: &'static str) -> clap::App<'static, 'static> {
917 clap::SubCommand::with_name(name)
918 }
919 fn new(_: &clap::ArgMatches) -> Result<Self, Self::Error> {
920 panic!("EmptySubcommand::new should never be called");
921 }
922}
923