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//! ![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//! 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}