Skip to main content

error_engine/
engine.rs

1use crate::{catalog::Catalog, diagnostic::{EngineDiagnostic, Severity}};
2use tracing::{error, warn, info};
3
4pub struct Engine {
5    catalog: Catalog,
6}
7
8impl Engine {
9    pub fn new(catalog: Catalog) -> Self {
10        Self { catalog }
11    }
12
13    /// Plain text, no color, no logging. For GUI apps.
14    pub fn message(&self, diag: &dyn EngineDiagnostic) -> String {
15        self.catalog.render(diag.code(), &diag.context())
16    }
17
18    /// Sends to `tracing` at the matching level. For file/service logging.
19    pub fn log(&self, diag: &dyn EngineDiagnostic) {
20        let msg = self.message(diag);
21        match diag.severity() {
22            Severity::Error => error!(code = diag.code(), "{msg}"),
23            Severity::Warning => warn!(code = diag.code(), "{msg}"),
24            Severity::Info => info!(code = diag.code(), "{msg}"),
25        }
26    }
27
28    /// Colored terminal output, with hint if present. Requires the "cli" feature.
29    #[cfg(feature = "cli")]
30    pub fn print(&self, diag: &dyn EngineDiagnostic) {
31        use owo_colors::OwoColorize;
32
33        let msg = self.message(diag);
34        let hint = self.catalog.hint(diag.code());
35
36        match diag.severity() {
37            Severity::Error => eprintln!("{} {msg}", "✖".red().bold()),
38            Severity::Warning => eprintln!("{} {msg}", "⚠".yellow().bold()),
39            Severity::Info => println!("{} {msg}", "ℹ".blue().bold()),
40        }
41        if let Some(hint) = hint {
42            eprintln!("  {} {hint}", "→".dimmed());
43        }
44    }
45}