1use crate::highlighter::ReprHighlighter;
5use crate::style::Style;
6use crate::text::Text;
7
8#[derive(Debug, Clone)]
10pub struct ReprError {
11 pub message: String,
12 pub source: Option<String>,
13}
14
15impl std::fmt::Display for ReprError {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 write!(f, "ReprError: {}", self.message)
18 }
19}
20
21impl std::error::Error for ReprError {}
22
23pub trait RichRepr {
25 fn rich_repr(&self) -> Text;
27}
28
29pub fn auto<T: std::fmt::Debug>(value: &T) -> Text {
31 let debug_str = format!("{:#?}", value);
32 ReprHighlighter::new().highlight_str(&debug_str)
33}
34
35pub fn rich_repr(
37 type_name: &str,
38 fields: &[(&str, &dyn std::fmt::Display)],
39 _options: Option<&ReprOptions>,
40) -> Text {
41 let mut text = Text::new("");
42
43 text.append_styled(
45 type_name,
46 Style::new()
47 .bold(true)
48 .color(crate::color::Color::parse("cyan").unwrap()),
49 );
50
51 text.plain.push('(');
52
53 for (i, (name, value)) in fields.iter().enumerate() {
54 if i > 0 {
55 text.plain.push_str(", ");
56 }
57 text.append_styled(
58 format!("{}=", name),
59 Style::new().color(crate::color::Color::parse("yellow").unwrap()),
60 );
61 text.append_styled(
62 value.to_string(),
63 Style::new().color(crate::color::Color::parse("green").unwrap()),
64 );
65 }
66
67 text.plain.push(')');
68 text
69}
70
71#[derive(Debug, Clone)]
73pub struct ReprOptions {
74 pub max_string: Option<usize>,
75 pub max_depth: Option<usize>,
76 pub max_length: Option<usize>,
77 pub indent_guides: bool,
78 pub expand_all: bool,
79}
80
81impl Default for ReprOptions {
82 fn default() -> Self {
83 Self {
84 max_string: Some(100),
85 max_depth: Some(4),
86 max_length: Some(100),
87 indent_guides: true,
88 expand_all: false,
89 }
90 }
91}
92
93impl ReprOptions {
94 pub fn new() -> Self {
95 Self::default()
96 }
97 pub fn max_string(mut self, max: usize) -> Self {
98 self.max_string = Some(max);
99 self
100 }
101 pub fn max_depth(mut self, depth: usize) -> Self {
102 self.max_depth = Some(depth);
103 self
104 }
105 pub fn max_length(mut self, max: usize) -> Self {
106 self.max_length = Some(max);
107 self
108 }
109 pub fn indent_guides(mut self, value: bool) -> Self {
110 self.indent_guides = value;
111 self
112 }
113 pub fn expand_all(mut self) -> Self {
114 self.expand_all = true;
115 self
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn test_auto() {
125 let value = vec![1, 2, 3];
126 let text = auto(&value);
127 assert!(!text.plain.is_empty());
128 }
129
130 #[test]
131 fn test_rich_repr() {
132 let text = rich_repr("Point", &[("x", &1), ("y", &2)], None);
133 assert!(text.plain.contains("Point"));
134 assert!(text.plain.contains("x=1"));
135 assert!(text.plain.contains("y=2"));
136 }
137}