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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
use std::sync::Mutex; #[macro_use] extern crate lazy_static; lazy_static! { static ref TEXT: Mutex<String> = Mutex::new(String::new()); } pub struct Tqdm; impl Tqdm { pub fn new<I: Iterator>(iter: I) -> TqdmAuto<I> { let total = iter.size_hint().0; TqdmAuto {iter, current: 0, total} } pub fn manual(total: usize) -> TqdmManual { TqdmManual {current: 0, total} } } pub fn write(text: &str) { let mut msg = TEXT.lock().unwrap(); *msg = String::from(text); } fn clear_previous_line() { print!("\x1b[1A"); print!("\r"); let size = terminal_size::terminal_size().expect("Unable to get terminal size."); let width = size.0.0 as usize; print!("{}", " ".repeat(width)); print!("\r"); } trait WriteCon { fn get_current_amount(&self) -> usize {0} fn get_total_amount(&self) -> usize {0} fn get_percentage(&self) -> usize { let fraction = self.get_current_amount() as f32 / self.get_total_amount() as f32; (fraction * 100f32).round() as usize } fn create_bar(&self) -> String { let percents = self.get_percentage(); let current = self.get_current_amount(); let total = self.get_total_amount(); let length = total.to_string().len(); format!("{:>3}% | progress bar | {:>length$}/{}", percents, current, total, length = length) } fn display(&self) { let bar = self.create_bar(); let mut text = TEXT.lock().unwrap(); if self.get_current_amount() != 0 { let lines = text.matches("\n").count(); for _ in 1..=lines { clear_previous_line(); } clear_previous_line(); clear_previous_line(); } if !text.is_empty() { println!("{}", text); *text = String::new(); } else { println!(""); } println!("{}", bar); } } pub struct TqdmAuto<I: Iterator> { iter: I, current: usize, total: usize, } impl<I: Iterator> Iterator for TqdmAuto<I> { type Item = (); fn next(&mut self) -> Option<Self::Item> { let next = self.iter.next(); if next.is_some() { self.display(); self.current += 1; Some(()) } else { self.display(); None } } } impl<I: Iterator> WriteCon for TqdmAuto<I> { fn get_current_amount(&self) -> usize { self.current } fn get_total_amount(&self) -> usize { self.total } } pub struct TqdmManual { current: usize, total: usize, } impl TqdmManual { pub fn update(mut self, num: usize) { self.current = std::cmp::min(self.total, self.current + num); self.display(); } } impl WriteCon for TqdmManual { fn get_current_amount(&self) -> usize { self.current } fn get_total_amount(&self) -> usize { self.total } }