1 use std::io::{self, Write};
2 use std::sync::{Arc, Mutex};
3 use std::thread;
4 use std::time::{Duration, Instant};
5
6 use lazy_static::lazy_static;
7
8 lazy_static! {
9 static ref PROGRESS: Progress = Progress {
10 message: Arc::new(Mutex::new("".to_string())),
11 is_complete: Arc::new(Mutex::new(false))
12 };
13 }
14
15 pub struct Progress {
16 message: Arc<Mutex<String>>,
17 is_complete: Arc<Mutex<bool>>,
18 }
19
20 impl Progress {
start(&self)21 fn start(&self) {
22 let is_complete = self.is_complete.clone();
23 let message_ref = self.message.clone();
24 thread::spawn(move || {
25 let start = Instant::now();
26 while !*is_complete.lock().unwrap() {
27 let minutes = start.elapsed().as_secs() / 60;
28 let seconds = start.elapsed().as_secs() % 60;
29 let mut message =
30 format!(" {:01}:{:02} {}", minutes, seconds, message_ref.lock().unwrap());
31 if message.len() > 80 {
32 message.truncate(77);
33 message.push('…');
34 }
35 print!("\x1B[2K"); // clear the line
36 print!("\r{} ", message);
37 io::stdout().flush().unwrap();
38 thread::sleep(Duration::from_millis(100));
39 }
40 let mut complete = PROGRESS.is_complete.lock().unwrap();
41 *complete = false;
42 });
43 }
44
stop(&self)45 fn stop(&self) {
46 let mut is_complete = self.is_complete.lock().unwrap();
47 *is_complete = true;
48 print!("\x1B[2K"); // clear the line
49 print!("\r");
50 io::stdout().flush().unwrap();
51 }
52 }
53
update(message: &str)54 pub fn update(message: &str) {
55 let mut new_message = PROGRESS.message.lock().unwrap();
56 *new_message = message.to_string();
57 }
58
start(message: &str)59 pub fn start(message: &str) {
60 update(message);
61 PROGRESS.start();
62 }
63
stop()64 pub fn stop() {
65 PROGRESS.stop();
66 }
67