Skip to content

Commit 926d453

Browse files
committed
refactor: Move to anstream + anstyle for styling
1 parent bd4a800 commit 926d453

File tree

14 files changed

+166
-203
lines changed

14 files changed

+166
-203
lines changed

Cargo.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ dependencies = [
9595

9696
[[package]]
9797
name = "anstyle"
98-
version = "1.0.11"
98+
version = "1.0.13"
9999
source = "registry+https://github.com/rust-lang/crates.io-index"
100-
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
100+
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
101101

102102
[[package]]
103103
name = "anstyle-lossy"
@@ -3757,6 +3757,8 @@ name = "rustc_errors"
37573757
version = "0.0.0"
37583758
dependencies = [
37593759
"annotate-snippets 0.11.5",
3760+
"anstream",
3761+
"anstyle",
37603762
"derive_setters",
37613763
"rustc_abi",
37623764
"rustc_ast",
@@ -3773,7 +3775,6 @@ dependencies = [
37733775
"rustc_span",
37743776
"serde",
37753777
"serde_json",
3776-
"termcolor",
37773778
"termize",
37783779
"tracing",
37793780
"windows 0.61.3",
@@ -4327,7 +4328,6 @@ dependencies = [
43274328
"rustc_macros",
43284329
"rustc_session",
43294330
"rustc_span",
4330-
"termcolor",
43314331
"thin-vec",
43324332
"tracing",
43334333
"unicode-normalization",

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -521,11 +521,11 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) {
521521
};
522522

523523
// Try to prettify the raw markdown text. The result can be used by the pager or on stdout.
524-
let pretty_data = {
524+
let mut pretty_data = {
525525
let mdstream = markdown::MdStream::parse_str(content);
526526
let bufwtr = markdown::create_stdout_bufwtr();
527-
let mut mdbuf = bufwtr.buffer();
528-
if mdstream.write_termcolor_buf(&mut mdbuf).is_ok() { Some((bufwtr, mdbuf)) } else { None }
527+
let mut mdbuf = Vec::new();
528+
if mdstream.write_anstream_buf(&mut mdbuf).is_ok() { Some((bufwtr, mdbuf)) } else { None }
529529
};
530530

531531
// Try to print via the pager, pretty output if possible.
@@ -546,8 +546,8 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) {
546546
}
547547

548548
// The pager failed. Try to print pretty output to stdout.
549-
if let Some((bufwtr, mdbuf)) = &pretty_data
550-
&& bufwtr.print(mdbuf).is_ok()
549+
if let Some((bufwtr, mdbuf)) = &mut pretty_data
550+
&& bufwtr.write_all(&mdbuf).is_ok()
551551
{
552552
return;
553553
}

compiler/rustc_errors/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ edition = "2024"
66
[dependencies]
77
# tidy-alphabetical-start
88
annotate-snippets = "0.11"
9+
anstream = "0.6.20"
10+
anstyle = "1.0.13"
911
derive_setters = "0.1.6"
1012
rustc_abi = { path = "../rustc_abi" }
1113
rustc_ast = { path = "../rustc_ast" }
@@ -22,7 +24,6 @@ rustc_serialize = { path = "../rustc_serialize" }
2224
rustc_span = { path = "../rustc_span" }
2325
serde = { version = "1.0.125", features = ["derive"] }
2426
serde_json = "1.0.59"
25-
termcolor = "1.2.0"
2627
termize = "0.2"
2728
tracing = "0.1"
2829
# tidy-alphabetical-end

compiler/rustc_errors/src/emitter.rs

Lines changed: 43 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ use std::iter;
1616
use std::path::Path;
1717
use std::sync::Arc;
1818

19+
use anstream::{AutoStream, ColorChoice};
20+
use anstyle::{Ansi256Color, AnsiColor, Effects};
1921
use derive_setters::Setters;
2022
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2123
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
@@ -25,7 +27,6 @@ use rustc_lint_defs::pluralize;
2527
use rustc_span::hygiene::{ExpnKind, MacroKind};
2628
use rustc_span::source_map::SourceMap;
2729
use rustc_span::{FileLines, FileName, SourceFile, Span, char_width, str_width};
28-
use termcolor::{Buffer, BufferWriter, Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
2930
use tracing::{debug, instrument, trace, warn};
3031

3132
use crate::registry::Registry;
@@ -525,10 +526,6 @@ impl Emitter for HumanEmitter {
525526
!self.short_message
526527
}
527528

528-
fn supports_color(&self) -> bool {
529-
self.dst.supports_color()
530-
}
531-
532529
fn translator(&self) -> &Translator {
533530
&self.translator
534531
}
@@ -1701,7 +1698,6 @@ impl HumanEmitter {
17011698
} else {
17021699
col_sep_before_no_show_source = true;
17031700
}
1704-
17051701
// print out the span location and spacer before we print the annotated source
17061702
// to do this, we need to know if this span will be primary
17071703
let is_primary = primary_lo.file.name == annotated_file.file.name;
@@ -3127,7 +3123,6 @@ impl FileWithAnnotatedLines {
31273123
multiline_depth: 0,
31283124
});
31293125
}
3130-
31313126
let mut output = vec![];
31323127
let mut multiline_annotations = vec![];
31333128

@@ -3361,7 +3356,7 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
33613356
('\u{2069}', "�"),
33623357
];
33633358

3364-
fn normalize_whitespace(s: &str) -> String {
3359+
pub(crate) fn normalize_whitespace(s: &str) -> String {
33653360
const {
33663361
let mut i = 1;
33673362
while i < OUTPUT_REPLACEMENTS.len() {
@@ -3406,13 +3401,14 @@ fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool {
34063401
)
34073402
}
34083403

3409-
fn emit_to_destination(
3404+
pub(crate) fn emit_to_destination(
34103405
rendered_buffer: &[Vec<StyledString>],
34113406
lvl: &Level,
34123407
dst: &mut Destination,
34133408
short_message: bool,
34143409
) -> io::Result<()> {
34153410
use crate::lock;
3411+
const RESET: anstyle::Reset = anstyle::Reset;
34163412

34173413
// In order to prevent error message interleaving, where multiple error lines get intermixed
34183414
// when multiple compiler processes error simultaneously, we emit errors with additional
@@ -3429,10 +3425,8 @@ fn emit_to_destination(
34293425
let _buffer_lock = lock::acquire_global_lock("rustc_errors");
34303426
for (pos, line) in rendered_buffer.iter().enumerate() {
34313427
for part in line {
3432-
let style = part.style.color_spec(*lvl);
3433-
dst.set_color(&style)?;
3434-
write!(dst, "{}", part.text)?;
3435-
dst.reset()?;
3428+
let style = part.style.anstyle(*lvl);
3429+
write!(dst, "{RESET}{style}{}{RESET}", part.text)?;
34363430
}
34373431
if !short_message && (!lvl.is_failure_note() || pos != rendered_buffer.len() - 1) {
34383432
writeln!(dst)?;
@@ -3442,11 +3436,11 @@ fn emit_to_destination(
34423436
Ok(())
34433437
}
34443438

3445-
pub type Destination = Box<dyn WriteColor + Send>;
3439+
pub type Destination = AutoStream<Box<dyn Write + Send>>;
34463440

34473441
struct Buffy {
3448-
buffer_writer: BufferWriter,
3449-
buffer: Buffer,
3442+
buffer_writer: std::io::Stderr,
3443+
buffer: Vec<u8>,
34503444
}
34513445

34523446
impl Write for Buffy {
@@ -3455,7 +3449,7 @@ impl Write for Buffy {
34553449
}
34563450

34573451
fn flush(&mut self) -> io::Result<()> {
3458-
self.buffer_writer.print(&self.buffer)?;
3452+
self.buffer_writer.write_all(&self.buffer)?;
34593453
self.buffer.clear();
34603454
Ok(())
34613455
}
@@ -3470,83 +3464,59 @@ impl Drop for Buffy {
34703464
}
34713465
}
34723466

3473-
impl WriteColor for Buffy {
3474-
fn supports_color(&self) -> bool {
3475-
self.buffer.supports_color()
3476-
}
3477-
3478-
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
3479-
self.buffer.set_color(spec)
3480-
}
3481-
3482-
fn reset(&mut self) -> io::Result<()> {
3483-
self.buffer.reset()
3484-
}
3485-
}
3486-
34873467
pub fn stderr_destination(color: ColorConfig) -> Destination {
3468+
let buffer_writer = std::io::stderr();
34883469
let choice = color.to_color_choice();
3470+
// We need to resolve `ColorChoice::Auto` before `Box`ing since
3471+
// `ColorChoice::Auto` on `dyn Write` will always resolve to `Never`
3472+
let choice = if matches!(choice, ColorChoice::Auto) {
3473+
AutoStream::choice(&buffer_writer)
3474+
} else {
3475+
choice
3476+
};
34893477
// On Windows we'll be performing global synchronization on the entire
34903478
// system for emitting rustc errors, so there's no need to buffer
34913479
// anything.
34923480
//
34933481
// On non-Windows we rely on the atomicity of `write` to ensure errors
34943482
// don't get all jumbled up.
34953483
if cfg!(windows) {
3496-
Box::new(StandardStream::stderr(choice))
3484+
AutoStream::new(Box::new(buffer_writer), choice)
34973485
} else {
3498-
let buffer_writer = BufferWriter::stderr(choice);
3499-
let buffer = buffer_writer.buffer();
3500-
Box::new(Buffy { buffer_writer, buffer })
3486+
let buffer = Vec::new();
3487+
AutoStream::new(Box::new(Buffy { buffer_writer, buffer }), choice)
35013488
}
35023489
}
35033490

35043491
/// On Windows, BRIGHT_BLUE is hard to read on black. Use cyan instead.
35053492
///
35063493
/// See #36178.
3507-
const BRIGHT_BLUE: Color = if cfg!(windows) { Color::Cyan } else { Color::Blue };
3494+
const BRIGHT_BLUE: anstyle::Style = if cfg!(windows) {
3495+
Ansi256Color::from_ansi(AnsiColor::BrightCyan).on_default()
3496+
} else {
3497+
Ansi256Color::from_ansi(AnsiColor::BrightBlue).on_default()
3498+
};
35083499

35093500
impl Style {
3510-
fn color_spec(&self, lvl: Level) -> ColorSpec {
3511-
let mut spec = ColorSpec::new();
3501+
pub(crate) fn anstyle(&self, lvl: Level) -> anstyle::Style {
35123502
match self {
3513-
Style::Addition => {
3514-
spec.set_fg(Some(Color::Green)).set_intense(true);
3515-
}
3516-
Style::Removal => {
3517-
spec.set_fg(Some(Color::Red)).set_intense(true);
3518-
}
3519-
Style::LineAndColumn => {}
3520-
Style::LineNumber => {
3521-
spec.set_bold(true);
3522-
spec.set_intense(true);
3523-
spec.set_fg(Some(BRIGHT_BLUE));
3524-
}
3525-
Style::Quotation => {}
3526-
Style::MainHeaderMsg => {
3527-
spec.set_bold(true);
3528-
if cfg!(windows) {
3529-
spec.set_intense(true).set_fg(Some(Color::White));
3530-
}
3531-
}
3532-
Style::UnderlinePrimary | Style::LabelPrimary => {
3533-
spec = lvl.color();
3534-
spec.set_bold(true);
3535-
}
3536-
Style::UnderlineSecondary | Style::LabelSecondary => {
3537-
spec.set_bold(true).set_intense(true);
3538-
spec.set_fg(Some(BRIGHT_BLUE));
3539-
}
3540-
Style::HeaderMsg | Style::NoStyle => {}
3541-
Style::Level(lvl) => {
3542-
spec = lvl.color();
3543-
spec.set_bold(true);
3544-
}
3545-
Style::Highlight => {
3546-
spec.set_bold(true).set_fg(Some(Color::Magenta));
3503+
Style::Addition => Ansi256Color::from_ansi(AnsiColor::BrightGreen).on_default(),
3504+
Style::Removal => Ansi256Color::from_ansi(AnsiColor::BrightRed).on_default(),
3505+
Style::LineAndColumn => anstyle::Style::new(),
3506+
Style::LineNumber => BRIGHT_BLUE.effects(Effects::BOLD),
3507+
Style::Quotation => anstyle::Style::new(),
3508+
Style::MainHeaderMsg => if cfg!(windows) {
3509+
Ansi256Color::from_ansi(AnsiColor::BrightWhite).on_default()
3510+
} else {
3511+
anstyle::Style::new()
35473512
}
3513+
.effects(Effects::BOLD),
3514+
Style::UnderlinePrimary | Style::LabelPrimary => lvl.color().effects(Effects::BOLD),
3515+
Style::UnderlineSecondary | Style::LabelSecondary => BRIGHT_BLUE.effects(Effects::BOLD),
3516+
Style::HeaderMsg | Style::NoStyle => anstyle::Style::new(),
3517+
Style::Level(lvl) => lvl.color().effects(Effects::BOLD),
3518+
Style::Highlight => AnsiColor::Magenta.on_default().effects(Effects::BOLD),
35483519
}
3549-
spec
35503520
}
35513521
}
35523522

compiler/rustc_errors/src/json.rs

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use std::path::Path;
1515
use std::sync::{Arc, Mutex};
1616
use std::vec;
1717

18+
use anstream::{AutoStream, ColorChoice};
1819
use derive_setters::Setters;
1920
use rustc_data_structures::sync::IntoDynSyncSend;
2021
use rustc_error_messages::FluentArgs;
@@ -23,7 +24,6 @@ use rustc_span::Span;
2324
use rustc_span::hygiene::ExpnData;
2425
use rustc_span::source_map::{FilePathMapping, SourceMap};
2526
use serde::Serialize;
26-
use termcolor::{ColorSpec, WriteColor};
2727

2828
use crate::diagnostic::IsLint;
2929
use crate::emitter::{
@@ -333,7 +333,7 @@ impl Diagnostic {
333333
// generate regular command line output and store it in the json
334334

335335
// A threadsafe buffer for writing.
336-
#[derive(Default, Clone)]
336+
#[derive(Clone)]
337337
struct BufWriter(Arc<Mutex<Vec<u8>>>);
338338

339339
impl Write for BufWriter {
@@ -344,19 +344,6 @@ impl Diagnostic {
344344
self.0.lock().unwrap().flush()
345345
}
346346
}
347-
impl WriteColor for BufWriter {
348-
fn supports_color(&self) -> bool {
349-
false
350-
}
351-
352-
fn set_color(&mut self, _spec: &ColorSpec) -> io::Result<()> {
353-
Ok(())
354-
}
355-
356-
fn reset(&mut self) -> io::Result<()> {
357-
Ok(())
358-
}
359-
}
360347

361348
let translated_message = je.translator.translate_messages(&diag.messages, &args);
362349

@@ -382,13 +369,15 @@ impl Diagnostic {
382369
children
383370
.insert(0, Diagnostic::from_sub_diagnostic(&diag.emitted_at_sub_diag(), &args, je));
384371
}
385-
let buf = BufWriter::default();
386-
let mut dst: Destination = Box::new(buf.clone());
372+
let buf = BufWriter(Arc::new(Mutex::new(Vec::new())));
387373
let short = je.json_rendered.short();
388-
match je.color_config {
389-
ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)),
390-
ColorConfig::Never => {}
391-
}
374+
let dst: Destination = AutoStream::new(
375+
Box::new(buf.clone()),
376+
match je.color_config.to_color_choice() {
377+
ColorChoice::Auto => ColorChoice::Always,
378+
choice => choice,
379+
},
380+
);
392381
HumanEmitter::new(dst, je.translator.clone())
393382
.short_message(short)
394383
.sm(je.sm.clone())

0 commit comments

Comments
 (0)