switch to termcolor

This commit is contained in:
Pietro Albini 2023-03-07 10:21:25 +01:00
parent 3248ab758a
commit c015d0d2fa
No known key found for this signature in database
GPG key ID: CD76B35F7734769E
4 changed files with 82 additions and 51 deletions

View file

@ -67,11 +67,11 @@ dependencies = [
"sha2",
"sysinfo",
"tar",
"termcolor",
"toml",
"walkdir",
"winapi",
"xz2",
"yansi-term",
]
[[package]]
@ -649,6 +649,15 @@ dependencies = [
"xattr",
]
[[package]]
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"winapi-util",
]
[[package]]
name = "thread_local"
version = "1.1.4"
@ -813,12 +822,3 @@ name = "yansi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]]
name = "yansi-term"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1"
dependencies = [
"winapi",
]

View file

@ -47,13 +47,13 @@ serde_derive = "1.0.137"
serde_json = "1.0.2"
sha2 = "0.10"
tar = "0.4"
termcolor = "1.2.0"
toml = "0.5"
ignore = "0.4.10"
opener = "0.5"
once_cell = "1.7.2"
xz2 = "0.1"
walkdir = "2"
yansi-term = "0.1.2"
# Dependencies needed by the build-metrics feature
sysinfo = { version = "0.26.0", optional = true }

View file

@ -89,7 +89,7 @@ pub use crate::builder::PathSet;
use crate::cache::{Interned, INTERNER};
pub use crate::config::Config;
pub use crate::flags::Subcommand;
use yansi_term::Color;
use termcolor::{ColorChoice, StandardStream, WriteColor};
const LLVM_TOOLS: &[&str] = &[
"llvm-cov", // used to generate coverage report
@ -1577,21 +1577,29 @@ to download LLVM rather than building it.
self.config.ninja_in_file
}
pub fn color_for_stdout(&self, color: Color, message: &str) -> String {
self.color_for_inner(color, message, self.config.stdout_is_tty)
pub fn colored_stdout<R, F: FnOnce(&mut dyn WriteColor) -> R>(&self, f: F) -> R {
self.colored_stream_inner(StandardStream::stdout, self.config.stdout_is_tty, f)
}
pub fn color_for_stderr(&self, color: Color, message: &str) -> String {
self.color_for_inner(color, message, self.config.stderr_is_tty)
pub fn colored_stderr<R, F: FnOnce(&mut dyn WriteColor) -> R>(&self, f: F) -> R {
self.colored_stream_inner(StandardStream::stderr, self.config.stderr_is_tty, f)
}
fn color_for_inner(&self, color: Color, message: &str, is_tty: bool) -> String {
let use_color = match self.config.color {
flags::Color::Always => true,
flags::Color::Never => false,
flags::Color::Auto => is_tty,
fn colored_stream_inner<R, F, C>(&self, constructor: C, is_tty: bool, f: F) -> R
where
C: Fn(ColorChoice) -> StandardStream,
F: FnOnce(&mut dyn WriteColor) -> R,
{
let choice = match self.config.color {
flags::Color::Always => ColorChoice::Always,
flags::Color::Never => ColorChoice::Never,
flags::Color::Auto if !is_tty => ColorChoice::Never,
flags::Color::Auto => ColorChoice::Auto,
};
if use_color { color.paint(message).to_string() } else { message.to_string() }
let mut stream = constructor(choice);
let result = f(&mut stream);
stream.reset().unwrap();
result
}
}

View file

@ -10,7 +10,7 @@ use crate::builder::Builder;
use std::io::{BufRead, BufReader, Write};
use std::process::{ChildStdout, Command, Stdio};
use std::time::Duration;
use yansi_term::Color;
use termcolor::{Color, ColorSpec, WriteColor};
const TERSE_TESTS_PER_LINE: usize = 88;
@ -139,16 +139,12 @@ impl<'a> Renderer<'a> {
}
fn render_test_outcome_verbose(&self, outcome: Outcome<'_>, test: &TestOutcome) {
print!("test {} ... ", test.name);
self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap();
if let Some(exec_time) = test.exec_time {
println!(
"test {} ... {} (in {:.2?})",
test.name,
outcome.long(self.builder),
Duration::from_secs_f64(exec_time)
);
} else {
println!("test {} ... {}", test.name, outcome.long(self.builder));
print!(" ({exec_time:.2?})");
}
println!();
}
fn render_test_outcome_terse(&mut self, outcome: Outcome<'_>, _: &TestOutcome) {
@ -163,7 +159,7 @@ impl<'a> Renderer<'a> {
}
self.terse_tests_in_line += 1;
print!("{}", outcome.short(self.builder));
self.builder.colored_stdout(|stdout| outcome.write_short(stdout)).unwrap();
let _ = std::io::stdout().flush();
}
@ -208,10 +204,11 @@ impl<'a> Renderer<'a> {
}
}
print!("\ntest result: ");
self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap();
println!(
"\ntest result: {}. {} passed; {} failed; {} ignored; {} measured; \
{} filtered out; finished in {:.2?}\n",
outcome.long(self.builder),
". {} passed; {} failed; {} ignored; {} measured; {} filtered out; \
finished in {:.2?}\n",
suite.passed,
suite.failed,
suite.ignored,
@ -276,25 +273,51 @@ enum Outcome<'a> {
}
impl Outcome<'_> {
fn short(&self, builder: &Builder<'_>) -> String {
fn write_short(&self, writer: &mut dyn WriteColor) -> Result<(), std::io::Error> {
match self {
Outcome::Ok => builder.color_for_stdout(Color::Green, "."),
Outcome::BenchOk => builder.color_for_stdout(Color::Cyan, "b"),
Outcome::Failed => builder.color_for_stdout(Color::Red, "F"),
Outcome::Ignored { .. } => builder.color_for_stdout(Color::Yellow, "i"),
}
}
fn long(&self, builder: &Builder<'_>) -> String {
match self {
Outcome::Ok => builder.color_for_stdout(Color::Green, "ok"),
Outcome::BenchOk => builder.color_for_stdout(Color::Cyan, "benchmarked"),
Outcome::Failed => builder.color_for_stdout(Color::Red, "FAILED"),
Outcome::Ignored { reason: None } => builder.color_for_stdout(Color::Yellow, "ignored"),
Outcome::Ignored { reason: Some(reason) } => {
builder.color_for_stdout(Color::Yellow, &format!("ignored, {reason}"))
Outcome::Ok => {
writer.set_color(&ColorSpec::new().set_fg(Some(Color::Green)))?;
write!(writer, ".")?;
}
Outcome::BenchOk => {
writer.set_color(&ColorSpec::new().set_fg(Some(Color::Cyan)))?;
write!(writer, "b")?;
}
Outcome::Failed => {
writer.set_color(&ColorSpec::new().set_fg(Some(Color::Red)))?;
write!(writer, "F")?;
}
Outcome::Ignored { .. } => {
writer.set_color(&ColorSpec::new().set_fg(Some(Color::Yellow)))?;
write!(writer, "i")?;
}
}
writer.reset()
}
fn write_long(&self, writer: &mut dyn WriteColor) -> Result<(), std::io::Error> {
match self {
Outcome::Ok => {
writer.set_color(&ColorSpec::new().set_fg(Some(Color::Green)))?;
write!(writer, "ok")?;
}
Outcome::BenchOk => {
writer.set_color(&ColorSpec::new().set_fg(Some(Color::Cyan)))?;
write!(writer, "benchmarked")?;
}
Outcome::Failed => {
writer.set_color(&ColorSpec::new().set_fg(Some(Color::Red)))?;
write!(writer, "FAILED")?;
}
Outcome::Ignored { reason } => {
writer.set_color(&ColorSpec::new().set_fg(Some(Color::Yellow)))?;
write!(writer, "ignored")?;
if let Some(reason) = reason {
write!(writer, ", {reason}")?;
}
}
}
writer.reset()
}
}