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