mirror of https://github.com/zkat/miette.git
feat(report): take terminal width into account for wrapping text
This commit is contained in:
parent
f482dcec6a
commit
bc72532465
|
|
@ -19,6 +19,7 @@ owo-colors = "2.0.0"
|
||||||
atty = "0.2.14"
|
atty = "0.2.14"
|
||||||
ci_info = "0.14.2"
|
ci_info = "0.14.2"
|
||||||
textwrap = "0.14.2"
|
textwrap = "0.14.2"
|
||||||
|
term_size = "0.3.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
semver = "1.0.4"
|
semver = "1.0.4"
|
||||||
|
|
|
||||||
|
|
@ -95,8 +95,9 @@ fn get_default_printer(_err: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandl
|
||||||
} else {
|
} else {
|
||||||
atty::is(Stream::Stdout) && atty::is(Stream::Stderr) && !ci_info::is_ci()
|
atty::is(Stream::Stdout) && atty::is(Stream::Stderr) && !ci_info::is_ci()
|
||||||
};
|
};
|
||||||
|
let size = term_size::dimensions().unwrap_or((80, 0)).0;
|
||||||
if fancy {
|
if fancy {
|
||||||
Box::new(GraphicalReportHandler::new())
|
Box::new(GraphicalReportHandler::new().with_width(size))
|
||||||
} else {
|
} else {
|
||||||
Box::new(NarratableReportHandler)
|
Box::new(NarratableReportHandler)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ See [crate::set_hook] for more details on customizing your global printer.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct GraphicalReportHandler {
|
pub struct GraphicalReportHandler {
|
||||||
pub(crate) linkify_code: bool,
|
pub(crate) linkify_code: bool,
|
||||||
|
pub(crate) termwidth: usize,
|
||||||
pub(crate) theme: GraphicalTheme,
|
pub(crate) theme: GraphicalTheme,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,6 +31,7 @@ impl GraphicalReportHandler {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
linkify_code: true,
|
linkify_code: true,
|
||||||
|
termwidth: 200,
|
||||||
theme: GraphicalTheme::default(),
|
theme: GraphicalTheme::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +40,7 @@ impl GraphicalReportHandler {
|
||||||
pub fn new_themed(theme: GraphicalTheme) -> Self {
|
pub fn new_themed(theme: GraphicalTheme) -> Self {
|
||||||
Self {
|
Self {
|
||||||
linkify_code: true,
|
linkify_code: true,
|
||||||
|
termwidth: 200,
|
||||||
theme,
|
theme,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -47,6 +50,18 @@ impl GraphicalReportHandler {
|
||||||
self.linkify_code = false;
|
self.linkify_code = false;
|
||||||
self
|
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 {
|
impl Default for GraphicalReportHandler {
|
||||||
|
|
@ -66,6 +81,7 @@ impl GraphicalReportHandler {
|
||||||
diagnostic: &(dyn Diagnostic),
|
diagnostic: &(dyn Diagnostic),
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
self.render_header(f, diagnostic)?;
|
self.render_header(f, diagnostic)?;
|
||||||
|
writeln!(f)?;
|
||||||
self.render_causes(f, diagnostic)?;
|
self.render_causes(f, diagnostic)?;
|
||||||
|
|
||||||
if let Some(snippets) = diagnostic.snippets() {
|
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 {
|
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))?;
|
write!(f, "{}", self.theme.characters.hbar.to_string().repeat(4))?;
|
||||||
if self.linkify_code && diagnostic.url().is_some() && diagnostic.code().is_some() {
|
if self.linkify_code && diagnostic.url().is_some() && diagnostic.code().is_some() {
|
||||||
let url = diagnostic.url().unwrap(); // safe
|
let url = diagnostic.url().unwrap(); // safe
|
||||||
|
|
@ -100,24 +111,25 @@ impl GraphicalReportHandler {
|
||||||
write!(f, "[{}]", code.style(self.theme.styles.code))?;
|
write!(f, "[{}]", code.style(self.theme.styles.code))?;
|
||||||
}
|
}
|
||||||
writeln!(f, "{}", self.theme.characters.hbar.to_string().repeat(20),)?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_causes(&self, f: &mut impl fmt::Write, diagnostic: &(dyn Diagnostic)) -> fmt::Result {
|
fn render_causes(&self, f: &mut impl fmt::Write, diagnostic: &(dyn Diagnostic)) -> fmt::Result {
|
||||||
let severity_style = match diagnostic.severity() {
|
let (severity_style, severity_icon) = match diagnostic.severity() {
|
||||||
Some(Severity::Error) | None => self.theme.styles.error,
|
Some(Severity::Error) | None => (self.theme.styles.error, self.theme.characters.x),
|
||||||
Some(Severity::Warning) => self.theme.styles.warning,
|
Some(Severity::Warning) => (self.theme.styles.warning, self.theme.characters.warning),
|
||||||
Some(Severity::Advice) => self.theme.styles.advice,
|
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() {
|
if let Some(cause) = diagnostic.source() {
|
||||||
let mut cause_iter = Chain::new(cause).peekable();
|
let mut cause_iter = Chain::new(cause).peekable();
|
||||||
while let Some(error) = cause_iter.next() {
|
while let Some(error) = cause_iter.next() {
|
||||||
|
|
@ -135,7 +147,7 @@ impl GraphicalReportHandler {
|
||||||
let rest_indent = format!(" {} ", self.theme.characters.vbar)
|
let rest_indent = format!(" {} ", self.theme.characters.vbar)
|
||||||
.style(severity_style)
|
.style(severity_style)
|
||||||
.to_string();
|
.to_string();
|
||||||
let opts = textwrap::Options::new(80)
|
let opts = textwrap::Options::new(width)
|
||||||
.initial_indent(&initial_indent)
|
.initial_indent(&initial_indent)
|
||||||
.subsequent_indent(&rest_indent);
|
.subsequent_indent(&rest_indent);
|
||||||
writeln!(f, "{}", textwrap::fill(&error.to_string(), opts))?;
|
writeln!(f, "{}", textwrap::fill(&error.to_string(), opts))?;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ fn fmt_report(diag: Report) -> String {
|
||||||
// Mostly for dev purposes.
|
// Mostly for dev purposes.
|
||||||
if std::env::var("STYLE").is_ok() {
|
if std::env::var("STYLE").is_ok() {
|
||||||
GraphicalReportHandler::new_themed(GraphicalTheme::unicode())
|
GraphicalReportHandler::new_themed(GraphicalTheme::unicode())
|
||||||
|
.with_width(80)
|
||||||
.render_report(&mut out, diag.as_ref())
|
.render_report(&mut out, diag.as_ref())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else if std::env::var("NARRATED").is_ok() {
|
} else if std::env::var("NARRATED").is_ok() {
|
||||||
|
|
@ -17,6 +18,7 @@ fn fmt_report(diag: Report) -> String {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor())
|
GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor())
|
||||||
|
.with_width(80)
|
||||||
.render_report(&mut out, diag.as_ref())
|
.render_report(&mut out, diag.as_ref())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue