1use bitflags::bitflags;
2
3#[derive(Debug, Clone, Copy, PartialEq)]
4pub enum Color {
5 Reset,
6 Black,
7 Red,
8 Green,
9 Yellow,
10 Blue,
11 Magenta,
12 Cyan,
13 Gray,
14 DarkGray,
15 LightRed,
16 LightGreen,
17 LightYellow,
18 LightBlue,
19 LightMagenta,
20 LightCyan,
21 White,
22 Rgb(u8, u8, u8),
23 Indexed(u8),
24}
25
26impl Color {
27 pub(crate) fn code(self) -> &'static str {
30 match self {
31 Color::Reset => "X",
32 Color::Black => "b",
33 Color::Red => "r",
34 Color::Green => "c",
35 Color::Yellow => "y",
36 Color::Blue => "b",
37 Color::Magenta => "m",
38 Color::Cyan => "c",
39 Color::Gray => "w",
40 Color::DarkGray => "B",
41 Color::LightRed => "R",
42 Color::LightGreen => "G",
43 Color::LightYellow => "Y",
44 Color::LightBlue => "B",
45 Color::LightMagenta => "M",
46 Color::LightCyan => "C",
47 Color::White => "W",
48 Color::Indexed(_) => "i",
49 Color::Rgb(_, _, _) => "o",
50 }
51 }
52}
53
54bitflags! {
55 pub struct Modifier: u16 {
56 const BOLD = 0b0000_0000_0001;
57 const DIM = 0b0000_0000_0010;
58 const ITALIC = 0b0000_0000_0100;
59 const UNDERLINED = 0b0000_0000_1000;
60 const SLOW_BLINK = 0b0000_0001_0000;
61 const RAPID_BLINK = 0b0000_0010_0000;
62 const REVERSED = 0b0000_0100_0000;
63 const HIDDEN = 0b0000_1000_0000;
64 const CROSSED_OUT = 0b0001_0000_0000;
65 }
66}
67
68impl Modifier {
69 pub(crate) fn code(self) -> String {
72 use std::fmt::Write;
73
74 let mut result = String::new();
75
76 if self.contains(Modifier::BOLD) {
77 write!(result, "BO").unwrap();
78 }
79 if self.contains(Modifier::DIM) {
80 write!(result, "DI").unwrap();
81 }
82 if self.contains(Modifier::ITALIC) {
83 write!(result, "IT").unwrap();
84 }
85 if self.contains(Modifier::UNDERLINED) {
86 write!(result, "UN").unwrap();
87 }
88 if self.contains(Modifier::SLOW_BLINK) {
89 write!(result, "SL").unwrap();
90 }
91 if self.contains(Modifier::RAPID_BLINK) {
92 write!(result, "RA").unwrap();
93 }
94 if self.contains(Modifier::REVERSED) {
95 write!(result, "RE").unwrap();
96 }
97 if self.contains(Modifier::HIDDEN) {
98 write!(result, "HI").unwrap();
99 }
100 if self.contains(Modifier::CROSSED_OUT) {
101 write!(result, "CR").unwrap();
102 }
103
104 result
105 }
106}
107
108#[derive(Debug, Clone, Copy, PartialEq)]
109pub struct Style {
110 pub fg: Color,
111 pub bg: Color,
112 pub modifier: Modifier,
113}
114
115impl Default for Style {
116 fn default() -> Style {
117 Style {
118 fg: Color::Reset,
119 bg: Color::Reset,
120 modifier: Modifier::empty(),
121 }
122 }
123}
124
125impl Style {
126 pub fn reset(&mut self) {
127 self.fg = Color::Reset;
128 self.bg = Color::Reset;
129 self.modifier = Modifier::empty();
130 }
131
132 pub fn fg(mut self, color: Color) -> Style {
133 self.fg = color;
134 self
135 }
136 pub fn bg(mut self, color: Color) -> Style {
137 self.bg = color;
138 self
139 }
140 pub fn modifier(mut self, modifier: Modifier) -> Style {
141 self.modifier = modifier;
142 self
143 }
144}