use std::time::Duration;
use indicatif::{ProgressStyle, ProgressState, HumanDuration};
pub const PROGRESS_CHARS: &str = "█▉▊▋▌▍▎▏ ";
pub const INDICATIF_PROGRESS_TEMPLATE: &str = if cfg!(windows) {
"{elapsed_precise:.bold} ▕{wide_bar:.blue/white.dim}▏ {percent:.bold} {pos} ({fps:.bold}, eta {fixed_eta}{msg})"
} else {
"{spinner:.green.bold} {elapsed_precise:.bold} ▕{wide_bar:.blue/white.dim}▏ {percent:.bold} {pos} ({fps:.bold}, eta {fixed_eta}{msg})"
};
pub const INDICATIF_SPINNER_TEMPLATE: &str = if cfg!(windows) {
"{elapsed_precise:.bold} {pos} ({fps:.bold}{msg})"
} else {
"{spinner:.green.bold} {elapsed_precise:.bold} {pos} ({fps:.bold}{msg})"
};
pub fn pretty_progress_style() -> ProgressStyle {
ProgressStyle::default_bar()
.template(INDICATIF_PROGRESS_TEMPLATE)
.unwrap()
.with_key(
"fps",
|state: &ProgressState, w: &mut dyn std::fmt::Write| {
if state.pos() == 0 || state.elapsed().as_secs_f32() < f32::EPSILON {
write!(w, "0 fps").unwrap();
} else {
let fps = state.pos() as f32 / state.elapsed().as_secs_f32();
if fps < 1.0 {
write!(w, "{:.2} s/fr", 1.0 / fps).unwrap();
} else {
write!(w, "{:.2} fps", fps).unwrap();
}
}
},
)
.with_key(
"fixed_eta",
|state: &ProgressState, w: &mut dyn std::fmt::Write| {
if state.pos() == 0 || state.elapsed().as_secs_f32() < f32::EPSILON {
write!(w, "unknown").unwrap();
} else {
let spf = state.elapsed().as_secs_f32() / state.pos() as f32;
let remaining = state.len().unwrap_or(0) - state.pos();
write!(
w,
"{:#}",
HumanDuration(Duration::from_secs_f32(spf * remaining as f32))
)
.unwrap();
}
},
)
.with_key(
"pos",
|state: &ProgressState, w: &mut dyn std::fmt::Write| {
write!(w, "{}/{}", state.pos(), state.len().unwrap_or(0)).unwrap();
},
)
.with_key(
"percent",
|state: &ProgressState, w: &mut dyn std::fmt::Write| {
write!(w, "{:>3.0}%", state.fraction() * 100_f32).unwrap();
},
)
.progress_chars(PROGRESS_CHARS)
}
pub fn pretty_spinner_style() -> ProgressStyle {
ProgressStyle::default_bar()
.template(INDICATIF_SPINNER_TEMPLATE)
.unwrap()
.with_key(
"fps",
|state: &ProgressState, w: &mut dyn std::fmt::Write| {
if state.pos() == 0 || state.elapsed().as_secs_f32() < f32::EPSILON {
write!(w, "0 fps").unwrap();
} else {
let fps = state.pos() as f32 / state.elapsed().as_secs_f32();
if fps < 1.0 {
write!(w, "{:.2} s/fr", 1.0 / fps).unwrap();
} else {
write!(w, "{:.2} fps", fps).unwrap();
}
}
},
)
.with_key(
"pos",
|state: &ProgressState, w: &mut dyn std::fmt::Write| {
write!(w, "{}", state.pos()).unwrap();
},
)
.progress_chars(PROGRESS_CHARS)
}