1use std::borrow::Cow;
2use std::fmt::{Display, Formatter};
3
4#[derive(Debug, Clone, PartialEq, Eq, Hash)]
5pub enum Font {
6 Reset,
8 Bold,
10 RBold,
11 Underline,
13 RUnderline,
14 Italic,
16 RItalic,
17 Reverse,
19 RReverse,
20 Delete,
22 RDelete,
23 Black,
25 RBlack,
26 Red,
28 RRed,
29 Green,
31 RGreen,
32 Yellow,
34 RYellow,
35 Blue,
37 RBlue,
38 Purple,
40 RPurple,
41 Cyan,
43 RCyan,
44 Grey,
46 RGrey,
47 BgBlack,
49 RBgBlack,
50 BgRed,
52 RBgRed,
53 BgGreen,
55 RBgGreen,
56 BgYellow,
58 RBgYellow,
59 BgBlue,
61 RBgBlue,
62 BgPurple,
64 RBgPurple,
65 BgCyan,
67 RBgCyan,
68 BgGrey,
70 RBgGrey,
71 Color(u8, u8, u8),
73 RColor(u8, u8, u8),
74 BgColor(u8, u8, u8),
76 RBgColor(u8, u8, u8),
77}
78
79impl Font {
80 pub fn as_str(&self) -> Cow<'static, str> {
81 match self {
82 Font::Reset => Cow::Borrowed("0"),
83 Font::Bold => Cow::Borrowed("1"),
84 Font::RBold => Cow::Borrowed("0;1"),
85 Font::Italic => Cow::Borrowed("3"),
86 Font::RItalic => Cow::Borrowed("0;3"),
87 Font::Underline => Cow::Borrowed("4"),
88 Font::RUnderline => Cow::Borrowed("0;4"),
89 Font::Reverse => Cow::Borrowed("7"),
90 Font::RReverse => Cow::Borrowed("0;7"),
91 Font::Delete => Cow::Borrowed("9"),
92 Font::RDelete => Cow::Borrowed("0;9"),
93 Font::Black => Cow::Borrowed("30"),
94 Font::RBlack => Cow::Borrowed("0;30"),
95 Font::Red => Cow::Borrowed("31"),
96 Font::RRed => Cow::Borrowed("0;31"),
97 Font::Green => Cow::Borrowed("32"),
98 Font::RGreen => Cow::Borrowed("0;32"),
99 Font::Yellow => Cow::Borrowed("33"),
100 Font::RYellow => Cow::Borrowed("0;33"),
101 Font::Blue => Cow::Borrowed("34"),
102 Font::RBlue => Cow::Borrowed("0;34"),
103 Font::Purple => Cow::Borrowed("35"),
104 Font::RPurple => Cow::Borrowed("0;35"),
105 Font::Cyan => Cow::Borrowed("36"),
106 Font::RCyan => Cow::Borrowed("0;36"),
107 Font::Grey => Cow::Borrowed("37"),
108 Font::RGrey => Cow::Borrowed("0;37"),
109 Font::BgBlack => Cow::Borrowed("40"),
110 Font::RBgBlack => Cow::Borrowed("0;40"),
111 Font::BgRed => Cow::Borrowed("41"),
112 Font::RBgRed => Cow::Borrowed("0;41"),
113 Font::BgGreen => Cow::Borrowed("42"),
114 Font::RBgGreen => Cow::Borrowed("0;42"),
115 Font::BgYellow => Cow::Borrowed("43"),
116 Font::RBgYellow => Cow::Borrowed("0;43"),
117 Font::BgBlue => Cow::Borrowed("44"),
118 Font::RBgBlue => Cow::Borrowed("0;44"),
119 Font::BgPurple => Cow::Borrowed("45"),
120 Font::RBgPurple => Cow::Borrowed("0;45"),
121 Font::BgCyan => Cow::Borrowed("46"),
122 Font::RBgCyan => Cow::Borrowed("0;46"),
123 Font::BgGrey => Cow::Borrowed("47"),
124 Font::RBgGrey => Cow::Borrowed("0;47"),
125 Font::Color(r, g, b) => Cow::Owned(format!("38;2;{};{};{}", r, g, b)),
126 Font::RColor(r, g, b) => Cow::Owned(format!("0;38;2;{};{};{}", r, g, b)),
127 Font::BgColor(r, g, b) => Cow::Owned(format!("48;2;{};{};{}", r, g, b)),
128 Font::RBgColor(r, g, b) => Cow::Owned(format!("0;48;2;{};{};{}", r, g, b)),
129 }
130 }
131}
132impl Display for Font {
133 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
134 write!(f, "\x1b[{}m", self.as_str())
135 }
136}
137
138#[test]
139fn font_is_work() {
140 assert_eq!("\x1b[30m", format!("{}", Font::Black));
141 assert_eq!("\x1b[38;2;1;2;3m", format!("{}", Font::Color(1, 2, 3)));
142}
143
144#[macro_export]
153macro_rules! fonts {
154 ($ ($font:expr),*) => {{
155 let mut s = String::new();
156 $crate::wf!(&mut s, $($font),*);
157 s
158 }};
159}
160
161#[macro_export]
172macro_rules! wf {
173 ($s:expr, $($font:expr),*) => {{
174 use std::fmt::Write;
175 $s.push_str("\x1b[");
176 $(
177 let s = $font.as_str();
178 if s.starts_with("\x1b[") {
179 write!($s, "{};", &s[2..s.len() - 1]).unwrap();
180 }else {
181 write!($s, "{};", s).unwrap();
182 }
183 )*
184 $s.pop();
185 $s.push('m');
186 }};
187}
188
189pub trait FontTool {
190 fn reset(&mut self) -> &Self;
191
192 fn no_reset(self) -> Self;
193
194 fn none_font(&self) -> Self;
195}
196
197impl FontTool for String {
198 fn reset(&mut self) -> &Self {
199 let reset = Font::Reset.to_string();
200 if !self.ends_with(&reset) {
201 self.push_str(&reset)
202 }
203 self
204 }
205
206 fn no_reset(mut self) -> Self {
207 if self.ends_with("\x1b[0m") {
208 self.truncate(self.len() - 4);
209 }
210 self
211 }
212
213 fn none_font(&self) -> Self {
214 none_font(self)
215 }
216}
217
218pub fn none_font(s: &str) -> String {
219 let mut buf = String::new();
220 let mut flag = false;
221 for c in s.chars() {
222 match c {
223 '\x1b' => flag = true,
224 'm' if flag => flag = false,
225 _ if !flag => buf.push(c),
226 _ => {}
227 }
228 }
229 buf
230}
231
232#[test]
233fn aaa() {
234 use crate::cs;
235 use crate::Colored;
236 let s = cs!(Font::Red => "hello");
237 println!("{s}");
238 println!("{}", s.none_font());
239 println!("{}456", "123".red().no_reset());
240}