1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
extern crate yansi;
use yansi::Paint;
use std::ops::FnOnce;
use std::fmt::Display;
use std::io::{ stdout, Write };
pub struct Progress<'a> {
action: &'a str,
description: &'a str,
padding: usize,
value: u8
}
impl<'a> Progress<'a> {
pub fn new(action: &'a str, description: &'a str, padding: usize) -> Progress<'a> {
Progress{ action, description, padding, value: 0 }
}
pub fn initialize(&mut self) {
self.set_from(0, 100, 0);
}
pub fn set(&mut self, value: usize) {
self.set_from(0, 100, value)
}
pub fn increment(&mut self, offset: usize) {
self.set(self.value as usize + offset);
}
pub fn set_from(&mut self, min: usize, max: usize, value: usize) {
self.value = (((value - min) * 100) / (max - min)) as u8;
print!("\r{:>3$} [{:>3}%] {:<4$}", Paint::yellow(self.action), self.value, self.description, self.padding, self.description.len());
stdout().flush().unwrap_or_default();
}
fn ok<R>(&mut self, result: &R) where R: Display {
self.value = 100;
println!("\r{:>3$} [{:>3}%] {:<4$}", Paint::green(self.action), self.value, result, self.padding, self.description.len());
}
fn err<E>(&mut self, error: &E) where E: Display {
println!("\r{:>3$} [{:>3}%] {:<4$}", Paint::red(self.action), self.value, error, self.padding, self.description.len());
}
}
pub fn proceed<F, R, D, E>(action: &str, description: &str, function: F) -> Result<R, E> where
F: FnOnce(&mut Progress) -> Result<(R, D), E>,
D: Display,
E: Display
{
proceed_with_padding(action, description, function, 12)
}
pub fn proceed_with_padding<F, R, D, E>(action: &str, description: &str, function: F, padding: usize) -> Result<R, E> where
F: FnOnce(&mut Progress) -> Result<(R, D), E>,
D: Display,
E: Display
{
let mut progress = Progress::new(action, description, padding);
progress.initialize();
match function(&mut progress) {
Ok(result) => {
progress.ok(&result.1);
Ok(result.0)
},
Err(error) => {
progress.err(&error);
Err(error)
}
}
}