1 //! # Terminal progress bar for Rust
2 //!
3 //! Console progress bar for Rust Inspired from [pb](http://github.com/cheggaaa/pb), support and
4 //! tested on MacOS, Linux and Windows
5 //!
6 //! ![Screenshot](https://raw.githubusercontent.com/a8m/pb/master/gif/rec_v3.gif)
7 //!
8 //! [Documentation](http://a8m.github.io/pb/doc/pbr/index.html)
9 //!
10 //! ### Examples
11 //! 1. simple example
12 //!
13 //! ```ignore
14 //! extern crate pbr;
15 //!
16 //! use pbr::ProgressBar;
17 //! use std::thread;
18 //!
19 //! fn main() {
20 //!     let count = 1000;
21 //!     let mut pb = ProgressBar::new(count);
22 //!     pb.format("╢▌▌░╟");
23 //!     for _ in 0..count {
24 //!         pb.inc();
25 //!         thread::sleep_ms(200);
26 //!     }
27 //!     pb.finish_print("done");
28 //! }
29 //! ```
30 //!
31 //! 2. MultiBar example. see full example [here](https://github.com/a8m/pb/blob/master/examples/multi.rs)
32 //!
33 //! ```ignore
34 //! extern crate pbr;
35 //!
36 //! use std::thread;
37 //! use pbr::MultiBar;
38 //! use std::time::Duration;
39 //!
40 //! fn main() {
41 //!     let mut mb = MultiBar::new();
42 //!     let count = 100;
43 //!     mb.println("Application header:");
44 //!
45 //!     let mut p1 = mb.create_bar(count);
46 //!     let _ = thread::spawn(move || {
47 //!         for _ in 0..count {
48 //!             p1.inc();
49 //!             thread::sleep(Duration::from_millis(100));
50 //!         }
51 //!         // notify the multibar that this bar finished.
52 //!         p1.finish();
53 //!     });
54 //!
55 //!     mb.println("add a separator between the two bars");
56 //!
57 //!     let mut p2 = mb.create_bar(count * 2);
58 //!     let _ = thread::spawn(move || {
59 //!         for _ in 0..count * 2 {
60 //!             p2.inc();
61 //!             thread::sleep(Duration::from_millis(100));
62 //!         }
63 //!         // notify the multibar that this bar finished.
64 //!         p2.finish();
65 //!     });
66 //!
67 //!     // start listen to all bars changes.
68 //!     // this is a blocking operation, until all bars will finish.
69 //!     // to ignore blocking, you can run it in a different thread.
70 //!     mb.listen();
71 //! }
72 //! ```
73 //!
74 //! 3. Broadcast writing(simple file copying)
75 //!
76 //! ```ignore
77 //! #![feature(io)]
78 //! extern crate pbr;
79 //!
80 //! use std::io::copy;
81 //! use std::io::prelude::*;
82 //! use std::fs::File;
83 //! use pbr::{ProgressBar, Units};
84 //!
85 //! fn main() {
86 //!     let mut file = File::open("/usr/share/dict/words").unwrap();
87 //!     let n_bytes = file.metadata().unwrap().len() as usize;
88 //!     let mut pb = ProgressBar::new(n_bytes);
89 //!     pb.set_units(Units::Bytes);
90 //!     let mut handle = File::create("copy-words").unwrap().broadcast(&mut pb);
91 //!     copy(&mut file, &mut handle).unwrap();
92 //!     pb.finish_print("done");
93 //! }
94 //! ```
95 
96 // Macro for writing to the giving writer.
97 // Used in both pb.rs and multi.rs modules.
98 //
99 // # Examples
100 //
101 // ```
102 // let w = io::stdout();
103 // printfl!(w, "");
104 // printfl!(w, "\r{}", out);
105 //
106 // ```
107 macro_rules! printfl {
108    ($w:expr, $($tt:tt)*) => {{
109         $w.write(&format!($($tt)*).as_bytes()).ok().expect("write() fail");
110         $w.flush().ok().expect("flush() fail");
111     }}
112 }
113 
114 extern crate crossbeam_channel;
115 extern crate time;
116 mod multi;
117 mod pb;
118 mod tty;
119 pub use multi::{MultiBar, Pipe};
120 pub use pb::{ProgressBar, Units};
121 use std::io::{stdout, Stdout, Write};
122 
123 pub struct PbIter<T, I>
124 where
125     I: Iterator,
126     T: Write,
127 {
128     iter: I,
129     progress_bar: ProgressBar<T>,
130 }
131 
132 impl<I> PbIter<Stdout, I>
133 where
134     I: Iterator,
135 {
new(iter: I) -> Self136     pub fn new(iter: I) -> Self {
137         Self::on(stdout(), iter)
138     }
139 }
140 
141 impl<T, I> PbIter<T, I>
142 where
143     I: Iterator,
144     T: Write,
145 {
on(handle: T, iter: I) -> Self146     pub fn on(handle: T, iter: I) -> Self {
147         let size = iter.size_hint().0;
148         PbIter {
149             iter: iter,
150             progress_bar: ProgressBar::on(handle, size as u64),
151         }
152     }
153 }
154 
155 impl<T, I> Iterator for PbIter<T, I>
156 where
157     I: Iterator,
158     T: Write,
159 {
160     type Item = I::Item;
161 
next(&mut self) -> Option<I::Item>162     fn next(&mut self) -> Option<I::Item> {
163         match self.iter.next() {
164             Some(i) => {
165                 self.progress_bar.inc();
166                 Some(i)
167             }
168             None => None,
169         }
170     }
171 
size_hint(&self) -> (usize, Option<usize>)172     fn size_hint(&self) -> (usize, Option<usize>) {
173         self.iter.size_hint()
174     }
175 }
176