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
//! A macro to generate SGR (Set Graphic Rendition) control sequences for [ECMA-48] compatible terminals.
//!
//! # Examples
//!
//! The general syntax is:
//! ```text
//! [visibity] <name> = <attribute> [| attributes...];
//! ```
//!
//! You can specify multiple constants at once,
//! as well as add attributes or doc comments to each:
//!
//! ```rust
//! sgr_const::sgr_const! {
//!     /// Error styling. Should be flashy.
//!     STYLE_ERROR = Bold | BlackFg | RedBg;
//!     STYLE_WARN  = Bold | YellowFg;
//!     STYLE_INFO  = Bold | CyanFg;
//!     STYLE_DEBUG = MagentaFg;
//!     #[allow(unused)]
//!     STYLE_TRACE = GreenFg;
//!     STYLE_NONE  = Reset;
//! }
//!
//! # fn main() {
//! assert_eq!(STYLE_ERROR, "\x1b[1;30;41m");
//! assert_eq!(STYLE_WARN,  "\x1b[1;33m");
//! assert_eq!(STYLE_INFO,  "\x1b[1;36m");
//! assert_eq!(STYLE_DEBUG, "\x1b[35m");
//! assert_eq!(STYLE_TRACE, "\x1b[32m");
//! assert_eq!(STYLE_NONE,  "\x1b[0m");
//! # }
//! ```
//!
//! [ECMA-48]: https://www.ecma-international.org/publications/standards/Ecma-048.htm

#![no_std]

#[macro_export]
macro_rules! sgr_const {
    // SGR attribute name to parameter value lookup.
    (@sgr Reset)       => {  0 };

    (@sgr Bold)        => {  1 };
    (@sgr Dim)         => {  2 };
    (@sgr Italics)     => {  3 };
    (@sgr Underline)   => {  4 };
    (@sgr Blink)       => {  5 };
    (@sgr Negative)    => {  7 };

    (@sgr NoBold)      => { 22 };
    (@sgr NoItalics)   => { 23 };
    (@sgr NoUnderline) => { 24 };
    (@sgr NoBlink)     => { 25 };
    (@sgr NoNegative)  => { 27 };

    (@sgr BlackFg)     => { 30 };
    (@sgr RedFg)       => { 31 };
    (@sgr GreenFg)     => { 32 };
    (@sgr YellowFg)    => { 33 };
    (@sgr BlueFg)      => { 34 };
    (@sgr MagentaFg)   => { 35 };
    (@sgr CyanFg)      => { 36 };
    (@sgr WhiteFg)     => { 37 };

    (@sgr ResetFg)     => { 39 };

    (@sgr BlackBg)     => { 40 };
    (@sgr RedBg)       => { 41 };
    (@sgr GreenBg)     => { 42 };
    (@sgr YellowBg)    => { 43 };
    (@sgr BlueBg)      => { 44 };
    (@sgr MegantaBg)   => { 45 };
    (@sgr CyanBg)      => { 46 };
    (@sgr WhiteBg)     => { 47 };

    (@sgr ResetBg)     => { 49 };

    // Take unseperated list of expressions, throw them into `concat!`.
    (@collect $($strs:expr)*) => { concat!("\x1b[", $($strs),*, "m") };

    // Entry.
    {
        $(
            $(#[$($attr:meta)+])*
            $vis:vis $name:ident = $($sgr:ident)|+;
        )*
    } => {
        $(
            $(#[$($attr)+])*
            $vis const $name: &'static str = $crate::sgr_const!(@collect $($crate::sgr_const!(@sgr $sgr))";"+);
        )*
    };
}