This repository has no description
1use console::Style;
2use indicatif::{ProgressBar, ProgressStyle};
3use std::borrow::Cow;
4use std::sync::{Arc, Mutex};
5use std::thread::{self, JoinHandle};
6use std::time;
7
8pub const PROGRESS_BARS_STYLE: &str =
9 "{prefix:>12.bold.cyan} {percent:03}% [{bar:25}] {pos}/{len}: {msg} ({elapsed} ago, {eta} left)";
10
11pub struct Spinner {
12 pub spinner: ProgressBar,
13 pub finished: Arc<Mutex<bool>>,
14 pub thread: JoinHandle<()>,
15}
16
17impl Spinner {
18 pub fn start(verb: &'static str, message: &str) -> Self {
19 let spinner = ProgressBar::new(0).with_style(
20 ProgressStyle::with_template(&format_log_msg_cyan(
21 verb,
22 &(message.to_owned() + " {spinner:.cyan}"),
23 ))
24 .unwrap(),
25 );
26 spinner.tick();
27
28 let thread_spinner = spinner.clone();
29 let finished = Arc::new(Mutex::new(false));
30 let thread_finished = Arc::clone(&finished);
31 let spinner_thread = thread::spawn(move || {
32 while !*thread_finished.lock().unwrap() {
33 thread_spinner.tick();
34 thread::sleep(time::Duration::from_millis(100));
35 }
36 thread_spinner.finish_and_clear();
37 });
38
39 Self {
40 spinner: spinner.clone(),
41 finished,
42 thread: spinner_thread,
43 }
44 }
45
46 pub fn end(self, message: &str) {
47 self.spinner.finish_and_clear();
48 *self.finished.lock().unwrap() = true;
49 self.thread.join().unwrap();
50 println!("{}", message);
51 }
52}
53
54pub fn setup_progress_bar(total: u64, verb: &'static str) -> ProgressBar {
55 indicatif::ProgressBar::new(total)
56 .with_prefix(verb)
57 .with_style(
58 indicatif::ProgressStyle::with_template(PROGRESS_BARS_STYLE)
59 .unwrap()
60 .progress_chars("=> "),
61 )
62}
63
64pub trait Log {
65 fn log(&self, verb: &'static str, message: &str);
66}
67
68pub fn format_log_msg(verb: &'static str, message: &str) -> String {
69 let style = Style::new().bold().green();
70 format!("{} {}", style.apply_to(format!("{verb:>12}")), message)
71}
72
73pub fn format_log_msg_cyan(verb: &'static str, message: &str) -> String {
74 let style = Style::new().bold().cyan();
75 format!("{} {}", style.apply_to(format!("{verb:>12}")), message)
76}
77
78impl Log for ProgressBar {
79 fn log(&self, verb: &'static str, message: &str) {
80 self.println(format_log_msg(verb, message));
81 }
82}
83
84impl Log for Option<&ProgressBar> {
85 fn log(&self, verb: &'static str, message: &str) {
86 if let Some(pb) = self {
87 pb.println(format_log_msg(verb, message));
88 }
89 }
90}
91
92pub trait MaybeProgressBar<'a> {
93 fn set_message(&'a self, message: impl Into<Cow<'static, str>>);
94 fn inc(&'a self, n: u64);
95 fn println(&'a self, message: impl AsRef<str>);
96}
97
98impl<'a> MaybeProgressBar<'a> for Option<&'a ProgressBar> {
99 fn set_message(&'a self, message: impl Into<Cow<'static, str>>) {
100 if let Some(pb) = self {
101 pb.set_message(message);
102 }
103 }
104
105 fn inc(&'a self, n: u64) {
106 if let Some(pb) = self {
107 pb.inc(n);
108 }
109 }
110
111 fn println(&'a self, message: impl AsRef<str>) {
112 if let Some(pb) = self {
113 pb.println(message);
114 }
115 }
116}