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