From 74a44d9fcb95e14854d8d4c1f724ff606ae65d0c Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 28 Sep 2023 16:50:29 -0500 Subject: [PATCH] refactor(shell): Switch termcolor to anstream --- Cargo.lock | 32 --------- Cargo.toml | 8 --- src/cargo/core/shell.rs | 144 ++++++++++++++-------------------------- 3 files changed, 50 insertions(+), 134 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5515b306e8fb..84db9a1ad3e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,16 +61,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "anstyle-termcolor" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c3d1411f1f4c8a7b177caec3c71b51290f9e8ad9f99124fd3fe9aa96e56834" -dependencies = [ - "anstyle", - "termcolor", -] - [[package]] name = "anstyle-wincon" version = "3.0.1" @@ -248,7 +238,6 @@ version = "0.75.0" dependencies = [ "anstream", "anstyle", - "anstyle-termcolor", "anyhow", "base64", "bytesize", @@ -267,7 +256,6 @@ dependencies = [ "curl-sys", "filetime", "flate2", - "fwdansi", "git2", "git2-curl", "gix", @@ -308,7 +296,6 @@ dependencies = [ "syn 2.0.29", "tar", "tempfile", - "termcolor", "time", "toml", "toml_edit", @@ -993,16 +980,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fwdansi" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c1f5787fe85505d1f7777268db5103d80a7a374d2316a7ce262e57baf8f208" -dependencies = [ - "memchr", - "termcolor", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -3181,15 +3158,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - [[package]] name = "terminal_size" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index ae066a2d24b4..42e68e95c163 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,6 @@ license = "MIT OR Apache-2.0" [workspace.dependencies] anstream = "0.6.3" anstyle = "1.0.4" -anstyle-termcolor = "1.1.0" anyhow = "1.0.75" base64 = "0.21.3" bytesize = "1.3" @@ -41,7 +40,6 @@ curl = "0.4.44" curl-sys = "0.4.66" filetime = "0.2.22" flate2 = { version = "1.0.27", default-features = false, features = ["zlib"] } -fwdansi = "1.1.0" git2 = "0.18.0" git2-curl = "0.19.0" gix = { version = "0.54.1", default-features = false, features = ["blocking-http-transport-curl", "progress-tree", "revision"] } @@ -91,7 +89,6 @@ snapbox = { version = "0.4.13", features = ["diff", "path"] } syn = { version = "2.0.29", features = ["extra-traits", "full"] } tar = { version = "0.4.40", default-features = false } tempfile = "3.8.0" -termcolor = "1.2.0" thiserror = "1.0.47" time = { version = "0.3", features = ["parsing", "formatting", "serde"] } toml = "0.7.6" @@ -124,7 +121,6 @@ path = "src/cargo/lib.rs" [dependencies] anstream.workspace = true -anstyle-termcolor.workspace = true anstyle.workspace = true anyhow.workspace = true base64.workspace = true @@ -179,7 +175,6 @@ shell-escape.workspace = true syn.workspace = true tar.workspace = true tempfile.workspace = true -termcolor.workspace = true time.workspace = true toml.workspace = true toml_edit.workspace = true @@ -194,9 +189,6 @@ walkdir.workspace = true [target.'cfg(not(windows))'.dependencies] openssl = { workspace = true, optional = true } -[target.'cfg(windows)'.dependencies] -fwdansi.workspace = true - [target.'cfg(windows)'.dependencies.windows-sys] workspace = true features = [ diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index 375dc9b82ff9..306ac76ff454 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -2,9 +2,8 @@ use std::fmt; use std::io::prelude::*; use std::io::IsTerminal; +use anstream::AutoStream; use anstyle::Style; -use anstyle_termcolor::to_termcolor_spec; -use termcolor::{self, BufferWriter, StandardStream, WriteColor}; use crate::util::errors::CargoResult; use crate::util::style::*; @@ -86,10 +85,8 @@ enum ShellOut { /// corresponding stream. The non-buffered fields should be used when you /// do not want content to be buffered. Stream { - stdout: StandardStream, - buffered_stdout: BufferWriter, - stderr: StandardStream, - buffered_stderr: BufferWriter, + stdout: AutoStream, + stderr: AutoStream, stderr_tty: bool, color_choice: ColorChoice, }, @@ -111,15 +108,13 @@ impl Shell { /// output. pub fn new() -> Shell { let auto_clr = ColorChoice::CargoAuto; - let stdout_choice = auto_clr.to_termcolor_color_choice(Stream::Stdout); - let stderr_choice = auto_clr.to_termcolor_color_choice(Stream::Stderr); + let stdout_choice = auto_clr.to_anstream_color_choice(); + let stderr_choice = auto_clr.to_anstream_color_choice(); Shell { output: ShellOut::Stream { - stdout: StandardStream::stdout(stdout_choice), - buffered_stdout: BufferWriter::stdout(stdout_choice), - stderr: StandardStream::stderr(stderr_choice), - buffered_stderr: BufferWriter::stderr(stderr_choice), - color_choice: ColorChoice::CargoAuto, + stdout: AutoStream::new(std::io::stdout(), stdout_choice), + stderr: AutoStream::new(std::io::stderr(), stderr_choice), + color_choice: auto_clr, stderr_tty: std::io::stderr().is_terminal(), }, verbosity: Verbosity::Verbose, @@ -297,9 +292,7 @@ impl Shell { pub fn set_color_choice(&mut self, color: Option<&str>) -> CargoResult<()> { if let ShellOut::Stream { ref mut stdout, - ref mut buffered_stdout, ref mut stderr, - ref mut buffered_stderr, ref mut color_choice, .. } = self.output @@ -317,12 +310,10 @@ impl Shell { ), }; *color_choice = cfg; - let stdout_choice = cfg.to_termcolor_color_choice(Stream::Stdout); - let stderr_choice = cfg.to_termcolor_color_choice(Stream::Stderr); - *stdout = StandardStream::stdout(stdout_choice); - *buffered_stdout = BufferWriter::stdout(stdout_choice); - *stderr = StandardStream::stderr(stderr_choice); - *buffered_stderr = BufferWriter::stderr(stderr_choice); + let stdout_choice = cfg.to_anstream_color_choice(); + let stderr_choice = cfg.to_anstream_color_choice(); + *stdout = AutoStream::new(std::io::stdout(), stdout_choice); + *stderr = AutoStream::new(std::io::stderr(), stderr_choice); } Ok(()) } @@ -342,14 +333,14 @@ impl Shell { pub fn err_supports_color(&self) -> bool { match &self.output { ShellOut::Write(_) => false, - ShellOut::Stream { stderr, .. } => stderr.supports_color(), + ShellOut::Stream { stderr, .. } => supports_color(stderr.current_choice()), } } pub fn out_supports_color(&self) -> bool { match &self.output { ShellOut::Write(_) => false, - ShellOut::Stream { stdout, .. } => stdout.supports_color(), + ShellOut::Stream { stdout, .. } => supports_color(stdout.current_choice()), } } @@ -372,13 +363,6 @@ impl Shell { if self.needs_clear { self.err_erase_line(); } - #[cfg(windows)] - { - if let ShellOut::Stream { stderr, .. } = &mut self.output { - ::fwdansi::write_ansi(stderr, message)?; - return Ok(()); - } - } self.err().write_all(message)?; Ok(()) } @@ -388,13 +372,6 @@ impl Shell { if self.needs_clear { self.err_erase_line(); } - #[cfg(windows)] - { - if let ShellOut::Stream { stdout, .. } = &mut self.output { - ::fwdansi::write_ansi(stdout, message)?; - return Ok(()); - } - } self.out().write_all(message)?; Ok(()) } @@ -426,26 +403,22 @@ impl ShellOut { justified: bool, ) -> CargoResult<()> { match *self { - ShellOut::Stream { - ref mut buffered_stderr, - .. - } => { - let mut buffer = buffered_stderr.buffer(); - buffer.reset()?; - buffer.set_color(&to_termcolor_spec(*style))?; + ShellOut::Stream { ref mut stderr, .. } => { + let style = style.render(); + let bold = (anstyle::Style::new() | anstyle::Effects::BOLD).render(); + let reset = anstyle::Reset.render(); + + let mut buffer = Vec::new(); if justified { - write!(buffer, "{:>12}", status)?; + write!(&mut buffer, "{style}{status:>12}{reset}")?; } else { - write!(buffer, "{}", status)?; - buffer.set_color(termcolor::ColorSpec::new().set_bold(true))?; - write!(buffer, ":")?; + write!(&mut buffer, "{style}{status}{reset}{bold}:{reset}")?; } - buffer.reset()?; match message { - Some(message) => writeln!(buffer, " {}", message)?, + Some(message) => writeln!(buffer, " {message}")?, None => write!(buffer, " ")?, } - buffered_stderr.print(&buffer)?; + stderr.write_all(&buffer)?; } ShellOut::Write(ref mut w) => { if justified { @@ -463,18 +436,15 @@ impl ShellOut { } /// Write a styled fragment - fn write_stdout(&mut self, fragment: impl fmt::Display, color: &Style) -> CargoResult<()> { + fn write_stdout(&mut self, fragment: impl fmt::Display, style: &Style) -> CargoResult<()> { match *self { - ShellOut::Stream { - ref mut buffered_stdout, - .. - } => { - let mut buffer = buffered_stdout.buffer(); - buffer.reset()?; - buffer.set_color(&to_termcolor_spec(*color))?; - write!(buffer, "{}", fragment)?; - buffer.reset()?; - buffered_stdout.print(&buffer)?; + ShellOut::Stream { ref mut stdout, .. } => { + let style = style.render(); + let reset = anstyle::Reset.render(); + + let mut buffer = Vec::new(); + write!(buffer, "{style}{}{reset}", fragment)?; + stdout.write_all(&buffer)?; } ShellOut::Write(ref mut w) => { write!(w, "{}", fragment)?; @@ -484,18 +454,15 @@ impl ShellOut { } /// Write a styled fragment - fn write_stderr(&mut self, fragment: impl fmt::Display, color: &Style) -> CargoResult<()> { + fn write_stderr(&mut self, fragment: impl fmt::Display, style: &Style) -> CargoResult<()> { match *self { - ShellOut::Stream { - ref mut buffered_stderr, - .. - } => { - let mut buffer = buffered_stderr.buffer(); - buffer.reset()?; - buffer.set_color(&to_termcolor_spec(*color))?; - write!(buffer, "{}", fragment)?; - buffer.reset()?; - buffered_stderr.print(&buffer)?; + ShellOut::Stream { ref mut stderr, .. } => { + let style = style.render(); + let reset = anstyle::Reset.render(); + + let mut buffer = Vec::new(); + write!(buffer, "{style}{}{reset}", fragment)?; + stderr.write_all(&buffer)?; } ShellOut::Write(ref mut w) => { write!(w, "{}", fragment)?; @@ -523,32 +490,21 @@ impl ShellOut { impl ColorChoice { /// Converts our color choice to termcolor's version. - fn to_termcolor_color_choice(self, stream: Stream) -> termcolor::ColorChoice { + fn to_anstream_color_choice(self) -> anstream::ColorChoice { match self { - ColorChoice::Always => termcolor::ColorChoice::Always, - ColorChoice::Never => termcolor::ColorChoice::Never, - ColorChoice::CargoAuto => { - if stream.is_terminal() { - termcolor::ColorChoice::Auto - } else { - termcolor::ColorChoice::Never - } - } + ColorChoice::Always => anstream::ColorChoice::Always, + ColorChoice::Never => anstream::ColorChoice::Never, + ColorChoice::CargoAuto => anstream::ColorChoice::Auto, } } } -enum Stream { - Stdout, - Stderr, -} - -impl Stream { - fn is_terminal(self) -> bool { - match self { - Self::Stdout => std::io::stdout().is_terminal(), - Self::Stderr => std::io::stderr().is_terminal(), - } +fn supports_color(choice: anstream::ColorChoice) -> bool { + match choice { + anstream::ColorChoice::Always + | anstream::ColorChoice::AlwaysAnsi + | anstream::ColorChoice::Auto => true, + anstream::ColorChoice::Never => false, } }