devalang_core/utils/
logger.rs

1#[cfg(feature = "cli")]
2use crossterm::style::{Attribute, Color, ResetColor, SetAttribute, SetForegroundColor};
3use std::fmt::Write;
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum LogLevel {
7    Success,
8    Error,
9    Info,
10    Print,
11    Warning,
12    Watcher,
13    Debug,
14}
15
16#[derive(Debug, Clone)]
17pub struct Logger;
18
19impl Logger {
20    pub fn new() -> Self {
21        Logger
22    }
23
24    // --- log_message ---
25
26    #[cfg(feature = "cli")]
27    pub fn log_message(&self, level: LogLevel, message: &str) {
28        let formatted_status = self.format_status(level);
29        println!(
30            "🦊 {} {} {}",
31            self.language_signature(),
32            formatted_status,
33            message
34        );
35    }
36
37    #[cfg(not(feature = "cli"))]
38    pub fn log_message(&self, _level: LogLevel, _message: &str) {
39        // no-op for WASM
40    }
41
42    // --- log_message_with_trace ---
43
44    #[cfg(feature = "cli")]
45    pub fn log_message_with_trace(&self, level: LogLevel, message: &str, trace: Vec<&str>) {
46        let formatted_status = self.format_status(level);
47        println!(
48            "🦊 {} {} {}",
49            self.language_signature(),
50            formatted_status,
51            message
52        );
53        for t in trace {
54            println!("     ↳ {}", t);
55        }
56    }
57
58    #[cfg(not(feature = "cli"))]
59    pub fn log_message_with_trace(&self, _level: LogLevel, _message: &str, _trace: Vec<&str>) {
60        // no-op for WASM
61    }
62
63    // --- log_error_with_stacktrace ---
64
65    #[cfg(feature = "cli")]
66    pub fn log_error_with_stacktrace(&self, message: &str, stacktrace: &str) {
67        let formatted_status = self.format_status(LogLevel::Error);
68        println!(
69            "🦊 {} {} {}",
70            self.language_signature(),
71            formatted_status,
72            message
73        );
74        println!("     ↳ {}", stacktrace);
75    }
76
77    #[cfg(not(feature = "cli"))]
78    pub fn log_error_with_stacktrace(&self, _message: &str, _stacktrace: &str) {
79        // no-op for WASM
80    }
81
82    // --- language_signature ---
83
84    #[cfg(feature = "cli")]
85    fn language_signature(&self) -> String {
86        let mut s = String::new();
87
88        write!(&mut s, "{}", SetForegroundColor(Color::Grey)).unwrap();
89        s.push('[');
90
91        write!(
92            &mut s,
93            "{}",
94            SetForegroundColor(Color::Rgb {
95                r: 29,
96                g: 211,
97                b: 176
98            })
99        )
100        .unwrap();
101        write!(&mut s, "{}", SetAttribute(Attribute::Bold)).unwrap();
102        s.push_str("Devalang");
103        write!(&mut s, "{}", SetAttribute(Attribute::Reset)).unwrap();
104
105        write!(&mut s, "{}", SetForegroundColor(Color::Grey)).unwrap();
106        s.push(']');
107        write!(&mut s, "{}", ResetColor).unwrap();
108
109        s
110    }
111
112    #[cfg(not(feature = "cli"))]
113    fn language_signature(&self) -> String {
114        "[Devalang]".to_string()
115    }
116
117    // --- format_status ---
118
119    #[cfg(feature = "cli")]
120    fn format_status(&self, level: LogLevel) -> String {
121        let mut s = String::new();
122
123        let color = match level {
124            LogLevel::Success => Color::Rgb {
125                r: 76,
126                g: 175,
127                b: 80,
128            },
129            LogLevel::Error => Color::Rgb {
130                r: 244,
131                g: 67,
132                b: 54,
133            },
134            LogLevel::Info => Color::Rgb {
135                r: 33,
136                g: 150,
137                b: 243,
138            },
139            LogLevel::Warning => Color::Rgb {
140                r: 255,
141                g: 152,
142                b: 0,
143            },
144            LogLevel::Watcher => Color::Rgb {
145                r: 156,
146                g: 39,
147                b: 176,
148            },
149            LogLevel::Debug => Color::Rgb {
150                r: 103,
151                g: 58,
152                b: 183,
153            },
154            LogLevel::Print => Color::Rgb {
155                r: 255,
156                g: 255,
157                b: 255,
158            },
159        };
160
161        let status = match level {
162            LogLevel::Success => "SUCCESS",
163            LogLevel::Error => "ERROR",
164            LogLevel::Info => "INFO",
165            LogLevel::Warning => "WARNING",
166            LogLevel::Watcher => "WATCHER",
167            LogLevel::Debug => "DEBUG",
168            LogLevel::Print => "PRINT",
169        };
170
171        s.push('[');
172        write!(&mut s, "{}", SetForegroundColor(color)).unwrap();
173        write!(&mut s, "{}", SetAttribute(Attribute::Bold)).unwrap();
174        s.push_str(status);
175        write!(&mut s, "{}", SetAttribute(Attribute::Reset)).unwrap();
176        s.push(']');
177        write!(&mut s, "{}", ResetColor).unwrap();
178
179        s
180    }
181
182    #[cfg(not(feature = "cli"))]
183    fn format_status(&self, level: LogLevel) -> String {
184        match level {
185            LogLevel::Success => "[SUCCESS]",
186            LogLevel::Error => "[ERROR]",
187            LogLevel::Info => "[INFO]",
188            LogLevel::Warning => "[WARNING]",
189            LogLevel::Watcher => "[WATCHER]",
190            LogLevel::Debug => "[DEBUG]",
191            LogLevel::Print => "[PRINT]",
192        }
193        .to_string()
194    }
195}