diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index 77f897d6073..023a87e6562 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -120,6 +120,13 @@ impl Shell { self.err.as_write() } + /// Erase from cursor to end of line. + pub fn err_erase_line(&mut self) { + if let ShellOut::Stream { tty: true, .. } = self.err { + imp::err_erase_line(self); + } + } + /// Shortcut to right-align and color green a status message. pub fn status(&mut self, status: T, message: U) -> CargoResult<()> where @@ -332,6 +339,8 @@ mod imp { use libc; + use super::Shell; + pub fn stderr_width() -> Option { unsafe { let mut winsize: libc::winsize = mem::zeroed(); @@ -345,10 +354,19 @@ mod imp { } } } + + pub fn err_erase_line(shell: &mut Shell) { + // This is the "EL - Erase in Line" sequence. It clears from the cursor + // to the end of line. + // https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences + let _ = shell.err().write_all(b"\x1B[K"); + } } #[cfg(all(unix, not(any(target_os = "linux", target_os = "macos"))))] mod imp { + pub(super) use super::default_err_erase_line as err_erase_line; + pub fn stderr_width() -> Option { None } @@ -366,6 +384,8 @@ mod imp { use self::winapi::um::wincon::*; use self::winapi::um::winnt::*; + pub(super) use super::default_err_erase_line as err_erase_line; + pub fn stderr_width() -> Option { unsafe { let stdout = GetStdHandle(STD_ERROR_HANDLE); @@ -408,3 +428,14 @@ mod imp { } } } + +#[cfg(any( + all(unix, not(any(target_os = "linux", target_os = "macos"))), + windows, +))] +fn default_err_erase_line(shell: &mut Shell) { + if let Some(max_width) = imp::stderr_width() { + let blank = " ".repeat(max_width); + drop(write!(shell.err(), "{}\r", blank)); + } +} diff --git a/src/cargo/util/progress.rs b/src/cargo/util/progress.rs index c6cedf62191..15347690cd2 100644 --- a/src/cargo/util/progress.rs +++ b/src/cargo/util/progress.rs @@ -196,9 +196,7 @@ impl<'cfg> State<'cfg> { } fn clear(&mut self) { - self.try_update_max_width(); - let blank = " ".repeat(self.format.max_width); - drop(write!(self.config.shell().err(), "{}\r", blank)); + self.config.shell().err_erase_line(); } fn try_update_max_width(&mut self) {