From bc72532465bde00e11d83ff4a9f767051ee6771d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Fri, 10 Sep 2021 12:39:10 -0700 Subject: [PATCH] feat(report): take terminal width into account for wrapping text --- Cargo.toml | 1 + src/eyreish/mod.rs | 3 ++- src/handlers/graphical.rs | 48 ++++++++++++++++++++++++--------------- tests/printer.rs | 2 ++ 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f9f83e6..72daccb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ owo-colors = "2.0.0" atty = "0.2.14" ci_info = "0.14.2" textwrap = "0.14.2" +term_size = "0.3.2" [dev-dependencies] semver = "1.0.4" diff --git a/src/eyreish/mod.rs b/src/eyreish/mod.rs index 8a45e27..db1e563 100644 --- a/src/eyreish/mod.rs +++ b/src/eyreish/mod.rs @@ -95,8 +95,9 @@ fn get_default_printer(_err: &(dyn Diagnostic + 'static)) -> Box Self { Self { linkify_code: true, + termwidth: 200, theme: GraphicalTheme::default(), } } @@ -38,6 +40,7 @@ impl GraphicalReportHandler { pub fn new_themed(theme: GraphicalTheme) -> Self { Self { linkify_code: true, + termwidth: 200, theme, } } @@ -47,6 +50,18 @@ impl GraphicalReportHandler { self.linkify_code = false; self } + + /// Set a theme for this handler. + pub fn with_theme(mut self, theme: GraphicalTheme) -> Self { + self.theme = theme; + self + } + + /// Sets the width to wrap the report at. + pub fn with_width(mut self, width: usize) -> Self { + self.termwidth = width; + self + } } impl Default for GraphicalReportHandler { @@ -66,6 +81,7 @@ impl GraphicalReportHandler { diagnostic: &(dyn Diagnostic), ) -> fmt::Result { self.render_header(f, diagnostic)?; + writeln!(f)?; self.render_causes(f, diagnostic)?; if let Some(snippets) = diagnostic.snippets() { @@ -80,11 +96,6 @@ impl GraphicalReportHandler { } fn render_header(&self, f: &mut impl fmt::Write, diagnostic: &(dyn Diagnostic)) -> fmt::Result { - let (severity_style, severity_icon) = match diagnostic.severity() { - Some(Severity::Error) | None => (self.theme.styles.error, self.theme.characters.x), - Some(Severity::Warning) => (self.theme.styles.warning, self.theme.characters.warning), - Some(Severity::Advice) => (self.theme.styles.advice, self.theme.characters.point_right), - }; write!(f, "{}", self.theme.characters.hbar.to_string().repeat(4))?; if self.linkify_code && diagnostic.url().is_some() && diagnostic.code().is_some() { let url = diagnostic.url().unwrap(); // safe @@ -100,24 +111,25 @@ impl GraphicalReportHandler { write!(f, "[{}]", code.style(self.theme.styles.code))?; } writeln!(f, "{}", self.theme.characters.hbar.to_string().repeat(20),)?; - writeln!(f)?; - // TODO: terminal width support - let initial_indent = format!(" {} ", severity_icon.style(severity_style)); - let rest_indent = format!(" {} ", self.theme.characters.vbar.style(severity_style)); - let opts = textwrap::Options::new(80) - .initial_indent(&initial_indent) - .subsequent_indent(&rest_indent); - writeln!(f, "{}", textwrap::fill(&diagnostic.to_string(), opts))?; Ok(()) } fn render_causes(&self, f: &mut impl fmt::Write, diagnostic: &(dyn Diagnostic)) -> fmt::Result { - let severity_style = match diagnostic.severity() { - Some(Severity::Error) | None => self.theme.styles.error, - Some(Severity::Warning) => self.theme.styles.warning, - Some(Severity::Advice) => self.theme.styles.advice, + let (severity_style, severity_icon) = match diagnostic.severity() { + Some(Severity::Error) | None => (self.theme.styles.error, self.theme.characters.x), + Some(Severity::Warning) => (self.theme.styles.warning, self.theme.characters.warning), + Some(Severity::Advice) => (self.theme.styles.advice, self.theme.characters.point_right), }; + let initial_indent = format!(" {} ", severity_icon.style(severity_style)); + let rest_indent = format!(" {} ", self.theme.characters.vbar.style(severity_style)); + let width = self.termwidth.saturating_sub(4); + let opts = textwrap::Options::new(width) + .initial_indent(&initial_indent) + .subsequent_indent(&rest_indent); + + writeln!(f, "{}", textwrap::fill(&diagnostic.to_string(), opts))?; + if let Some(cause) = diagnostic.source() { let mut cause_iter = Chain::new(cause).peekable(); while let Some(error) = cause_iter.next() { @@ -135,7 +147,7 @@ impl GraphicalReportHandler { let rest_indent = format!(" {} ", self.theme.characters.vbar) .style(severity_style) .to_string(); - let opts = textwrap::Options::new(80) + let opts = textwrap::Options::new(width) .initial_indent(&initial_indent) .subsequent_indent(&rest_indent); writeln!(f, "{}", textwrap::fill(&error.to_string(), opts))?; diff --git a/tests/printer.rs b/tests/printer.rs index 33db5fc..a64cd51 100644 --- a/tests/printer.rs +++ b/tests/printer.rs @@ -9,6 +9,7 @@ fn fmt_report(diag: Report) -> String { // Mostly for dev purposes. if std::env::var("STYLE").is_ok() { GraphicalReportHandler::new_themed(GraphicalTheme::unicode()) + .with_width(80) .render_report(&mut out, diag.as_ref()) .unwrap(); } else if std::env::var("NARRATED").is_ok() { @@ -17,6 +18,7 @@ fn fmt_report(diag: Report) -> String { .unwrap(); } else { GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor()) + .with_width(80) .render_report(&mut out, diag.as_ref()) .unwrap(); };