diff --git a/Cargo.toml b/Cargo.toml index 72daccb..1f31399 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ atty = "0.2.14" ci_info = "0.14.2" textwrap = "0.14.2" term_size = "0.3.2" +unicode-width = "0.1.8" [dev-dependencies] semver = "1.0.4" diff --git a/src/handlers/graphical.rs b/src/handlers/graphical.rs index fec93b6..b8c9917 100644 --- a/src/handlers/graphical.rs +++ b/src/handlers/graphical.rs @@ -1,6 +1,7 @@ -use std::fmt; +use std::fmt::{self, Write}; use owo_colors::{OwoColorize, Style}; +use unicode_width::UnicodeWidthStr; use crate::chain::Chain; use crate::handlers::theme::*; @@ -96,7 +97,14 @@ impl GraphicalReportHandler { } fn render_header(&self, f: &mut impl fmt::Write, diagnostic: &(dyn Diagnostic)) -> fmt::Result { - write!(f, "{}", self.theme.characters.hbar.to_string().repeat(4))?; + let mut header = String::new(); + let mut width = 0; + write!( + header, + "{}", + self.theme.characters.hbar.to_string().repeat(4) + )?; + width += UnicodeWidthStr::width(&header[..]); if self.linkify_code && diagnostic.url().is_some() && diagnostic.code().is_some() { let url = diagnostic.url().unwrap(); // safe let code = format!( @@ -106,11 +114,24 @@ impl GraphicalReportHandler { .expect("MIETTE BUG: already got checked for None") ); let link = format!("\u{1b}]8;;{}\u{1b}\\{}\u{1b}]8;;\u{1b}\\", url, code); - write!(f, "[{}]", link.style(self.theme.styles.code))?; + write!(header, "[{}]", link.style(self.theme.styles.code))?; + width += UnicodeWidthStr::width(&url.to_string()[..]) + + UnicodeWidthStr::width(&code[..]) + + 2; } else if let Some(code) = diagnostic.code() { - write!(f, "[{}]", code.style(self.theme.styles.code))?; + write!(header, "[{}]", code.style(self.theme.styles.code))?; + width += UnicodeWidthStr::width(&code.to_string()[..]) + 2; } - writeln!(f, "{}", self.theme.characters.hbar.to_string().repeat(20),)?; + writeln!( + f, + "{}{}", + header, + self.theme + .characters + .hbar + .to_string() + .repeat(self.termwidth.saturating_sub(width)), + )?; Ok(()) } diff --git a/tests/printer.rs b/tests/printer.rs index a64cd51..6efef2a 100644 --- a/tests/printer.rs +++ b/tests/printer.rs @@ -48,7 +48,7 @@ fn single_line_highlight() -> Result<(), MietteError> { let out = fmt_report(err.into()); println!("{}", out); let expected = r#" -────[oops::my::bad]──────────────────── +────[oops::my::bad]───────────────────────────────────────────────────────────── × oops! @@ -91,7 +91,7 @@ fn single_line_highlight_offset_zero() -> Result<(), MietteError> { let out = fmt_report(err.into()); println!("{}", out); let expected = r#" -────[oops::my::bad]──────────────────── +────[oops::my::bad]───────────────────────────────────────────────────────────── × oops! @@ -134,7 +134,7 @@ fn single_line_highlight_with_empty_span() -> Result<(), MietteError> { let out = fmt_report(err.into()); println!("{}", out); let expected = r#" -────[oops::my::bad]──────────────────── +────[oops::my::bad]───────────────────────────────────────────────────────────── × oops! @@ -177,7 +177,7 @@ fn single_line_highlight_no_label() -> Result<(), MietteError> { let out = fmt_report(err.into()); println!("{}", out); let expected = r#" -────[oops::my::bad]──────────────────── +────[oops::my::bad]───────────────────────────────────────────────────────────── × oops! @@ -222,7 +222,7 @@ fn multiple_same_line_highlights() -> Result<(), MietteError> { let out = fmt_report(err.into()); println!("{}", out); let expected = r#" -────[oops::my::bad]──────────────────── +────[oops::my::bad]───────────────────────────────────────────────────────────── × oops! @@ -266,7 +266,7 @@ fn multiline_highlight_adjacent() -> Result<(), MietteError> { let out = fmt_report(err.into()); println!("{}", out); let expected = r#" -────[oops::my::bad]──────────────────── +────[oops::my::bad]───────────────────────────────────────────────────────────── × oops! @@ -317,7 +317,7 @@ line5 let out = fmt_report(err.into()); println!("{}", out); let expected = r#" -────[oops::my::bad]──────────────────── +────[oops::my::bad]───────────────────────────────────────────────────────────── × oops! @@ -382,7 +382,7 @@ line5 let out = fmt_report(err.into()); println!("{}", out); let expected = " -────[oops::my::bad]──────────────────── +────[oops::my::bad]───────────────────────────────────────────────────────────── × wtf?! │ it broke :( @@ -436,7 +436,7 @@ fn multiple_multiline_highlights_adjacent() -> Result<(), MietteError> { let out = fmt_report(err.into()); println!("{}", out); let expected = r#" -────[oops::my::bad]──────────────────── +────[oops::my::bad]───────────────────────────────────────────────────────────── × oops! @@ -582,7 +582,7 @@ fn unnamed_snippet_shows_message() { let out = fmt_report(err.into()); println!("{}", out); let expected = r#" -────[oops::my::bad]──────────────────── +────[oops::my::bad]───────────────────────────────────────────────────────────── × oops!