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
/// Quickly get a good `main` function
///
/// Inside the block, you can write code using `?`. An `Ok(())` will
/// automatically be appended. The macro will also set up logging (using
/// `env_logger`) automatically.
///
/// # Parameters
///
/// You can optionally call this macro with a closure-like syntax to get some
/// default bindings:
///
/// - `main!(|args: Cli| { ... })`: Automatically parses command line flags into
///   a struct `Cli` and binds it to `args`. (Basically, it prepends
///   `let args = Cli::from_args();`).
/// - `main!(|args: Cli, log_level: verbosity| { ... })`: The log level will
///   depend on the integer value of the `verbosity` field of `args` (error = 0,
///   warn = 1, info = 2, debug = 3, trace = ≥4). The field's type should be
///   set to `parse(from_occurrences)` in the `#[structopt(…)]` attribute,
///   so structopt will automatically give you its number of occurances..
///
/// # Examples
///
/// ```rust,ignore
/// #[macro_use] extern crate quicli;
/// use quicli::prelude::*;
///
/// main!({
///     let x = read_file(".gitignore")?;
///     println!("{}", x);
/// });
/// ```
#[macro_export]
macro_rules! main {
    (|$args:ident: $cli:ty, log_level: $verbosity:ident| $body:expr) => {
        fn main() {
            fn run() -> $crate::prelude::Result<()> {
                let $args = <$cli>::from_args();
                let log_level = match $args.$verbosity {
                    0 => $crate::prelude::LogLevel::Error,
                    1 => $crate::prelude::LogLevel::Warn,
                    2 => $crate::prelude::LogLevel::Info,
                    3 => $crate::prelude::LogLevel::Debug,
                    _ => $crate::prelude::LogLevel::Trace,
                }.to_level_filter();

                $crate::prelude::LoggerBuiler::new()
                    .filter(Some(env!("CARGO_PKG_NAME")), log_level)
                    .filter(None, $crate::prelude::LogLevel::Warn.to_level_filter())
                    .try_init()?;

                $body

                Ok(())
            }

            match run() {
                Ok(_) => {}
                Err(e) => {
                    eprintln!("{}", e);
                    ::std::process::exit(1);
                }
            }
        }
    };

    (|$args:ident: $cli:ty| $body:expr) => {
        fn main() {
            fn run() -> $crate::prelude::Result<()> {
                let $args = <$cli>::from_args();
                $crate::prelude::LoggerBuiler::new()
                    .filter(Some(env!("CARGO_PKG_NAME")), $crate::prelude::LogLevel::Error.to_level_filter())
                    .filter(None, $crate::prelude::LogLevel::Warn.to_level_filter())
                    .try_init()?;

                $body

                Ok(())
            }

            match run() {
                Ok(_) => {}
                Err(e) => {
                    eprintln!("{}", e);
                    ::std::process::exit(1);
                }
            }
        }
    };

    (|| $body:expr) => { main!($body); };

    ($body:expr) => {
        fn main() {
            fn run() -> $crate::prelude::Result<()> {
                $crate::prelude::LoggerBuiler::new()
                    .filter(Some(env!("CARGO_PKG_NAME")), $crate::prelude::LogLevel::Error.to_level_filter())
                    .filter(None, $crate::prelude::LogLevel::Warn.to_level_filter())
                    .try_init()?;

                $body
                Ok(())
            }

            match run() {
                Ok(_) => {}
                Err(e) => {
                    eprintln!("{}", e);
                    ::std::process::exit(1);
                }
            }
        }
    };
}