diff options
author | Edwin Cheng <[email protected]> | 2019-11-26 20:09:30 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2019-11-26 20:09:30 +0000 |
commit | 5b49ad5bd5d78a8425f7162b6387c2cad6e2ef10 (patch) | |
tree | c669d35af48f35d8cfe31bb2cfa5aed6d91fd36f /crates/ra_cli/src/progress_bar.rs | |
parent | 4d753fa6f514ea1105c25ace91201c5324ee0b92 (diff) |
Use a simple progress bar instead of indicatif
Diffstat (limited to 'crates/ra_cli/src/progress_bar.rs')
-rw-r--r-- | crates/ra_cli/src/progress_bar.rs | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/crates/ra_cli/src/progress_bar.rs b/crates/ra_cli/src/progress_bar.rs new file mode 100644 index 000000000..95bfcf4d0 --- /dev/null +++ b/crates/ra_cli/src/progress_bar.rs | |||
@@ -0,0 +1,130 @@ | |||
1 | //! A simple progress bar | ||
2 | //! | ||
3 | //! A single thread non-optimized progress bar | ||
4 | use std::io::Write; | ||
5 | |||
6 | /// A Simple ASCII Progress Bar | ||
7 | pub struct ProgressBar { | ||
8 | curr: f32, | ||
9 | text: String, | ||
10 | anim: usize, | ||
11 | hidden: bool, | ||
12 | |||
13 | len: u64, | ||
14 | pos: u64, | ||
15 | msg: String, | ||
16 | } | ||
17 | |||
18 | impl ProgressBar { | ||
19 | const ANIMATION: &'static str = r#"|/-\"#; | ||
20 | const BLOCK_COUNT: usize = 20; | ||
21 | |||
22 | pub fn new(len: u64) -> ProgressBar { | ||
23 | ProgressBar { | ||
24 | curr: 0.0, | ||
25 | text: String::new(), | ||
26 | anim: 0, | ||
27 | hidden: false, | ||
28 | len, | ||
29 | pos: 0, | ||
30 | msg: String::new(), | ||
31 | } | ||
32 | } | ||
33 | |||
34 | pub fn hidden() -> ProgressBar { | ||
35 | ProgressBar { | ||
36 | curr: 0.0, | ||
37 | text: String::new(), | ||
38 | anim: 0, | ||
39 | hidden: true, | ||
40 | len: 0, | ||
41 | pos: 0, | ||
42 | msg: String::new(), | ||
43 | } | ||
44 | } | ||
45 | |||
46 | pub fn set_message(&mut self, msg: &str) { | ||
47 | self.msg = msg.to_string(); | ||
48 | self.tick(); | ||
49 | } | ||
50 | |||
51 | pub fn println<I: Into<String>>(&mut self, msg: I) { | ||
52 | self.clear(); | ||
53 | println!("{}", msg.into()); | ||
54 | self.tick(); | ||
55 | } | ||
56 | |||
57 | pub fn inc(&mut self, delta: u64) { | ||
58 | self.pos += delta; | ||
59 | if self.len == 0 { | ||
60 | self.set_value(0.0) | ||
61 | } else { | ||
62 | self.set_value((self.pos as f32) / (self.len as f32)) | ||
63 | } | ||
64 | self.tick(); | ||
65 | } | ||
66 | |||
67 | pub fn finish_and_clear(&mut self) { | ||
68 | self.clear(); | ||
69 | } | ||
70 | |||
71 | pub fn tick(&mut self) { | ||
72 | if self.hidden { | ||
73 | return; | ||
74 | } | ||
75 | |||
76 | let progress_block: usize = (self.curr * Self::BLOCK_COUNT as f32) as usize; | ||
77 | let percent = (self.curr * 100.0) as u32; | ||
78 | let text = format!( | ||
79 | "[{}{}] {:3>}% {} {}", | ||
80 | "#".repeat(progress_block), | ||
81 | "-".repeat(Self::BLOCK_COUNT - progress_block), | ||
82 | percent, | ||
83 | Self::ANIMATION.chars().nth(self.anim).unwrap(), | ||
84 | self.msg, | ||
85 | ); | ||
86 | |||
87 | self.anim = (self.anim + 1) % Self::ANIMATION.len(); | ||
88 | self.update_text(&text); | ||
89 | } | ||
90 | |||
91 | fn update_text(&mut self, text: &str) { | ||
92 | // Get length of common portion | ||
93 | let mut common_prefix_length = 0; | ||
94 | let common_length = usize::min(self.text.len(), text.len()); | ||
95 | |||
96 | while common_prefix_length < common_length | ||
97 | && text.chars().nth(common_prefix_length).unwrap() | ||
98 | == self.text.chars().nth(common_prefix_length).unwrap() | ||
99 | { | ||
100 | common_prefix_length += 1; | ||
101 | } | ||
102 | |||
103 | // Backtrack to the first differing character | ||
104 | let mut output = String::new(); | ||
105 | output += &'\x08'.to_string().repeat(self.text.len() - common_prefix_length); | ||
106 | // Output new suffix | ||
107 | output += &text[common_prefix_length..text.len()]; | ||
108 | |||
109 | // If the new text is shorter than the old one: delete overlapping characters | ||
110 | if let Some(overlap_count) = self.text.len().checked_sub(text.len()) { | ||
111 | if overlap_count > 0 { | ||
112 | output += &" ".repeat(overlap_count); | ||
113 | output += &"\x08".repeat(overlap_count); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | let _ = std::io::stdout().write(output.as_bytes()); | ||
118 | let _ = std::io::stdout().flush(); | ||
119 | self.text = text.to_string(); | ||
120 | } | ||
121 | |||
122 | fn set_value(&mut self, value: f32) { | ||
123 | self.curr = f32::max(0.0, f32::min(1.0, value)); | ||
124 | } | ||
125 | |||
126 | fn clear(&mut self) { | ||
127 | print!("{}", "\x08".repeat(self.text.len())); | ||
128 | self.text = String::new(); | ||
129 | } | ||
130 | } | ||