duplicate_finder/
progress_line.rs1use crate::tty::{terminal_size, Width};
2use std::iter::repeat;
3
4macro_rules! repeat {
5 ($s: expr, $n: expr) => {{
6 &repeat($s).take($n).collect::<String>()
7 }};
8}
9
10pub struct ProgressLine {
11 pub total: u64,
12 pub current: u64,
13 pub width: Option<usize>,
14 pub message: String,
15 pub show_counters: bool,
16 pub show_message: bool,
17}
18
19impl ProgressLine {
20 pub fn to_string(&self) -> String {
21 let width = self.width();
22
23 let mut base = String::new();
24 let mut prefix = String::new();
25 let mut out;
26
27 if self.show_message {
28 prefix = prefix + &format!("{}", self.message)
29 }
30
31 if self.show_counters {
32 let (c, t) = (self.current as f64, self.total as f64);
33 let percent = self.current as f64 / (self.total as f64 / 100f64);
34
35 prefix = prefix
36 + &format!(
37 "{}/{}, {:.*}%",
38 c,
39 t,
40 2,
41 if percent.is_nan() { 0.0 } else { percent }
42 );
43 }
44
45 let p = prefix.len() + 3;
46 if p < width {
47 let size = width - p;
48 let curr_count =
49 ((self.current as f64 / self.total as f64) * size as f64).ceil() as usize;
50 if size >= curr_count {
51 let rema_count = size - curr_count;
52 if rema_count > 0 && curr_count > 0 {
53 base = "[".to_string() + repeat!("=", curr_count - 1) + ">";
54 } else {
55 base = "[".to_string() + repeat!("=", curr_count);
56 }
57 base = base + repeat!("-", rema_count) + "] ";
58 }
59 }
60
61 out = base + &prefix;
62
63 if out.len() < width {
64 let gap = width - out.len();
65 out = out + repeat!(" ", gap);
66 }
67
68 out
69 }
70
71 pub fn to_empty_string(&self) -> String {
72 repeat!(" ", self.width()).to_string()
73 }
74
75 fn width(&self) -> usize {
76 if let Some(w) = self.width {
77 w
78 } else if let Some((Width(w), _)) = terminal_size() {
79 w as usize
80 } else {
81 80
82 }
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 const MESSAGE: &str = "some. ";
91
92 #[test]
93 fn converts_self_to_string_full_1() {
94 let line = create_progress_line(100, 0, Some(80), MESSAGE.to_string(), true, true);
95
96 assert_eq!(
97 "[-----------------------------------------------------------] some. 0/100, 0.00%",
98 line.to_string()
99 );
100 }
101
102 #[test]
103 fn converts_self_to_string_full_2() {
104 let line = create_progress_line(100, 10, Some(80), MESSAGE.to_string(), true, true);
105
106 assert_eq!(
107 "[=====>---------------------------------------------------] some. 10/100, 10.00%",
108 line.to_string()
109 );
110 }
111
112 #[test]
113 fn converts_self_to_string_full_3() {
114 let line = create_progress_line(100, 90, Some(80), MESSAGE.to_string(), true, true);
115
116 assert_eq!(
117 "[===================================================>-----] some. 90/100, 90.00%",
118 line.to_string()
119 );
120 }
121
122 #[test]
123 fn converts_self_to_string_full_4() {
124 let line = create_progress_line(100, 50, Some(80), MESSAGE.to_string(), true, true);
125
126 assert_eq!(
127 "[============================>----------------------------] some. 50/100, 50.00%",
128 line.to_string()
129 );
130 }
131
132 #[test]
133 fn converts_self_to_string_full_5() {
134 let line = create_progress_line(100, 100, Some(80), MESSAGE.to_string(), true, true);
135
136 assert_eq!(
137 "[=======================================================] some. 100/100, 100.00%",
138 line.to_string()
139 );
140 }
141
142 #[test]
143 fn converts_self_to_string_file() {
144 let line = create_progress_line(100, 34, Some(100), MESSAGE.to_string(), false, true);
145
146 assert_eq!(
147 "[==============================>------------------------------------------------------------] some. ",
148 line.to_string()
149 );
150 }
151
152 #[test]
153 fn converts_self_to_string_summary() {
154 let line = create_progress_line(41200, 6333, Some(60), String::new(), true, false);
155
156 assert_eq!(
157 "[=====>---------------------------------] 6333/41200, 15.37%",
158 line.to_string()
159 );
160 }
161
162 fn create_progress_line(
163 total: u64,
164 current: u64,
165 width: Option<usize>,
166 message: String,
167 show_counters: bool,
168 show_message: bool,
169 ) -> super::ProgressLine {
170 ProgressLine {
171 total,
172 current,
173 width,
174 message,
175 show_counters,
176 show_message,
177 }
178 }
179}