1use crate::segment::{Meta, MetaApply, SegmentBuffer};
2
3pub type Text = SegmentBuffer<Formatting>;
4
5#[derive(Default, Clone, PartialEq, Debug)]
6pub struct Formatting {
7 pub color: Option<u32>,
8 pub bg_color: Option<u32>,
9 pub bold: bool,
10 pub underline: bool,
11 pub decoration: bool,
12}
13impl Meta for Formatting {
14 fn try_merge(&mut self, other: &Self) -> bool {
15 self == other
16 }
17}
18
19impl MetaApply<Formatting> for Formatting {
20 fn apply(&mut self, change: &Formatting) {
21 if let Some(color) = change.color {
22 self.color = Some(color);
23 }
24 if let Some(bg_color) = change.bg_color {
25 self.bg_color = Some(bg_color);
26 }
27 if change.bold {
28 self.bold = true;
29 }
30 if change.underline {
31 self.underline = true;
32 }
33 }
34}
35
36pub struct AddColorToUncolored(pub u32);
37impl MetaApply<AddColorToUncolored> for Formatting {
38 fn apply(&mut self, change: &AddColorToUncolored) {
39 if self.color.is_some() {
40 return;
41 }
42 self.color = Some(change.0);
43 }
44}
45
46impl Formatting {
47 pub fn line_number() -> Self {
48 Self {
49 color: Some(0x92837400),
50 bg_color: Some(0x28282800),
51 ..Default::default()
52 }
53 }
54 pub fn color(color: u32) -> Self {
55 Self {
56 color: Some(color),
57 ..Default::default()
58 }
59 }
60 pub fn rgb([r, g, b]: [u8; 3]) -> Self {
61 Self::color(u32::from_be_bytes([r, g, b, 0]))
62 }
63
64 pub fn decoration(mut self) -> Self {
65 self.decoration = true;
66 self
67 }
68}
69
70pub fn text_to_ansi(buf: &Text, out: &mut String) {
71 use std::fmt::Write;
72
73 for (text, meta) in buf.iter() {
74 if let Some(color) = meta.color {
75 let [r, g, b, _a] = u32::to_be_bytes(color);
76 write!(out, "\x1b[38;2;{r};{g};{b}m").expect("no fmt error");
77 }
78 if let Some(bg_color) = meta.bg_color {
79 let [r, g, b, _a] = u32::to_be_bytes(bg_color);
80 write!(out, "\x1b[48;2;{r};{g};{b}m").expect("no fmt error")
81 }
82 for chunk in text {
83 write!(out, "{chunk}").expect("no fmt error");
84 }
85 if meta.color.is_some() || meta.bg_color.is_some() {
86 write!(out, "\x1b[0m").expect("no fmt error")
87 }
88 }
89}