1use crate::console::{Console, ConsoleOptions};
8use crate::measure::Measurement;
9use crate::protocol::Renderable;
10use crate::segment::Segment;
11use crate::style::Style;
12
13pub struct Styled {
15 renderable: Box<dyn Renderable>,
16 style: Style,
17}
18
19impl Styled {
20 pub fn new(renderable: Box<dyn Renderable>, style: Style) -> Self {
22 Styled { renderable, style }
23 }
24}
25
26impl Renderable for Styled {
27 fn rich_render(&self, console: &Console, options: &ConsoleOptions) -> Vec<Segment> {
28 let segments = self.renderable.rich_render(console, options);
29 Segment::apply_style(&segments, &self.style)
30 }
31
32 fn measure(&self, console: &Console, options: &ConsoleOptions) -> Measurement {
33 self.renderable.measure(console, options)
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use crate::color::ColorSystem;
43 use crate::text::Text;
44
45 fn console() -> Console {
46 Console::builder()
47 .force_terminal(true)
48 .color_system(Some(ColorSystem::Truecolor))
49 .width(20)
50 .build()
51 }
52
53 #[test]
54 fn applies_base_style() {
55 let styled = Styled::new(Box::new(Text::new("hi")), Style::parse("on red").unwrap());
57 assert_eq!(console().render_to_string(&styled), "\x1b[41mhi\x1b[0m");
58 }
59
60 #[test]
61 fn child_style_wins_on_top() {
62 let inner = Text::new("x");
64 let mut inner = inner;
65 inner.set_base_style(Style::parse("bold").unwrap());
66 let styled = Styled::new(Box::new(inner), Style::parse("green").unwrap());
67 assert_eq!(console().render_to_string(&styled), "\x1b[1;32mx\x1b[0m");
68 }
69}