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
114
115
116
117
118
119
120
121
122
123
124
125
126
/// Display an error in the same style as cargo or rustc:
/// <code style="display: block; padding: 0.25em; margin: 0.5em 0;"><span style="color: red; font-weight: bold">error\[E1234\]</span><span style="color: grey; font-weight: bold">:</span> an error message
/// <span style="color: darkcyan; font-weight: bold"> --&gt; </span>examples/macros.rs:2:3</code>
///
/// # Example
///
/// ```rust
/// # use mmrbi::*;
/// error!(at: "examples/macros.rs", line: 2, col: 3, code: "E1234", "an {} message", "error");
/// error!("an {} message", "error"); // all params optional
/// ```
#[macro_export] macro_rules! error { ($($tt:tt)*) => { $crate::_logln!($crate::_log_impl::Severity::Error,    $($tt)*) }; }

/// Display a warning in the same style as cargo or rustc:
/// <code style="display: block; padding: 0.25em; margin: 0.5em 0;"><span style="color: olive; font-weight: bold">warning\[E1234\]</span><span style="color: grey; font-weight: bold">:</span> a warning message
/// <span style="color: darkcyan; font-weight: bold"> --&gt; </span>examples/macros.rs:2:3</code>
///
/// # Example
///
/// ```rust
/// # use mmrbi::*;
/// warning!(at: "examples/macros.rs", line: 2, col: 3, code: "E1234", "a {} message", "warning");
/// warning!("a {} message", "warning"); // all params optional
/// ```
#[macro_export] macro_rules! warning { ($($tt:tt)*) => { $crate::_logln!($crate::_log_impl::Severity::Warning,  $($tt)*) }; }

/// Display informational messages in the same style as cargo or rustc:
/// <code style="display: block; padding: 0.25em; margin: 0.5em 0;"><span style="color: darkcyan; font-weight: bold">info\[E1234\]</span><span style="color: grey; font-weight: bold">:</span> an informational message
/// <span style="color: darkcyan; font-weight: bold"> --&gt; </span>examples/macros.rs:2:3</code>
///
/// # Example
///
/// ```rust
/// # use mmrbi::*;
/// info!(at: "examples/macros.rs", line: 2, col: 3, code: "E1234", "a {} message", "informational");
/// info!("an {} message", "informational"); // all params optional
/// ```
#[macro_export] macro_rules! info { ($($tt:tt)*) => { $crate::_logln!($crate::_log_impl::Severity::Info,     $($tt)*) }; }

/// Display a status/progress lines in the same style as cargo or rustc:
/// <code style="display: block; padding: 0.25em; margin: 0.5em 0;"><span style="color: green; font-weight: bold">&nbsp;Documenting</span> mmrbi v0.0.0 (C:\local\mmrbi)
/// <span style="color: green; font-weight: bold">&nbsp;&nbsp;&nbsp;&nbsp;Finished</span> dev \[debuginfo\] target(s) in 0.91s</code>
///
/// # Example
///
/// ```rust
/// # use mmrbi::*;
/// status!("Documenting", "{} {} ({})", "mmrbi", "v0.0.0", r"C:\local\mmrbi");
/// status!("Finished", "{} [{}] target(s) in {}s", "dev", "debuginfo", "0.91");
/// ```
#[macro_export] macro_rules! status {
    ( $verb:expr, $fmt:literal $($tt:tt)* ) => {{
        use std::io::Write;
        let stderr = std::io::stderr();
        let mut stderr = stderr.lock();
        let _ = write!  (&mut stderr, "\u{001B}[32;1m{: >12}\u{001B}[0m ", $verb);
        let _ = writeln!(&mut stderr, $fmt $($tt)*);
    }};
}

/// Display an error in the same style as cargo or rustc, then `exit(1)`:
/// <code style="display: block; padding: 0.25em; margin: 0.5em 0;"><span style="color: red; font-weight: bold">error\[E1234\]</span><span style="color: grey; font-weight: bold">:</span> an error message
/// <span style="color: darkcyan; font-weight: bold"> --&gt; </span>examples/macros.rs:2:3</code>
///
/// # Example
///
/// ```rust,no_run
/// # use mmrbi::*;
/// fatal!(at: "examples/macros.rs", line: 2, col: 3, code: "E1234", "an {} message", "error");
/// fatal!("an {} message", "error"); // all params optional
/// ```
#[macro_export] macro_rules! fatal {
    ( $($tt:tt)* ) => {{
        $crate::error!($($tt)*);
        ::std::process::exit(1);
    }};
}

/// Display a header section:
/// <code style="display: block; color: black; background: #14CE14; padding: 0.25em; margin: 0.5em 0;">  a header  </code>
///
/// # Example
///
/// ```rust,no_run
/// # use mmrbi::*;
/// header!("  a header  ");
/// ```
#[macro_export] macro_rules! header {
    ( $fmt:literal $($tt:tt)* ) => {{
        use std::io::Write;
        let stderr = std::io::stderr();
        let mut stderr = stderr.lock();
        let _ = writeln!(&mut stderr, concat!("\u{001B}[30;102m", $fmt, "\u{001B}[0m") $($tt)*);
    }};
}



#[doc(hidden)] #[macro_export] macro_rules! _logln {
    ( $sev:expr, $($tt:tt)* ) => {{
        #[allow(unused_mut)]
        let mut ctx = $crate::_log_impl::Context {
            severity:   $sev,
            code:       "",
            at:         None,
            line:       0,
            col:        0,
        };
        $crate::_logln_inner!( ctx, $($tt)* );
    }};
}

#[doc(hidden)] #[macro_export] macro_rules! _logln_inner {
    ( $ctx:expr, code:   $code:expr, $($tt:tt)* ) => { let code = format!("[{}]", $code); $ctx.code = code.as_str(); $crate::_logln_inner!($ctx, $($tt)*); };
    ( $ctx:expr, at:     $at:expr,   $($tt:tt)* ) => { let at = $at; $ctx.at = Some(at.as_ref()); $crate::_logln_inner!($ctx, $($tt)*); };
    ( $ctx:expr, path:   $at:expr,   $($tt:tt)* ) => { let at = $at; $ctx.at = Some(at.as_ref()); $crate::_logln_inner!($ctx, $($tt)*); };
    ( $ctx:expr, line:   $line:expr, $($tt:tt)* ) => { $ctx.line = $line; $crate::_logln_inner!($ctx, $($tt)*); };
    ( $ctx:expr, col:    $col:expr,  $($tt:tt)* ) => { $ctx.col = $col; $crate::_logln_inner!($ctx, $($tt)*); };
    ( $ctx:expr, column: $col:expr,  $($tt:tt)* ) => { $ctx.col = $col; $crate::_logln_inner!($ctx, $($tt)*); };

    // Terminal rule
    ( $ctx:expr, $fmt:literal $($tt:tt)* ) => {
        use ::std::io::Write;
        $crate::_log_impl::write($ctx, |stderr| writeln!(stderr, $fmt $($tt)*));
    };
}