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
use crate::font::Font;
use std::fmt::Display;

/// color_string 快速生成彩色字符串
/// # Examples
/// ```
/// use color_string::cs;
/// use color_string::Font::*;
/// let s = cs!(Red, Bold; "{:X}", u32::MAX);
/// println!("{s}");
/// assert_eq!("\u{1b}[0;31;1mFFFFFFFF\u{1b}[0m", s);
///
/// let s = cs!{
///     Red => 123456, "\n";
///     Green,Bold => "hello world";
/// };
/// println!("{s}");
/// assert_eq!("\u{1b}[0;31m123456\n\u{1b}[0;32;1mhello world\u{1b}[0m", s);
/// ```
#[macro_export]
macro_rules! cs {
     ($($arg:tt)*) => {{
        let mut s = String::new();
        $crate::wcs!(&mut s, $($arg)*);
        s
    }};
}

/// write_color_string 写入彩色字符串
/// # Examples
/// ```
/// use color_string::wcs;
/// use color_string::Font::*;
/// let mut s = String::new();
/// wcs!(&mut s, Red, Bold; "{:X}", u32::MAX);
/// println!("{s}");
/// assert_eq!("\u{1b}[0;31;1mFFFFFFFF\u{1b}[0m", s);
///
/// let mut s = String::new();
/// wcs!{
///     &mut s,
///     Red => 123456, "\n";
///     Green,Bold => "hello world";
/// }
/// println!("{s}");
/// assert_eq!("\u{1b}[0;31m123456\n\u{1b}[0;32;1mhello world\u{1b}[0m", s);
/// ```
#[macro_export]
macro_rules! wcs {
     ($buf:expr, $($font:expr),* ; $($arg:tt)*) => {{
        use std::fmt::Write;
        $crate::wf!($buf, $($font),*);
        write!($buf, $($arg)*).unwrap();
        $buf.push_str("\x1b[0m");
    }};

    ($buf:expr, $($($font:expr),* => $($s:expr),* );* $(;)?) => {{
        use std::fmt::Write;
        $(
            $crate::wf!($buf, $($font),*);
            $(write!($buf, "{}", $s).unwrap();)*
        )*
        $buf.push_str("\x1b[0m");
    }};
}

macro_rules! colored_trait {
    ($($method:ident => $font:expr),*) => {
        pub trait Colored:Display {
            $(
                fn $method(&self) -> String {
                    $crate::cs!($font => self)
                }
            )*

            fn color(&self, r:u8, g:u8, b:u8) -> String {
                $crate::cs!($crate::color::Font::Color(r,g,b) => self)
            }

            fn bg_color(&self, r:u8, g:u8, b:u8) -> String {
                $crate::cs!($crate::color::Font::BgColor(r,g,b) => self)
            }

            /// # Examples
            /// ```rust,ignore
            /// println!("{}","test".fonts("\x1b[1;31m"));
            /// println!("{}","test".fonts(fonts!(Font::Bold,Font::Red)));
            /// ```
            #[allow(clippy::ptr_arg)]
            fn fonts(&self, mut fonts:String) -> String {
                use std::fmt::Write;
                write!(&mut fonts, "{}\x1b[0m", self).unwrap();
                fonts
            }
        }
    };
}

/// 为所有实现 Display 的数据实现 Colored
impl<T> Colored for T where T: Display + ?Sized {}
colored_trait! {
    bold => Font::Bold,
    underline => Font::Underline,
    italic => Font::Italic,
    reverse => Font::Reverse,
    delete => Font::Delete,
    black => Font::Black,
    red => Font::Red,
    green => Font::Green,
    yellow => Font::Yellow,
    blue => Font::Blue,
    purple => Font::Purple,
    cyan => Font::Cyan,
    grey => Font::Grey,
    bg_black => Font::BgBlack,
    bg_red => Font::BgRed,
    bg_green => Font::BgGreen,
    bg_yellow => Font::BgYellow,
    bg_blue => Font::BgBlue,
    bg_purple => Font::BgPurple,
    bg_cyan => Font::Cyan,
    bg_grey => Font::BgGrey
}