1use std::fmt::Display;
2use std::io::Write;
3
4#[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
5pub enum Fmt {
6 Default,
7 Bold,
8 Underline,
9 UnderlineStop,
10}
11
12#[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
13pub enum Col {
14 Black,
15 Red,
16 Green,
17 Yellow,
18 Blue,
19 Purple,
20 DarkCyan,
21 Grey,
22 DarkGrey,
23 BrightRed,
24 Lime,
25 BrightYellow,
26 BrightBlue,
27 Magenta,
28 Cyan,
29 White,
30}
31
32macro_rules! f {
33 ($s:expr) => {
34 format!("{}[{}m", 27 as char, $s).as_str()
35 };
36}
37
38pub struct Printer {
39 s: String,
40 last_col: Col,
41 last_bg: Col,
42 last_fmt: Fmt,
43}
44
45impl Printer {
46 pub fn start() -> Self {
47 Printer {
48 s: "".to_string(),
49 last_col: Col::White,
50 last_bg: Col::Black,
51 last_fmt: Fmt::Default,
52 }
53 }
54
55 pub fn text(mut self, text: &str) -> Self {
56 self.s.push_str(text);
57 self
58 }
59
60 pub fn text_ln(self, text: &str) -> Self {
61 let f = self.last_fmt;
62 let c = self.last_col;
63 let g = self.last_bg;
64 self.text(text).def().ln().col(c).bg(g).fmt(f)
65 }
66
67 pub fn ln(mut self) -> Self {
68 let f = self.last_fmt;
69 let c = self.last_col;
70 let b = self.last_bg;
71 self.s.push_str(f!(0));
72 self.s.push(10 as char);
73 self.col(c).bg(b).fmt(f)
74 }
75
76 pub fn fmt(mut self, fmt: Fmt) -> Self {
77 match fmt {
78 Fmt::Default => self.s.push_str(f!(0)),
79 Fmt::Bold => self.s.push_str(f!(1)),
80 Fmt::Underline => self.s.push_str(f!(4)),
81 Fmt::UnderlineStop => self.s.push_str(f!(24)),
82 }
83 self.last_fmt = fmt;
84 self
85 }
86
87 pub fn def(self) -> Self {
88 self.fmt(Fmt::Default)
89 }
90
91 pub fn col(mut self, col: Col) -> Self {
92 match col {
93 Col::Black => self.s.push_str(f!(30)),
94 Col::Red => self.s.push_str(f!(31)),
95 Col::Green => self.s.push_str(f!(32)),
96 Col::Yellow => self.s.push_str(f!(33)),
97 Col::Blue => self.s.push_str(f!(34)),
98 Col::Purple => self.s.push_str(f!(35)),
99 Col::DarkCyan => self.s.push_str(f!(36)),
100 Col::Grey => self.s.push_str(f!(37)),
101 Col::DarkGrey => self.s.push_str(f!(90)),
102 Col::BrightRed => self.s.push_str(f!(91)),
103 Col::Lime => self.s.push_str(f!(92)),
104 Col::BrightYellow => self.s.push_str(f!(93)),
105 Col::BrightBlue => self.s.push_str(f!(94)),
106 Col::Magenta => self.s.push_str(f!(95)),
107 Col::Cyan => self.s.push_str(f!(96)),
108 Col::White => self.s.push_str(f!(97)),
109 }
110 self.last_col = col;
111 self
112 }
113
114 pub fn bg(mut self, col: Col) -> Self {
115 match col {
116 Col::Black => self.s.push_str(f!(40)),
117 Col::Red => self.s.push_str(f!(41)),
118 Col::Green => self.s.push_str(f!(42)),
119 Col::Yellow => self.s.push_str(f!(43)),
120 Col::Blue => self.s.push_str(f!(44)),
121 Col::Purple => self.s.push_str(f!(45)),
122 Col::DarkCyan => self.s.push_str(f!(46)),
123 Col::Grey => self.s.push_str(f!(47)),
124 Col::DarkGrey => self.s.push_str(f!(100)),
125 Col::BrightRed => self.s.push_str(f!(101)),
126 Col::Lime => self.s.push_str(f!(102)),
127 Col::BrightYellow => self.s.push_str(f!(103)),
128 Col::BrightBlue => self.s.push_str(f!(104)),
129 Col::Magenta => self.s.push_str(f!(105)),
130 Col::Cyan => self.s.push_str(f!(106)),
131 Col::White => self.s.push_str(f!(107)),
132 }
133 self.last_bg = col;
134 self
135 }
136
137 pub fn revert_styles(self, fmt: Fmt, col: Col, bg: Col) -> Self {
138 self.col(col).bg(bg).fmt(fmt)
139 }
140
141 pub fn fmt_for(self, fmt: Fmt, text: &str) -> Self {
142 let f = self.last_fmt;
143 let c = self.last_col;
144 let b = self.last_bg;
145 self.fmt(fmt).text(text).revert_styles(f, c, b)
146 }
147
148 pub fn fmt_for_ln(self, fmt: Fmt, text: &str) -> Self {
149 self.fmt_for(fmt, text).ln()
150 }
151
152 pub fn col_for(self, col: Col, text: &str) -> Self {
153 let f = self.last_fmt;
154 let c = self.last_col;
155 let b = self.last_bg;
156 self.col(col).text(text).revert_styles(f, c, b)
157 }
158
159 pub fn col_for_ln(self, col: Col, text: &str) -> Self {
160 self.col_for(col, text).ln()
161 }
162
163 pub fn bg_for(self, col: Col, text: &str) -> Self {
164 let f = self.last_fmt;
165 let c = self.last_col;
166 let b = self.last_bg;
167 self.bg(col).text(text).revert_styles(f, c, b)
168 }
169
170 pub fn bg_for_ln(self, col: Col, text: &str) -> Self {
171 self.bg_for(col, text).ln()
172 }
173
174 pub fn all_for(self, fmt: Fmt, col: Col, bg: Col, text: &str) -> Self {
175 let f = self.last_fmt;
176 let c = self.last_col;
177 let b = self.last_bg;
178 self.col(col)
179 .bg(bg)
180 .fmt(fmt)
181 .text(text)
182 .revert_styles(f, c, b)
183 }
184
185 pub fn all_for_ln(self, fmt: Fmt, col: Col, bg: Col, text: &str) -> Self {
186 self.all_for(fmt, col, bg, text).ln()
187 }
188
189 pub fn flush(self) {
190 print!("{}", self.def().s);
191 std::io::stdout().flush().unwrap();
192 }
193}
194
195impl Display for Printer {
196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 write!(f, "{}", self.s)
198 }
199}