Skip to content

Commit

Permalink
Use flag in Shell to track progress clearing.
Browse files Browse the repository at this point in the history
  • Loading branch information
ehuss committed Feb 1, 2019
1 parent 78ba948 commit 2932713
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 24 deletions.
18 changes: 1 addition & 17 deletions src/cargo/core/compiler/job_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use jobserver::{Acquired, HelperThread};
use log::{debug, info, trace};

use crate::core::profiles::Profile;
use crate::core::{PackageId, Target, TargetKind, Verbosity};
use crate::core::{PackageId, Target, TargetKind};
use crate::handle_error;
use crate::util;
use crate::util::diagnostic_server::{self, DiagnosticPrinter};
Expand Down Expand Up @@ -289,14 +289,8 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
};

for event in events {
// CAUTION: Care must be taken to clear the progress bar if a
// message is to be actually displayed. Try to avoid
// unnecessarily clearing it to avoid flickering.
match event {
Message::Run(cmd) => {
if cx.bcx.config.shell().verbosity() == Verbosity::Verbose {
self.progress.clear();
}
cx.bcx
.config
.shell()
Expand All @@ -306,17 +300,14 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
plan.update(&module_name, &cmd, &filenames)?;
}
Message::Stdout(out) => {
self.progress.clear();
println!("{}", out);
}
Message::Stderr(err) => {
self.progress.clear();
let mut shell = cx.bcx.config.shell();
shell.print_ansi(err.as_bytes())?;
shell.err().write_all(b"\n")?;
}
Message::FixDiagnostic(msg) => {
self.progress.clear();
print.print(&msg)?;
}
Message::Finish(key, result) => {
Expand All @@ -336,7 +327,6 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
match result {
Ok(()) => self.finish(key, cx)?,
Err(e) => {
self.progress.clear();
let msg = "The following warnings were emitted during compilation:";
self.emit_warnings(Some(msg), &key, cx)?;

Expand Down Expand Up @@ -460,7 +450,6 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
let bcx = &mut cx.bcx;
if let Some(output) = output.get(&(key.pkg, key.kind)) {
if !output.warnings.is_empty() {
self.progress.clear();
if let Some(msg) = msg {
writeln!(bcx.config.shell().err(), "{}\n", msg)?;
}
Expand Down Expand Up @@ -521,12 +510,10 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
// Skip Doctest
if !key.mode.is_any_test() {
self.documented.insert(key.pkg);
self.progress.clear();
config.shell().status("Documenting", key.pkg)?;
}
} else {
self.compiled.insert(key.pkg);
self.progress.clear();
if key.mode.is_check() {
config.shell().status("Checking", key.pkg)?;
} else {
Expand All @@ -540,9 +527,6 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
&& !(key.mode == CompileMode::Doctest && self.compiled.contains(&key.pkg))
{
self.compiled.insert(key.pkg);
if config.shell().verbosity() == Verbosity::Verbose {
self.progress.clear();
}
config.shell().verbose(|c| c.status("Fresh", key.pkg))?;
}
}
Expand Down
33 changes: 30 additions & 3 deletions src/cargo/core/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ pub struct Shell {
err: ShellOut,
/// How verbose messages should be
verbosity: Verbosity,
/// Flag that indicates the current line needs to be cleared before
/// printing. Used when a progress bar is currently displayed.
needs_clear: bool,
}

impl fmt::Debug for Shell {
Expand Down Expand Up @@ -75,6 +78,7 @@ impl Shell {
tty: atty::is(atty::Stream::Stderr),
},
verbosity: Verbosity::Verbose,
needs_clear: false,
}
}

Expand All @@ -83,6 +87,7 @@ impl Shell {
Shell {
err: ShellOut::Write(out),
verbosity: Verbosity::Verbose,
needs_clear: false,
}
}

Expand All @@ -97,10 +102,25 @@ impl Shell {
) -> CargoResult<()> {
match self.verbosity {
Verbosity::Quiet => Ok(()),
_ => self.err.print(status, message, color, justified),
_ => {
if self.needs_clear {
self.err_erase_line();
}
self.err.print(status, message, color, justified)
}
}
}

/// Set whether or not the next print should clear the current line.
pub fn set_needs_clear(&mut self, needs_clear: bool) {
self.needs_clear = needs_clear;
}

/// True if the `needs_clear` flag is not set.
pub fn is_cleared(&self) -> bool {
!self.needs_clear
}

/// Returns the width of the terminal in spaces, if any
pub fn err_width(&self) -> Option<usize> {
match self.err {
Expand All @@ -119,13 +139,17 @@ impl Shell {

/// Get a reference to the underlying writer
pub fn err(&mut self) -> &mut dyn Write {
if self.needs_clear {
self.err_erase_line();
}
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);
self.needs_clear = false;
}
}

Expand Down Expand Up @@ -251,6 +275,9 @@ impl Shell {

/// Prints a message and translates ANSI escape code into console colors.
pub fn print_ansi(&mut self, message: &[u8]) -> CargoResult<()> {
if self.needs_clear {
self.err_erase_line();
}
#[cfg(windows)]
{
if let ShellOut::Stream { stream, .. } = &mut self.err {
Expand Down Expand Up @@ -361,7 +388,7 @@ mod imp {
// 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");
let _ = shell.err.as_write().write_all(b"\x1B[K");
}
}

Expand Down Expand Up @@ -434,6 +461,6 @@ mod imp {
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));
drop(write!(shell.err.as_write(), "{}\r", blank));
}
}
11 changes: 7 additions & 4 deletions src/cargo/util/progress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,18 +195,21 @@ impl<'cfg> State<'cfg> {
}

// Only update if the line has changed.
if self.last_line.as_ref() != Some(&line) {
self.config.shell().status_header(&self.name)?;
write!(self.config.shell().err(), "{}\r", line)?;
if self.config.shell().is_cleared() || self.last_line.as_ref() != Some(&line) {
let mut shell = self.config.shell();
shell.set_needs_clear(false);
shell.status_header(&self.name)?;
write!(shell.err(), "{}\r", line)?;
self.last_line = Some(line);
shell.set_needs_clear(true);
}

Ok(())
}

fn clear(&mut self) {
// No need to clear if the progress is not currently being displayed.
if self.last_line.is_some() {
if self.last_line.is_some() && !self.config.shell().is_cleared() {
self.config.shell().err_erase_line();
self.last_line = None;
}
Expand Down

0 comments on commit 2932713

Please sign in to comment.