hi_doc/
formatting.rs

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}