use std::io::{self, Read};
use std::time::Duration;
use indicatif::{ProgressBar, ProgressStyle};
use crate::cli;
pub fn should_show(when: cli::When) -> bool {
match when {
cli::When::Never => false,
cli::When::Always => true,
cli::When::Auto => is_stderr_tty(),
}
}
fn is_stderr_tty() -> bool {
use std::io::IsTerminal;
io::stderr().is_terminal()
}
pub fn new_bar(total_bytes: Option<u64>, prefix: &str) -> ProgressBar {
match total_bytes {
Some(n) => {
let pb = ProgressBar::new(n);
pb.set_style(
ProgressStyle::with_template(
"{prefix:.bold} {bar:30.cyan/blue} {bytes}/{total_bytes} ({bytes_per_sec}, ETA {eta})",
)
.unwrap_or_else(|_| ProgressStyle::default_bar())
.progress_chars("=> "),
);
pb.set_prefix(prefix.to_string());
pb.enable_steady_tick(Duration::from_millis(120));
pb
}
None => {
let pb = ProgressBar::new_spinner();
pb.set_style(
ProgressStyle::with_template("{prefix:.bold} {spinner} {bytes} ({bytes_per_sec})")
.unwrap_or_else(|_| ProgressStyle::default_spinner()),
);
pb.set_prefix(prefix.to_string());
pb.enable_steady_tick(Duration::from_millis(120));
pb
}
}
}
pub fn new_count_bar(total: u64, prefix: &str, unit: &str) -> ProgressBar {
let pb = ProgressBar::new(total);
let template = format!(
"{{prefix:.bold}} {{bar:30.cyan/blue}} {{pos}}/{{len}} {unit} ({{per_sec}}, ETA {{eta}})"
);
pb.set_style(
ProgressStyle::with_template(&template)
.unwrap_or_else(|_| ProgressStyle::default_bar())
.progress_chars("=> "),
);
pb.set_prefix(prefix.to_string());
pb.enable_steady_tick(Duration::from_millis(120));
pb
}
pub struct ProgressReader<R: Read> {
inner: R,
bar: ProgressBar,
}
impl<R: Read> ProgressReader<R> {
pub fn new(inner: R, bar: ProgressBar) -> Self {
Self { inner, bar }
}
}
impl<R: Read> Read for ProgressReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let n = self.inner.read(buf)?;
if n > 0 {
self.bar.inc(n as u64);
}
Ok(n)
}
}