stylex_macros/
stylex_error.rs1use colored::Colorize;
7use std::fmt;
8use stylex_constants::logger::STYLEX_LOG_PREFIX;
9
10#[derive(Debug, Clone)]
19pub struct StyleXError {
20 pub message: String,
21 pub file: Option<String>,
22 pub key_path: Option<Vec<String>>,
23 pub line: Option<usize>,
24 pub col: Option<usize>,
25 pub source_location: Option<String>,
26}
27
28impl fmt::Display for StyleXError {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 write!(f, "{} ", "[StyleX]".bright_blue().bold())?;
32
33 if let Some(ref keys) = self.key_path {
35 for key in keys {
36 write!(f, "{} > ", key.dimmed().cyan())?;
37 }
38 }
39
40 write!(f, "{}", self.message.red())?;
42
43 if let Some(ref file) = self.file {
45 match (self.line, self.col) {
46 (Some(line), Some(col)) => {
47 write!(f, "\n --> {file}:{line}:{col}")?;
48 },
49 (Some(line), None) => {
50 write!(f, "\n --> {file}:{line}")?;
51 },
52 _ => {
53 write!(f, "\n --> {file}")?;
54 },
55 }
56 }
57
58 if let Some(ref src) = self.source_location
60 && log::log_enabled!(log::Level::Info)
61 {
62 write!(f, "\n{}: {src}", "[Stack trace]".dimmed().yellow(),)?;
63 }
64
65 Ok(())
66 }
67}
68
69impl std::error::Error for StyleXError {}
70
71pub fn is_panic_stderr_suppressed() -> bool {
76 SUPPRESS_PANIC_STDERR.with(|f| f.get())
77}
78
79pub struct SuppressPanicStderr;
90
91impl SuppressPanicStderr {
92 pub fn new() -> Self {
93 SUPPRESS_PANIC_STDERR.with(|f| f.set(true));
94 Self
95 }
96}
97
98impl Default for SuppressPanicStderr {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104impl Drop for SuppressPanicStderr {
105 fn drop(&mut self) {
106 SUPPRESS_PANIC_STDERR.with(|f| f.set(false));
107 }
108}
109
110fn strip_ansi(s: &str) -> String {
116 let mut result = String::with_capacity(s.len());
117 let mut chars = s.chars().peekable();
118 while let Some(ch) = chars.next() {
119 if ch == '\x1B' && chars.peek() == Some(&'[') {
120 chars.next(); for c in chars.by_ref() {
122 if c == 'm' {
123 break;
124 }
125 }
126 } else {
127 result.push(ch);
128 }
129 }
130 result
131}
132
133pub fn format_panic_message(error: &Box<dyn std::any::Any + Send>) -> String {
142 let raw = match error.downcast_ref::<String>() {
144 Some(s) => s.clone(),
145 None => match error.downcast_ref::<&str>() {
146 Some(s) => s.to_string(),
147 None => {
148 return format!("{} Unknown error during transformation", STYLEX_LOG_PREFIX);
149 },
150 },
151 };
152
153 if raw.contains(STYLEX_LOG_PREFIX) {
154 raw
155 } else {
156 let plain = strip_ansi(&raw);
157
158 format!("{} {}", STYLEX_LOG_PREFIX, plain)
159 }
160}
161
162thread_local! {
167 static SUPPRESS_PANIC_STDERR: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
168}