strides 1.0.0-rc.2

Async-first terminal UI spinners and progress bars
docs.rs failed to build strides-1.0.0-rc.2
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: strides-0.4.0

strides

Cargo Documentation MSRV

A command-line UI library to enhance async programs with progress bars and spinners.

The crate is built around two extension traits and two containers:

  • FutureExt adds .progress(theme) (sugar for .progressive().with_theme(theme)), .progressive() (unconfigured; inherits the parent Group's theme or renders with Theme::default() if awaited directly), and the .with_label(...) / .with_messages(...) / .with_progress(...) / .with_elapsed_time() setters that implicitly lift a bare Future into a ProgressFuture.
  • StreamExt adds .progress(theme, ...) / .progress_bytes(theme, ...) (sugar) and .progressive() / .progressive_bytes() (unconfigured) to any Stream.
  • future::Group runs many Futures concurrently, rendering one line per task.
  • stream::Group runs many Streams concurrently, rendering one line per stream.
  • For byte-counted file copies and downloads, convert an AsyncRead to a byte stream (e.g. via tokio_util::io::ReaderStream) and use .progress_bytes(...).

Each .progress(...) call animates automatically and returns a builder for further customization. A Theme bundles a Spinner, a Bar and a Layout, and is accepted everywhere a theme is expected. A Layout is an ordered list of Segments controlling the order, spacing and formatting of each progress line. See spinner::styles and bar::styles for predefined variants.

Pick a mode by how many tasks you have and how many terminal rows you want to spend on them:

Tasks Rows Futures Streams
1 1 fut.progress(theme).await s.progress(theme, ...) / s.progress_bytes(theme, ...)
N N Group::new(theme) + group.push(fut) per task stream::Group::new(theme) + group.push(s.progressive(...)) per stream
N 1 join(futs).with_theme(theme).await n/a
N 1-of-many group.push(join(futs).with_label(...)) n/a

The last row uses future::join inside a future::Group: many futures collapse into a single progress line that sits alongside other rows in the Group. Streams do not have a join collapse, s— push each stream as its own row.

Example

This example demonstrates how to animate single futures, a group of futures and a stream. Run it with cargo run --example readme.

use std::time::Duration;

use async_io::Timer;
use futures_lite::StreamExt;
use strides::spinner::styles::{DOTS_3, SAND};

async fn animate_simple_future() {
    use strides::future::FutureExt as _;

    Timer::after(Duration::from_secs(2))
        .progress(DOTS_3)
        .with_label("some work going on for two seconds")
        .await;
}

async fn animate_two_futures_concurrently() {
    use strides::future::{FutureExt as _, Group};

    let mut group = Group::new(SAND).with_elapsed_time();
    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 animate_stream() {
    use strides::stream::StreamExt as _;

    let theme = strides::Theme::default()
        .with_spinner(DOTS_3)
        .with_bar(strides::bar::styles::THIN_LINE);

    futures_lite::stream::iter(0..100)
        .progress(theme, |_, item| *item as f64 / 100.0)
        .with_label("streaming 100 items")
        .then(|item| async move {
            Timer::after(Duration::from_millis(20)).await;
            item
        })
        .for_each(|_| {})
        .await;
}

fn main() {
    futures_lite::future::block_on(async {
        animate_simple_future().await;
        animate_two_futures_concurrently().await;
        animate_stream().await;
    })
}

See the examples directory for more elaborate uses including downloads, dynamic messages, per-task progress bars, and custom layouts.

Minimum supported Rust version

strides requires Rust 1.85 or newer.

License

MIT