Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 30 additions & 47 deletions src/handlers/graphical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,17 +262,7 @@ impl GraphicalReportHandler {
if let Some(footer) = &self.footer {
writeln!(f)?;
let width = self.termwidth.saturating_sub(2);
let mut opts = textwrap::Options::new(width)
.initial_indent(" ")
.subsequent_indent(" ")
.break_words(self.break_words);
if let Some(word_separator) = self.word_separator {
opts = opts.word_separator(word_separator);
}
if let Some(word_splitter) = self.word_splitter.clone() {
opts = opts.word_splitter(word_splitter);
}

let opts = self.textwrap_options(width);
writeln!(f, "{}", self.wrap(footer, opts))?;
}
Ok(())
Expand Down Expand Up @@ -340,16 +330,10 @@ impl GraphicalReportHandler {
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(2);
let mut opts = textwrap::Options::new(width)
let opts = self
.textwrap_options(width)
.initial_indent(&initial_indent)
.subsequent_indent(&rest_indent)
.break_words(self.break_words);
if let Some(word_separator) = self.word_separator {
opts = opts.word_separator(word_separator);
}
if let Some(word_splitter) = self.word_splitter.clone() {
opts = opts.word_splitter(word_splitter);
}
.subsequent_indent(&rest_indent);

writeln!(f, "{}", self.wrap(&diagnostic.to_string(), opts))?;

Expand Down Expand Up @@ -386,16 +370,10 @@ impl GraphicalReportHandler {
)
.style(severity_style)
.to_string();
let mut opts = textwrap::Options::new(width)
let opts = self
.textwrap_options(width)
.initial_indent(&initial_indent)
.subsequent_indent(&rest_indent)
.break_words(self.break_words);
if let Some(word_separator) = self.word_separator {
opts = opts.word_separator(word_separator);
}
if let Some(word_splitter) = self.word_splitter.clone() {
opts = opts.word_splitter(word_splitter);
}
.subsequent_indent(&rest_indent);

match error {
ErrorKind::Diagnostic(diag) => {
Expand Down Expand Up @@ -428,16 +406,10 @@ impl GraphicalReportHandler {
if let Some(help) = diagnostic.help() {
let width = self.termwidth.saturating_sub(2);
let initial_indent = " help: ".style(self.theme.styles.help).to_string();
let mut opts = textwrap::Options::new(width)
let opts = self
.textwrap_options(width)
.initial_indent(&initial_indent)
.subsequent_indent(" ")
.break_words(self.break_words);
if let Some(word_separator) = self.word_separator {
opts = opts.word_separator(word_separator);
}
if let Some(word_splitter) = self.word_splitter.clone() {
opts = opts.word_splitter(word_splitter);
}
.subsequent_indent(" ");

writeln!(f, "{}", self.wrap(&help.to_string(), opts))?;
}
Expand Down Expand Up @@ -489,16 +461,10 @@ impl GraphicalReportHandler {
.style(severity_style)
.to_string();

let mut opts = textwrap::Options::new(width)
let opts = self
.textwrap_options(width)
.initial_indent(&initial_indent)
.subsequent_indent(&rest_indent)
.break_words(self.break_words);
if let Some(word_separator) = self.word_separator {
opts = opts.word_separator(word_separator);
}
if let Some(word_splitter) = self.word_splitter.clone() {
opts = opts.word_splitter(word_splitter);
}
.subsequent_indent(&rest_indent);

let mut inner = String::new();

Expand Down Expand Up @@ -1358,6 +1324,23 @@ impl GraphicalReportHandler {
}
Ok((context_data, lines))
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it might be a pessimization? It's cloning the word separate and splitter regardless of whether they changed., and it saves very few lines.
I agree there's probably a bit more elegant of a pattern in here somewhere, but personally (though my opinion doesn't matter, I'm not the creator nor maintainer), this doesn't seem better, it just seems less direct.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that correct? I think these are all cloned at the use-sites in the code before this change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the splitter was cloned before, I think? now both are.

Copy link
Contributor

@cgettys-microsoft cgettys-microsoft Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And initial_indent and subsequent_indent are called twice in some cases after this change.

Copy link
Contributor

@cgettys-microsoft cgettys-microsoft Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I almost wonder if a better approach would be to have this method return a textwrap::Options with the width, separator, splitter, and break_words populated, and the rest left to the call site. That'd fix the multiple initial_indent and subsequent_indent call problems.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe have GraphicalReportHandler keep an instance of textwrap::Options within itself, rather than keeping the separator and splitter and break words separately? idk, just brainstorming.

fn textwrap_options(&self, width: usize) -> textwrap::Options<'static> {
textwrap::Options::new(width)
.initial_indent(" ")
.subsequent_indent(" ")
.word_separator(
self.word_separator
.clone()
.unwrap_or(textwrap::WordSeparator::AsciiSpace),
)
.word_splitter(
self.word_splitter
.clone()
.unwrap_or(textwrap::WordSplitter::NoHyphenation),
)
.break_words(self.break_words)
}
}

impl ReportHandler for GraphicalReportHandler {
Expand Down