devalang_wasm/tools/logger/
mod.rs

1#[cfg(feature = "cli")]
2use crossterm::style::{Attribute, Color, ResetColor, SetAttribute, SetForegroundColor};
3#[cfg(feature = "cli")]
4use std::fmt::Write;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum LogLevel {
8    Success,
9    Error,
10    Info,
11    Warning,
12    Watch,
13    Debug,
14    Action,
15}
16
17#[derive(Debug, Clone, Default)]
18pub struct Logger;
19
20impl Logger {
21    pub fn new() -> Self {
22        Self
23    }
24
25    pub fn log(&self, level: LogLevel, message: impl AsRef<str>) {
26        self.print_line(level, message.as_ref());
27    }
28
29    pub fn log_with_details<I, S>(&self, level: LogLevel, message: impl AsRef<str>, details: I)
30    where
31        I: IntoIterator<Item = S>,
32        S: AsRef<str>,
33    {
34        self.print_line(level, message.as_ref());
35        for detail in details {
36            self.print_detail(detail.as_ref());
37        }
38    }
39
40    pub fn success(&self, message: impl AsRef<str>) {
41        self.log(LogLevel::Success, message);
42    }
43
44    pub fn info(&self, message: impl AsRef<str>) {
45        self.log(LogLevel::Info, message);
46    }
47
48    pub fn warn(&self, message: impl AsRef<str>) {
49        self.log(LogLevel::Warning, message);
50    }
51
52    pub fn error(&self, message: impl AsRef<str>) {
53        self.log(LogLevel::Error, message);
54    }
55
56    pub fn watch(&self, message: impl AsRef<str>) {
57        self.log(LogLevel::Watch, message);
58    }
59
60    pub fn debug(&self, message: impl AsRef<str>) {
61        self.log(LogLevel::Debug, message);
62    }
63
64    pub fn action(&self, message: impl AsRef<str>) {
65        self.log(LogLevel::Action, message);
66    }
67
68    fn print_detail(&self, detail: &str) {
69        #[cfg(feature = "cli")]
70        {
71            println!("   ↳ {}", detail);
72        }
73        #[cfg(not(feature = "cli"))]
74        {
75            println!("   -> {}", detail);
76        }
77    }
78
79    fn print_line(&self, level: LogLevel, message: &str) {
80        #[cfg(feature = "cli")]
81        {
82            println!("{}", self.render_colored_line(level, message));
83        }
84        #[cfg(not(feature = "cli"))]
85        {
86            println!("[{}] {}", level.as_plain_label(), message);
87        }
88    }
89
90    #[cfg(feature = "cli")]
91    fn render_colored_line(&self, level: LogLevel, message: &str) -> String {
92        let mut out = String::new();
93        let (emoji, color) = level.visuals();
94
95        out.push_str(emoji);
96        out.push(' ');
97        out.push_str(&self.render_signature());
98        out.push(' ');
99        out.push_str(&self.render_status(level, color));
100        out.push(' ');
101        out.push_str(message);
102        out
103    }
104
105    #[cfg(feature = "cli")]
106    fn render_signature(&self) -> String {
107        let mut s = String::new();
108        write!(&mut s, "{}", SetForegroundColor(Color::Grey)).unwrap();
109        s.push('[');
110        write!(
111            &mut s,
112            "{}",
113            SetForegroundColor(Color::Rgb {
114                r: 36,
115                g: 199,
116                b: 181,
117            })
118        )
119        .unwrap();
120        write!(&mut s, "{}", SetAttribute(Attribute::Bold)).unwrap();
121        s.push_str("Devalang");
122        write!(&mut s, "{}", SetAttribute(Attribute::Reset)).unwrap();
123        write!(&mut s, "{}", SetForegroundColor(Color::Grey)).unwrap();
124        s.push(']');
125        write!(&mut s, "{}", ResetColor).unwrap();
126        s
127    }
128
129    #[cfg(feature = "cli")]
130    fn render_status(&self, level: LogLevel, color: Color) -> String {
131        let mut s = String::new();
132        write!(&mut s, "{}", SetForegroundColor(color)).unwrap();
133        write!(&mut s, "{}", SetAttribute(Attribute::Bold)).unwrap();
134        s.push('[');
135        s.push_str(level.as_label());
136        s.push(']');
137        write!(&mut s, "{}", SetAttribute(Attribute::Reset)).unwrap();
138        write!(&mut s, "{}", ResetColor).unwrap();
139        s
140    }
141}
142
143impl LogLevel {
144    fn as_label(self) -> &'static str {
145        match self {
146            LogLevel::Success => "SUCCESS",
147            LogLevel::Error => "ERROR",
148            LogLevel::Info => "INFO",
149            LogLevel::Warning => "WARN",
150            LogLevel::Watch => "WATCH",
151            LogLevel::Debug => "DEBUG",
152            LogLevel::Action => "ACTION",
153        }
154    }
155
156    fn as_plain_label(self) -> &'static str {
157        match self {
158            LogLevel::Success => "SUCCESS",
159            LogLevel::Error => "ERROR",
160            LogLevel::Info => "INFO",
161            LogLevel::Warning => "WARN",
162            LogLevel::Watch => "WATCH",
163            LogLevel::Debug => "DEBUG",
164            LogLevel::Action => "ACTION",
165        }
166    }
167
168    #[cfg(feature = "cli")]
169    fn visuals(self) -> (&'static str, Color) {
170        match self {
171            LogLevel::Success => (
172                "✅",
173                Color::Rgb {
174                    r: 76,
175                    g: 175,
176                    b: 80,
177                },
178            ),
179            LogLevel::Error => (
180                "❌",
181                Color::Rgb {
182                    r: 244,
183                    g: 67,
184                    b: 54,
185                },
186            ),
187            LogLevel::Info => (
188                "ℹ️ ",
189                Color::Rgb {
190                    r: 33,
191                    g: 150,
192                    b: 243,
193                },
194            ),
195            LogLevel::Warning => (
196                "⚠️",
197                Color::Rgb {
198                    r: 255,
199                    g: 152,
200                    b: 0,
201                },
202            ),
203            LogLevel::Watch => (
204                "👀",
205                Color::Rgb {
206                    r: 171,
207                    g: 71,
208                    b: 188,
209                },
210            ),
211            LogLevel::Debug => (
212                "🛠️",
213                Color::Rgb {
214                    r: 121,
215                    g: 134,
216                    b: 203,
217                },
218            ),
219            LogLevel::Action => (
220                "🎵",
221                Color::Rgb {
222                    r: 0,
223                    g: 188,
224                    b: 212,
225                },
226            ),
227        }
228    }
229}
230
231pub mod format;
232pub mod layers;
233pub mod sinks;