Skip to content

Commit 5c50766

Browse files
committed
Print error messages with colors if possible
1 parent 67285f1 commit 5c50766

File tree

1 file changed

+80
-2
lines changed

1 file changed

+80
-2
lines changed

src/lib.rs

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use checkstyle::{output_footer, output_header};
4343
use config::Config;
4444
use filemap::FileMap;
4545
use issues::{BadIssueSeeker, Issue};
46-
use utils::{mk_sp, outer_attributes};
46+
use utils::{isatty, mk_sp, outer_attributes};
4747
use visitor::FmtVisitor;
4848

4949
pub use self::summary::Summary;
@@ -532,6 +532,76 @@ impl FormatReport {
532532
pub fn has_warnings(&self) -> bool {
533533
self.warning_count() > 0
534534
}
535+
536+
pub fn print_warnings_fancy(
537+
&self,
538+
mut t: Box<term::Terminal<Output = io::Stderr>>,
539+
) -> Result<(), term::Error> {
540+
for (file, errors) in &self.file_error_map {
541+
for error in errors {
542+
let prefix_space_len = error.line.to_string().len();
543+
let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect();
544+
545+
// First line: the overview of error
546+
t.fg(term::color::RED)?;
547+
t.attr(term::Attr::Bold)?;
548+
write!(t, "{} ", error.msg_prefix())?;
549+
t.reset()?;
550+
t.attr(term::Attr::Bold)?;
551+
write!(t, "{}\n", error.kind)?;
552+
553+
// Second line: file info
554+
write!(t, "{}--> ", &prefix_spaces[1..])?;
555+
t.reset()?;
556+
write!(t, "{}:{}\n", file, error.line)?;
557+
558+
// Third to fifth lines: show the line which triggered error, if available.
559+
if !error.line_buffer.is_empty() {
560+
let (space_len, target_len) = error.format_len();
561+
t.attr(term::Attr::Bold)?;
562+
write!(t, "{}|\n{} | ", prefix_spaces, error.line)?;
563+
t.reset()?;
564+
write!(t, "{}\n", error.line_buffer)?;
565+
t.attr(term::Attr::Bold)?;
566+
write!(t, "{}| ", prefix_spaces)?;
567+
t.fg(term::color::RED)?;
568+
write!(t, "{}\n", target_str(space_len, target_len))?;
569+
t.reset()?;
570+
}
571+
572+
// The last line: show note if available.
573+
let msg_suffix = error.msg_suffix();
574+
if !msg_suffix.is_empty() {
575+
t.attr(term::Attr::Bold)?;
576+
write!(t, "{}= note: ", prefix_spaces)?;
577+
t.reset()?;
578+
write!(t, "{}\n", error.msg_suffix())?;
579+
} else {
580+
write!(t, "\n")?;
581+
}
582+
t.reset()?;
583+
}
584+
}
585+
586+
if !self.file_error_map.is_empty() {
587+
t.attr(term::Attr::Bold)?;
588+
write!(t, "warning: ")?;
589+
t.reset()?;
590+
write!(
591+
t,
592+
"rustfmt may have failed to format. See previous {} errors.\n\n",
593+
self.warning_count(),
594+
)?;
595+
}
596+
597+
Ok(())
598+
}
599+
}
600+
601+
fn target_str(space_len: usize, target_len: usize) -> String {
602+
let empty_line: String = repeat(" ").take(space_len).collect();
603+
let overflowed: String = repeat("^").take(target_len).collect();
604+
empty_line + &overflowed
535605
}
536606

537607
impl fmt::Display for FormatReport {
@@ -867,7 +937,15 @@ pub fn run(input: Input, config: &Config) -> Summary {
867937
output_footer(out, config.write_mode()).ok();
868938

869939
if report.has_warnings() {
870-
msg!("{}", report);
940+
match term::stderr() {
941+
Some(ref t) if isatty() && t.supports_color() => {
942+
match report.print_warnings_fancy(term::stderr().unwrap()) {
943+
Ok(..) => (),
944+
Err(..) => panic!("Unable to write to stderr: {}", report),
945+
}
946+
}
947+
_ => msg!("{}", report),
948+
}
871949
}
872950

873951
summary

0 commit comments

Comments
 (0)