1use std::fmt::Debug;
15
16use crate::console::{Console, ConsoleOptions};
17use crate::highlighter::ReprHighlighter;
18use crate::measure::Measurement;
19use crate::protocol::{Highlighter, Renderable};
20use crate::segment::Segment;
21use crate::text::Text;
22
23pub struct Pretty {
26 text: Text,
27}
28
29impl Pretty {
30 pub fn new(value: &impl Debug) -> Self {
32 Pretty::from_string(format!("{value:#?}"))
33 }
34
35 pub fn compact(value: &impl Debug) -> Self {
37 Pretty::from_string(format!("{value:?}"))
38 }
39
40 fn from_string(rendered: String) -> Self {
41 let mut text = Text::new(rendered);
42 ReprHighlighter::new().highlight(&mut text);
43 Pretty { text }
44 }
45}
46
47impl Renderable for Pretty {
48 fn rich_render(&self, console: &Console, options: &ConsoleOptions) -> Vec<Segment> {
49 self.text.rich_render(console, options)
50 }
51
52 fn measure(&self, console: &Console, options: &ConsoleOptions) -> Measurement {
53 self.text.measure(console, options)
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use crate::color::ColorSystem;
61
62 fn render(pretty: &Pretty) -> String {
63 Console::builder()
64 .force_terminal(true)
65 .color_system(Some(ColorSystem::Truecolor))
66 .width(80)
67 .no_color(false)
68 .build()
69 .render_to_string(pretty)
70 }
71
72 #[test]
73 fn highlights_numbers_in_debug_output() {
74 let out = render(&Pretty::compact(&vec![1, 2, 3]));
76 assert!(out.contains("\x1b[1;36m1\x1b[0m"), "got {out:?}");
77 assert!(out.contains('3'));
78 }
79
80 #[test]
81 fn highlights_string_in_debug_output() {
82 let out = render(&Pretty::compact(&"hello"));
84 assert!(out.contains("\x1b[32m\"hello\"\x1b[0m"), "got {out:?}");
85 }
86
87 #[test]
88 fn pretty_multiline_preserves_structure() {
89 let out = render(&Pretty::new(&vec![vec![1, 2], vec![3, 4]]));
91 assert!(out.contains('\n'), "expected pretty multi-line layout");
92 assert!(out.contains("\x1b[1;36m4\x1b[0m"), "numbers highlighted");
93 }
94}