diff --git a/src/handlers/graphical.rs b/src/handlers/graphical.rs index 83d731c..b55d588 100644 --- a/src/handlers/graphical.rs +++ b/src/handlers/graphical.rs @@ -214,8 +214,7 @@ impl GraphicalReportHandler { let opts = textwrap::Options::new(width) .initial_indent(&initial_indent) .subsequent_indent(&rest_indent); - let mut message = diagnostic.to_string(); - + let message = self.apply_tags(diagnostic.to_string()); writeln!(f, "{}", textwrap::fill(&message, opts))?; @@ -805,6 +804,31 @@ impl GraphicalReportHandler { } Ok((context_data, lines)) } + + fn apply_tags(&self, message: String) -> String { + let mut message = message; + + for (tag, style) in &self.theme.tags { + let open_tag = format!("<{}>", tag); + let close_tag = format!("", tag); + + while let Some(open_index) = message.find(&open_tag) { + if let Some(close_index) = message.find(&close_tag) { + let inner = &message[open_index + open_tag.len()..close_index]; + + message = message.replace( + &format!("{}{}{}", open_tag, inner, close_tag), + &inner.style(*style).to_string(), + ); + } else { + // No closing? Just remove the opening... + message = message.replace(&open_tag, ""); + } + } + } + + message + } } impl ReportHandler for GraphicalReportHandler { diff --git a/tests/graphical.rs b/tests/graphical.rs index 34dc433..776c858 100644 --- a/tests/graphical.rs +++ b/tests/graphical.rs @@ -4,6 +4,7 @@ use miette::{ Diagnostic, GraphicalReportHandler, GraphicalTheme, MietteError, NamedSource, NarratableReportHandler, Report, SourceSpan, }; +use owo_colors::Style; use thiserror::Error; fn fmt_report(diag: Report) -> String { @@ -1214,3 +1215,32 @@ fn zero_length_eol_span() { assert_eq!(expected, out); } + +#[test] +fn message_tags() -> Result<(), MietteError> { + #[derive(Debug, Diagnostic, Error)] + #[error("this is a string with many style tags!")] + #[diagnostic(code(oops::my::bad))] + struct MyBad; + + let mut theme = GraphicalTheme::unicode(); + theme.tags.insert("green".to_string(), Style::new().green()); + theme + .tags + .insert("yellow".to_string(), Style::new().yellow()); + theme.tags.insert("blue".to_string(), Style::new().blue()); + + let err = MyBad; + let report: Report = err.into(); + let mut out = String::new(); + + GraphicalReportHandler::new_themed(theme) + .with_width(80) + .render_report(&mut out, report.as_ref()) + .unwrap(); + + println!("Error: {}", out); + let expected = "\u{1b}[31moops::my::bad\u{1b}[0m\n\n \u{1b}[31m×\u{1b}[0m this \u{1b}[32mis\u{1b}[0m a \u{1b}[33mstring \u{1b}[34mwith\u{1b}[0m\u{1b}[0m many \u{1b}[32mstyle\u{1b}[0m tags!\n"; + assert_eq!(expected, out); + Ok(()) +}