Expand description
A progress bar library with a focus on ergonomics.
Usage
use headway::ProgressBarIterable;
for _ in (0..100).progress() {
sleep(Duration::from_millis(20));
}
Multiple bars
Multiple bars are transparently supported. Just create more of them and they will automatically be placed so that they do not overlap.
use headway::ProgressBarIterable;
let mut handles = vec![];
for i in 0..5 {
handles.push(thread::spawn(move || {
for _ in (0..100).progress() {
sleep(Duration::from_millis(20 + i * 20));
}
}));
}
for handle in handles {
handle.join().unwrap();
}
Splitting bars
You can split bars into smaller bars if you have a task that consists of several sub-tasks.
use headway::{ProgressBar, ProgressBarIterable};
let mut p = ProgressBar::new().split_weighted();
let first_half = p.take(0.5).with_message("First part");
let second_half = p.take(0.5).with_message("Second part");
for _ in (0..50).progress_with(first_half) {
sleep(Duration::from_millis(20));
}
for _ in (0..50).progress_with(second_half) {
sleep(Duration::from_millis(30));
}
You can also split in other ways, not just using fractions.
use headway::ProgressBar;
// Split the bar into bars taking up a fixed fraction of the parent
let mut p = ProgressBar::new().split_weighted();
let first_quarter = p.take(0.25);
let last_three_quarters = p.take(0.75);
// Split the bar into fixed size nested bars
let p = ProgressBar::new();
p.set_length(50);
let mut p = p.split_sized();
let first_10 = p.take(10);
let another_30 = p.take(30);
let last_10 = p.remaining();
// Split the bar and display it by summing the progress from each child
let p = ProgressBar::new().split_summed();
let first = p.take();
let second = p.take();
// Split into several bars, each representing one item of the iterator
let items = &["a", "b", "c", "d"];
for (nested_bar, letter) in ProgressBar::new().split_each(items.iter()) {}
Printing while a progress bar is visible
Most progress bar libraries have their output messed up in some way if you try to e.g. call println
while a progress bar is visible.
Either the progress bar gets clobbered, or your printed text gets overwritten, or both!
This library interacts properly with stdout so you can freely use println
while a progress bar (or multiple) is visible.
use headway::ProgressBarIterable;
for i in (0..100).progress() {
if i % 10 == 0 {
println!("{}", i);
}
sleep(Duration::from_millis(20));
}
Caveats
Printing to stderr
has the potential to mess things up. However, if you flush stdout
before you print to stderr
then things should work properly.
If a child process prints to stdout
, this also has the potential to mess things up.
Abandoning bars
If you abandon a bar without finishing it (for example because a worker thread crashed), then the bar
will draw angry red marks to draw your attention. You can also explicitly abandon a bar using ProgressBar::abandon
.
use headway::ProgressBarIterable;
for i in (0..100).progress() {
if i == 20 {
panic!("Something went wrong!");
}
sleep(Duration::from_millis(50));
}
Indeterminate bars
If the progress bar doesn’t have a known length, the bar will show an animation instead.
use headway::ProgressBarIterable;
for i in (0..).progress() {
if i == 100 {
break;
}
sleep(Duration::from_millis(50));
}
Styling
It is currently not possible to style bars in any way.
Alternative crates
- Indicatif - A crate which supports progress bars and spinners and lots of styling. However it is less ergonomic, especially when working with multiple progress bars. It also interacts poorly with simultaneous printing to stdout.