Async-first terminal UI spinners and progress bars
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687//! Three ways to use [`future::Group`]://!//! 1. One line per future: push each future as its own row.//! 2. Per-line progress bars: each row drives its own bar via [`with_progress`].//! 3. Many futures, one line: wrap a batch with [`future::join`] so the row's bar fills as each//! inner future completes.//!//! Run with `cargo run --example groups`.
use std::time::{Duration, Instant};
use async_io::Timer;use async_signal::{Signal, Signals};use futures::channel::mpsc;use futures::SinkExt;use futures_concurrency::future::Race as _;use futures_lite::{future, StreamExt};use strides::future::{join, FutureExt, Group};use strides::{bar, term, Theme};
fn theme() -> Theme<'static> { let bar = bar::styles::THIN_LINE .with_filled_style(owo_colors::Style::new().bright_purple()) .with_empty_style(owo_colors::Style::new().bright_black());
Theme::default().with_bar(bar).with_bar_width(20)}
async fn one_line_per_future() { let mut group = Group::new(theme()).with_elapsed_time(); group.push(Timer::after(Duration::from_secs(1)).with_label("one second")); group.push(Timer::after(Duration::from_secs(2)).with_label("two seconds")); group.push(Timer::after(Duration::from_secs(3)).with_label("three seconds")); group.for_each(|_| {}).await;}
async fn per_line_progress() { let mut group = Group::new(theme());
for (label, secs) in [("qux", 2u64), ("foo", 3), ("bar", 4)] { let (mut tx, rx) = mpsc::unbounded::<f64>(); let secs = Duration::from_secs(secs); let work = async move { let start = Instant::now(); while start.elapsed() < secs { let _ = tx .send(start.elapsed().as_secs_f64() / secs.as_secs_f64()) .await; Timer::after(Duration::from_millis(50)).await; } }; group.push(work.with_label(label).with_progress(rx)); }
group.for_each(|_| {}).await;}
async fn many_futures_one_line() { let checks = (1..=6).map(|i| async move { Timer::after(Duration::from_millis(300 + i * 100)).await; i });
let mut group = Group::new(theme()).with_elapsed_time(); group.push(join(checks).with_label("checking")); group.for_each(|_| {}).await;}
fn main() { let mut signals = Signals::new([Signal::Int]).expect("signal handler");
future::block_on(async { let work = async { one_line_per_future().await; per_line_progress().await; many_futures_one_line().await; };
let on_interrupt = async { let _ = signals.next().await; let _ = term::reset(); };
(work, on_interrupt).race().await; });}