use std::fmt::Debug;
use crate::console::{Console, ConsoleOptions};
use crate::highlighter::ReprHighlighter;
use crate::measure::Measurement;
use crate::protocol::{Highlighter, Renderable};
use crate::segment::Segment;
use crate::text::Text;
pub struct Pretty {
text: Text,
}
impl Pretty {
pub fn new(value: &impl Debug) -> Self {
Pretty::from_string(format!("{value:#?}"))
}
pub fn compact(value: &impl Debug) -> Self {
Pretty::from_string(format!("{value:?}"))
}
fn from_string(rendered: String) -> Self {
let mut text = Text::new(rendered);
ReprHighlighter::new().highlight(&mut text);
Pretty { text }
}
}
impl Renderable for Pretty {
fn rich_render(&self, console: &Console, options: &ConsoleOptions) -> Vec<Segment> {
self.text.rich_render(console, options)
}
fn measure(&self, console: &Console, options: &ConsoleOptions) -> Measurement {
self.text.measure(console, options)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::color::ColorSystem;
fn render(pretty: &Pretty) -> String {
Console::builder()
.force_terminal(true)
.color_system(Some(ColorSystem::Truecolor))
.width(80)
.no_color(false)
.build()
.render_to_string(pretty)
}
#[test]
fn highlights_numbers_in_debug_output() {
let out = render(&Pretty::compact(&vec![1, 2, 3]));
assert!(out.contains("\x1b[1;36m1\x1b[0m"), "got {out:?}");
assert!(out.contains('3'));
}
#[test]
fn highlights_string_in_debug_output() {
let out = render(&Pretty::compact(&"hello"));
assert!(out.contains("\x1b[32m\"hello\"\x1b[0m"), "got {out:?}");
}
#[test]
fn pretty_multiline_preserves_structure() {
let out = render(&Pretty::new(&vec![vec![1, 2], vec![3, 4]]));
assert!(out.contains('\n'), "expected pretty multi-line layout");
assert!(out.contains("\x1b[1;36m4\x1b[0m"), "numbers highlighted");
}
}