1#![no_std]
29
30extern crate alloc;
31
32use core::fmt::Display;
33
34use alloc::{format, string::String};
35
36pub struct StyleBuilder {
38 bold: bool,
39 dim: bool,
40 italic: bool,
41 underline: bool,
42 blink: bool,
43 inverse: bool,
44 hidden: bool,
45 strikethrough: bool,
46 overline: bool,
47 color: Option<Color>,
48 bg_color: Option<BGColor>,
49}
50
51impl StyleBuilder {
52 #[must_use]
54 pub fn new() -> Self {
55 Self {
56 bold: false,
57 dim: false,
58 italic: false,
59 underline: false,
60 blink: false,
61 inverse: false,
62 hidden: false,
63 strikethrough: false,
64 overline: false,
65 color: None,
66 bg_color: None,
67 }
68 }
69
70 #[must_use]
72 pub fn bold(mut self) -> Self {
73 self.bold = true;
74 self
75 }
76
77 #[must_use]
79 pub fn dim(mut self) -> Self {
80 self.dim = true;
81 self
82 }
83
84 #[must_use]
86 pub fn italic(mut self) -> Self {
87 self.italic = true;
88 self
89 }
90
91 #[must_use]
93 pub fn underline(mut self) -> Self {
94 self.underline = true;
95 self
96 }
97
98 #[must_use]
100 pub fn blink(mut self) -> Self {
101 self.blink = true;
102 self
103 }
104
105 #[must_use]
107 pub fn inverse(mut self) -> Self {
108 self.inverse = true;
109 self
110 }
111
112 #[must_use]
114 pub fn hidden(mut self) -> Self {
115 self.hidden = true;
116 self
117 }
118
119 #[must_use]
121 pub fn strikethrough(mut self) -> Self {
122 self.strikethrough = true;
123 self
124 }
125
126 #[must_use]
128 pub fn overline(mut self) -> Self {
129 self.overline = true;
130 self
131 }
132
133 #[must_use]
135 pub fn black(mut self) -> Self {
136 self.color = Some(Color::Black);
137 self
138 }
139
140 #[must_use]
142 pub fn red(mut self) -> Self {
143 self.color = Some(Color::Red);
144 self
145 }
146
147 #[must_use]
149 pub fn green(mut self) -> Self {
150 self.color = Some(Color::Green);
151 self
152 }
153
154 #[must_use]
156 pub fn yellow(mut self) -> Self {
157 self.color = Some(Color::Yellow);
158 self
159 }
160
161 #[must_use]
163 pub fn blue(mut self) -> Self {
164 self.color = Some(Color::Blue);
165 self
166 }
167
168 #[must_use]
170 pub fn magenta(mut self) -> Self {
171 self.color = Some(Color::Magenta);
172 self
173 }
174
175 #[must_use]
177 pub fn cyan(mut self) -> Self {
178 self.color = Some(Color::Cyan);
179 self
180 }
181
182 #[must_use]
184 pub fn white(mut self) -> Self {
185 self.color = Some(Color::White);
186 self
187 }
188
189 #[must_use]
191 pub fn black_bright(mut self) -> Self {
192 self.color = Some(Color::BlackBright);
193 self
194 }
195
196 #[must_use]
198 pub fn red_bright(mut self) -> Self {
199 self.color = Some(Color::RedBright);
200 self
201 }
202
203 #[must_use]
205 pub fn green_bright(mut self) -> Self {
206 self.color = Some(Color::GreenBright);
207 self
208 }
209
210 #[must_use]
212 pub fn yellow_bright(mut self) -> Self {
213 self.color = Some(Color::YellowBright);
214 self
215 }
216
217 #[must_use]
219 pub fn blue_bright(mut self) -> Self {
220 self.color = Some(Color::BlueBright);
221 self
222 }
223
224 #[must_use]
226 pub fn magenta_bright(mut self) -> Self {
227 self.color = Some(Color::MagentaBright);
228 self
229 }
230
231 #[must_use]
233 pub fn cyan_bright(mut self) -> Self {
234 self.color = Some(Color::CyanBright);
235 self
236 }
237
238 #[must_use]
240 pub fn white_bright(mut self) -> Self {
241 self.color = Some(Color::WhiteBright);
242 self
243 }
244
245 #[must_use]
247 pub fn bg_black(mut self) -> Self {
248 self.bg_color = Some(BGColor::Black);
249 self
250 }
251
252 #[must_use]
254 pub fn bg_red(mut self) -> Self {
255 self.bg_color = Some(BGColor::Red);
256 self
257 }
258
259 #[must_use]
261 pub fn bg_green(mut self) -> Self {
262 self.bg_color = Some(BGColor::Green);
263 self
264 }
265
266 #[must_use]
268 pub fn bg_yellow(mut self) -> Self {
269 self.bg_color = Some(BGColor::Yellow);
270 self
271 }
272
273 #[must_use]
275 pub fn bg_blue(mut self) -> Self {
276 self.bg_color = Some(BGColor::Blue);
277 self
278 }
279
280 #[must_use]
282 pub fn bg_magenta(mut self) -> Self {
283 self.bg_color = Some(BGColor::Magenta);
284 self
285 }
286
287 #[must_use]
289 pub fn bg_cyan(mut self) -> Self {
290 self.bg_color = Some(BGColor::Cyan);
291 self
292 }
293
294 #[must_use]
296 pub fn bg_white(mut self) -> Self {
297 self.bg_color = Some(BGColor::White);
298 self
299 }
300
301 #[must_use]
303 pub fn bg_black_bright(mut self) -> Self {
304 self.bg_color = Some(BGColor::BlackBright);
305 self
306 }
307
308 #[must_use]
310 pub fn bg_red_bright(mut self) -> Self {
311 self.bg_color = Some(BGColor::RedBright);
312 self
313 }
314
315 #[must_use]
317 pub fn bg_green_bright(mut self) -> Self {
318 self.bg_color = Some(BGColor::GreenBright);
319 self
320 }
321
322 #[must_use]
324 pub fn bg_yellow_bright(mut self) -> Self {
325 self.bg_color = Some(BGColor::YellowBright);
326 self
327 }
328
329 #[must_use]
331 pub fn bg_blue_bright(mut self) -> Self {
332 self.bg_color = Some(BGColor::BlueBright);
333 self
334 }
335
336 #[must_use]
338 pub fn bg_magenta_bright(mut self) -> Self {
339 self.bg_color = Some(BGColor::MagentaBright);
340 self
341 }
342
343 #[must_use]
345 pub fn bg_cyan_bright(mut self) -> Self {
346 self.bg_color = Some(BGColor::CyanBright);
347 self
348 }
349
350 #[must_use]
352 pub fn bg_white_bright(mut self) -> Self {
353 self.bg_color = Some(BGColor::WhiteBright);
354 self
355 }
356
357 #[must_use]
360 pub fn build(self) -> Style {
361 let StyleBuilder {
362 bold,
363 dim,
364 italic,
365 underline,
366 blink,
367 inverse,
368 hidden,
369 strikethrough,
370 overline,
371 color,
372 bg_color,
373 } = self;
374
375 Style {
376 bold,
377 dim,
378 italic,
379 underline,
380 blink,
381 inverse,
382 hidden,
383 strikethrough,
384 overline,
385 color,
386 bg_color,
387 }
388 }
389}
390
391impl Default for StyleBuilder {
392 fn default() -> Self {
393 Self::new()
394 }
395}
396
397#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
399pub struct Style {
400 bold: bool,
401 dim: bool,
402 italic: bool,
403 underline: bool,
404 blink: bool,
405 inverse: bool,
406 hidden: bool,
407 strikethrough: bool,
408 overline: bool,
409 color: Option<Color>,
410 bg_color: Option<BGColor>,
411}
412
413impl Style {
414 #[must_use]
416 pub fn new() -> Self {
417 Self {
418 bold: false,
419 dim: false,
420 italic: false,
421 underline: false,
422 blink: false,
423 inverse: false,
424 hidden: false,
425 strikethrough: false,
426 overline: false,
427 color: None,
428 bg_color: None,
429 }
430 }
431
432 #[must_use]
434 pub fn builder() -> StyleBuilder {
435 StyleBuilder::new()
436 }
437
438 #[must_use]
440 pub fn bold(&self) -> bool {
441 self.bold
442 }
443
444 #[must_use]
446 pub fn dim(&self) -> bool {
447 self.dim
448 }
449
450 #[must_use]
452 pub fn italic(&self) -> bool {
453 self.italic
454 }
455
456 #[must_use]
458 pub fn underline(&self) -> bool {
459 self.underline
460 }
461
462 #[must_use]
464 pub fn blink(&self) -> bool {
465 self.blink
466 }
467
468 #[must_use]
470 pub fn inverse(&self) -> bool {
471 self.inverse
472 }
473
474 #[must_use]
476 pub fn hidden(&self) -> bool {
477 self.hidden
478 }
479
480 #[must_use]
482 pub fn strikethrough(&self) -> bool {
483 self.strikethrough
484 }
485
486 #[must_use]
488 pub fn overline(&self) -> bool {
489 self.overline
490 }
491
492 #[must_use]
495 pub fn color(&self) -> Color {
496 match self.color {
497 Some(color) => color,
498 None => Color::Any,
499 }
500 }
501
502 #[must_use]
505 pub fn bg_color(&self) -> BGColor {
506 match self.bg_color {
507 Some(color) => color,
508 None => BGColor::Any,
509 }
510 }
511
512 #[must_use]
520 pub fn rgb_to_ansi256(red: u8, green: u8, blue: u8) -> u8 {
521 if red == green && green == blue {
522 if red < 8 {
523 return 16;
524 }
525
526 if red > 248 {
527 return 231;
528 }
529
530 return ((((red as f32 - 8.) / 247.) * 24.) + 232.) as u8;
531 }
532
533 (16. + (36. * (red as f32 / 255. * 5.))
534 + (6. * (green as f32 / 255. * 5.))
535 + (blue as f32 / 255. * 5.)) as u8
536 }
537
538 #[must_use]
542 pub fn stylize(&self, text: &str) -> String {
543 format!("{self}{text}{}", Self::reset())
544 }
545
546 fn is_default(&self) -> bool {
547 *self == Self::default()
548 }
549
550 fn reset() -> &'static str {
551 "\x1B[0m"
552 }
553}
554
555impl Display for Style {
556 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
557 if self.is_default() {
558 return Ok(());
559 }
560
561 write!(f, "\x1B[")?;
562
563 let mut written = false;
564
565 {
566 let mut write_char = |c| {
567 if written {
568 write!(f, ";")?;
569 }
570 written = true;
571 write!(f, "{}", c)?;
572 Ok(())
573 };
574
575 if self.bold {
576 write_char('1')?;
577 }
578
579 if self.dim {
580 write_char('2')?;
581 }
582
583 if self.italic {
584 write_char('3')?;
585 }
586
587 if self.underline {
588 write_char('4')?;
589 }
590
591 if self.blink {
592 write_char('5')?;
593 }
594
595 if self.inverse {
596 write_char('7')?;
597 }
598
599 if self.hidden {
600 write_char('8')?;
601 }
602
603 if self.strikethrough {
604 write_char('9')?;
605 }
606
607 if self.overline {
608 write!(f, "53")?;
609 }
610 }
611
612 if let Some(color) = self.bg_color {
613 if written {
614 write!(f, ";{color}")?;
615 } else {
616 write!(f, "{color}")?;
617 written = true;
618 }
619 }
620
621 if let Some(color) = self.color {
622 if written {
623 write!(f, ";{color}")?;
624 } else {
625 write!(f, "{color}")?;
626 }
627 }
628
629 write!(f, "m")
630 }
631}
632
633impl Default for Style {
634 fn default() -> Self {
635 Self::new()
636 }
637}
638
639#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
642pub enum Color {
643 Any,
645 Black,
647 Red,
649 Green,
651 Yellow,
653 Blue,
655 Magenta,
657 Cyan,
659 White,
661
662 BlackBright,
664 RedBright,
666 GreenBright,
668 YellowBright,
670 BlueBright,
672 MagentaBright,
674 CyanBright,
676 WhiteBright,
678
679 Ansi256(u8),
681 RGB(u8, u8, u8),
683}
684
685impl Color {
686 #[must_use]
688 pub fn close(&self) -> &'static str {
689 "\x1B[39m"
690 }
691
692 #[must_use]
694 pub fn open(&self) -> String {
695 format!("\x1B[{self}m")
696 }
697
698 #[must_use]
702 pub fn paint(&self, text: &str) -> String {
703 format!("{}{text}{}", self.open(), self.close())
704 }
705}
706
707impl Display for Color {
708 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
709 match self {
710 Color::Any => write!(f, ""),
711 Color::Black => write!(f, "30"),
712 Color::Red => write!(f, "31"),
713 Color::Green => write!(f, "32"),
714 Color::Yellow => write!(f, "33"),
715 Color::Blue => write!(f, "34"),
716 Color::Magenta => write!(f, "35"),
717 Color::Cyan => write!(f, "36"),
718 Color::White => write!(f, "37"),
719 Color::BlackBright => write!(f, "90"),
720 Color::RedBright => write!(f, "91"),
721 Color::GreenBright => write!(f, "92"),
722 Color::YellowBright => write!(f, "93"),
723 Color::BlueBright => write!(f, "94"),
724 Color::MagentaBright => write!(f, "95"),
725 Color::CyanBright => write!(f, "96"),
726 Color::WhiteBright => write!(f, "97"),
727 Color::Ansi256(num) => write!(f, "38;5;{}", &num),
728 Color::RGB(r, g, b) => write!(f, "38;2;{};{};{}", &r, &g, &b),
729 }
730 }
731}
732
733#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
736pub enum BGColor {
737 Any,
739 Black,
741 Red,
743 Green,
745 Yellow,
747 Blue,
749 Magenta,
751 Cyan,
753 White,
755
756 BlackBright,
758 RedBright,
760 GreenBright,
762 YellowBright,
764 BlueBright,
766 MagentaBright,
768 CyanBright,
770 WhiteBright,
772
773 Ansi256(u8),
775 RGB(u8, u8, u8),
777}
778
779impl BGColor {
780 #[must_use]
782 pub fn close(&self) -> &'static str {
783 "\x1B[49m"
784 }
785
786 #[must_use]
788 pub fn open(&self) -> String {
789 format!("\x1B[{self}m")
790 }
791
792 #[must_use]
796 pub fn paint(&self, text: &str) -> String {
797 format!("{}{text}{}", self.open(), self.close())
798 }
799}
800
801impl Display for BGColor {
802 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
803 match self {
804 BGColor::Any => write!(f, ""),
805 BGColor::Black => write!(f, "40"),
806 BGColor::Red => write!(f, "41"),
807 BGColor::Green => write!(f, "42"),
808 BGColor::Yellow => write!(f, "43"),
809 BGColor::Blue => write!(f, "44"),
810 BGColor::Magenta => write!(f, "45"),
811 BGColor::Cyan => write!(f, "46"),
812 BGColor::White => write!(f, "47"),
813 BGColor::BlackBright => write!(f, "100"),
814 BGColor::RedBright => write!(f, "101"),
815 BGColor::GreenBright => write!(f, "102"),
816 BGColor::YellowBright => write!(f, "103"),
817 BGColor::BlueBright => write!(f, "104"),
818 BGColor::MagentaBright => write!(f, "105"),
819 BGColor::CyanBright => write!(f, "106"),
820 BGColor::WhiteBright => write!(f, "107"),
821 BGColor::Ansi256(num) => write!(f, "48;5;{}", &num),
822 BGColor::RGB(r, g, b) => write!(f, "48;2;{};{};{}", &r, &g, &b),
823 }
824 }
825}