Skip to content

Commit 8155921

Browse files
committed
download_tracker.rs: Erase line more robustly
In rust-lang#1781, we switched to using `delete_line()` but unfortunately that turns out to not work very well on Windows. So this commit turns us back to using spaces to erase things, but in a way which ought to be moderately more robust than before. There's still no guarantee we're doing it right, but at least this time if the terminal is approximately wide enough for the bar and no more, we won't be flowing onto the next line with loads of spaces after the rest of the tracker. Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
1 parent 373448b commit 8155921

File tree

1 file changed

+27
-24
lines changed

1 file changed

+27
-24
lines changed

src/cli/download_tracker.rs

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ pub struct DownloadTracker {
3131
/// If the download is quick enough, we don't have time to
3232
/// display the progress info.
3333
/// In that case, we do not want to do some cleanup stuff we normally do.
34-
displayed_progress: bool,
34+
///
35+
/// If we have displayed progress, this is the number of characters we
36+
/// rendered, so we can erase it cleanly.
37+
displayed_charcount: Option<usize>,
3538
}
3639

3740
impl DownloadTracker {
@@ -45,7 +48,7 @@ impl DownloadTracker {
4548
seconds_elapsed: 0,
4649
last_sec: None,
4750
term: term::stdout(),
48-
displayed_progress: false,
51+
displayed_charcount: None,
4952
}
5053
}
5154

@@ -102,7 +105,7 @@ impl DownloadTracker {
102105
}
103106
/// Notifies self that the download has finished.
104107
pub fn download_finished(&mut self) {
105-
if self.displayed_progress {
108+
if self.displayed_charcount.is_some() {
106109
// Display the finished state
107110
self.display();
108111
let _ = writeln!(self.term.as_mut().unwrap());
@@ -117,7 +120,7 @@ impl DownloadTracker {
117120
self.downloaded_last_few_secs.clear();
118121
self.seconds_elapsed = 0;
119122
self.last_sec = None;
120-
self.displayed_progress = false;
123+
self.displayed_charcount = None;
121124
}
122125
/// Display the tracked download information to the terminal.
123126
fn display(&mut self) {
@@ -132,38 +135,38 @@ impl DownloadTracker {
132135

133136
// First, move to the start of the current line and clear it.
134137
let _ = self.term.as_mut().unwrap().carriage_return();
135-
let _ = self.term.as_mut().unwrap().delete_line();
138+
// We'd prefer to use delete_line() but on Windows it seems to
139+
// sometimes do unusual things
140+
// let _ = self.term.as_mut().unwrap().delete_line();
141+
// So instead we do:
142+
if let Some(n) = self.displayed_charcount {
143+
// This is not ideal as very narrow terminals might mess up,
144+
// but it is more likely to succeed until term's windows console
145+
// fixes whatever's up with delete_line().
146+
let _ = write!(self.term.as_mut().unwrap(), "{}", " ".repeat(n));
147+
let _ = self.term.as_mut().unwrap().flush();
148+
let _ = self.term.as_mut().unwrap().carriage_return();
149+
}
136150

137-
match self.content_len {
151+
let output = match self.content_len {
138152
Some(content_len) => {
139153
let content_len = content_len as f64;
140154
let percent = (self.total_downloaded as f64 / content_len) * 100.;
141155
let content_len_h = HumanReadable(content_len);
142156
let remaining = content_len - self.total_downloaded as f64;
143157
let eta_h = HumanReadable(remaining / speed);
144-
let _ = write!(
145-
self.term.as_mut().unwrap(),
158+
format!(
146159
"{} / {} ({:3.0} %) {}/s ETA: {:#}",
147-
total_h,
148-
content_len_h,
149-
percent,
150-
speed_h,
151-
eta_h
152-
);
160+
total_h, content_len_h, percent, speed_h, eta_h
161+
)
153162
}
154-
None => {
155-
let _ = write!(
156-
self.term.as_mut().unwrap(),
157-
"Total: {} Speed: {}/s",
158-
total_h,
159-
speed_h
160-
);
161-
}
162-
}
163+
None => format!("Total: {} Speed: {}/s", total_h, speed_h),
164+
};
163165

166+
let _ = write!(self.term.as_mut().unwrap(), "{}", output);
164167
// Since stdout is typically line-buffered and we don't print a newline, we manually flush.
165168
let _ = self.term.as_mut().unwrap().flush();
166-
self.displayed_progress = true;
169+
self.displayed_charcount = Some(output.chars().count());
167170
}
168171
}
169172

0 commit comments

Comments
 (0)