1use std::sync::Arc;
2use std::time::Duration;
3use console::style;
4use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
5
6#[derive(PartialEq, Clone)]
8pub(crate) enum LineStatus { Idle, Busy }
9
10
11#[derive(Debug, Clone)]
13pub struct Line {
14 bar: ProgressBar,
16}
17
18
19impl Line {
20 pub(crate) fn new(progress: Arc<MultiProgress>) -> Self {
22 Self { bar: progress.add(ProgressBar::new(0)) }
23 }
24
25 pub fn println(&self, message: String) {
27 self.bar.println(message);
28 }
29
30 pub(crate) fn update_prefix(&self, prefix: String) {
32 self.bar.set_prefix(prefix);
33 }
34
35 pub fn update_message(&self, message: String) {
37 self.update_status_and_message(LineStatus::Busy, message)
38 }
39
40 pub(crate) fn update_status_and_message(&self, status: LineStatus, message: String) {
42 if status == LineStatus::Busy {
44 self.bar.enable_steady_tick(Duration::from_millis(1000 / 30));
45 } else {
46 self.bar.disable_steady_tick()
47 }
48
49 let mut progress_style = ProgressStyle::default_spinner().template("{prefix:.bold.dim} {wide_msg}").unwrap();
51 if status == LineStatus::Busy {
52 progress_style = progress_style
53 .tick_chars("⠈⠐⠠⢀⡀⠄⠂⠁ ")
54 .template("{prefix:.bold.dim} {spinner:.yellow} {wide_msg} {binary_bytes_per_sec}").unwrap();
55 }
56 self.bar.set_style(progress_style);
57
58 let message = format!(
60 "{}{}",
61 match status {
62 LineStatus::Idle => style("- ").yellow(),
63 LineStatus::Busy => style("").white(),
64 },
65 message
66 );
67 self.bar.set_message(message);
68 }
69
70 pub(crate) fn update_position(&self, position: usize) {
72 self.bar.set_position(position as u64);
73 }
74
75 pub(crate) fn suspend<F: FnOnce() -> R, R>(&self, f: F) -> R {
77 self.bar.suspend(f)
78 }
79}