1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! strides is an *async-first* crate to support building command line tools which display progress
//! to the user. The purpose is similar to that of the widely used indicatif crate but focuses on
//! integrating with async futures and streams and drive progress animations based on polling state.
//! For this strides provides utilities to integrate UI elements as part of the [`Future`] and
//! [`Stream`] abstractions.
//!
//! ## Spinners
//!
//! A spinner is a UI element that represents ongoing work. It is usually iconified as a circular
//! motion but anything that streams Unicode characters can be used. To create a spinner, import the
//! [`Spinner`] struct and pass it a string slice:
//!
//! ```rust
//! let abc = strides::spinner::Spinner::new("abc");
//! ```
//!
//! The [`ticks()`](crate::spinner::Spinner::ticks) method returns an infinite stream that cycles
//! through the characters of the string slice. The rate at which characters are cycled is set to
//! every 80ms and can be changed with the
//! [`with_interval()`](crate::spinner::Spinner::with_interval) function.
//!
//! The [`spinner::styles`] module provides a few pre-defined spinner
//! styles.
//!
//! ## Bars
//!
//! A [`Bar`] renders fractional progress as a strip of characters. It is defined by two characters,
//! one for the empty portion and one for the filled portion. In addition, optional borders,
//! in-between separator, and per-portion colors can be configured via the builder methods on
//! [`Bar`].
//!
//! Create a new bar with [`Bar::new()`](crate::bar::Bar::new) or pick a pre-defined variant from
//! [`bar::styles`]:
//!
//! ```rust
//! // This customizes the pre-defined thin line style with additional borders and colors for the
//! // filled portion.
//! let bar = strides::bar::styles::THIN_LINE
//! .with_border("[", "]")
//! .with_filled_style(owo_colors::Style::new().bright_purple());
//! ```
//!
//! The bar is attached to a [`Theme`] with [`with_bar()`](crate::Theme::with_bar). The bar width
//! defaults to the terminal size and can be overridden with
//! [`with_bar_width()`](crate::Theme::with_bar_width).
//!
//! ## Themes
//!
//! A [`Theme`] bundles a [`Spinner`](crate::spinner::Spinner) and a [`Bar`](crate::bar::Bar) into a
//! single configuration object that can be passed to both the futures and streams progress APIs:
//!
//! ```rust
//! let theme = strides::Theme::new()
//! .with_bar(strides::bar::styles::PARALLELOGRAM)
//! .with_spinner(strides::spinner::styles::DOTS_3);
//! ```
//!
//! A bare [`Spinner`](crate::spinner::Spinner) can also be passed directly wherever a
//! [`Theme`] is expected.
//!
//! ## Layout
//!
//! The order, spacing and per-element formatting of a progress line is controlled by a [`Layout`],
//! an ordered list of [`Segment`]s. [`Layout::DEFAULT`] renders elapsed time, spinner, label, bar
//! and message. Segments with nothing to show are skipped, so spacing stays correct. Attach a
//! custom layout with [`Theme::with_layout`]:
//!
//! ```rust
//! use strides::layout::{Layout, Segment};
//!
//! let theme = strides::Theme::new().with_layout(
//! Layout::new(&[])
//! .with_segment(Segment::spinner())
//! .with_segment(Segment::elapsed().with_border("[", "]"))
//! .with_segment(Segment::bar())
//! .with_segment(Segment::message()),
//! );
//! ```
//!
//! ## Futures
//!
//! Import the [`FutureExt`](crate::future::FutureExt) extension trait and call
//! [`progress()`](crate::future::FutureExt::progress) with a [`Theme`] on any [`Future`] to animate
//! its state, which is either in-progress or done. The return value double acts as a
//! [`ProgressBuilder`](crate::future::ProgressBuilder) for further customization of the animation:
//!
//! - [`with_label`](crate::future::ProgressBuilder::with_label) sets a static label,
//! - [`with_messages`](crate::future::ProgressBuilder::with_messages) installs a
//! [`Stream`](futures_lite::Stream) whose values replace the displayed message as they arrive,
//! - [`with_progress`](crate::future::ProgressBuilder::with_progress) drives the progress bar from a
//! `Stream<Item = f64>`.
//!
//! ```rust
//! use strides::future::FutureExt;
//! use strides::spinner::styles::DOTS_3;
//!
//! # futures_lite::future::block_on(
//! # async {
//! // Simulate work by waiting for three seconds.
//! futures_timer::Delay::new(std::time::Duration::from_secs(3))
//! .progress(DOTS_3)
//! .with_label("this will take some time")
//! .await;
//! # }
//! # );
//! ```
//!
//! For multiple concurrent futures use [`Group`], which renders one line per task
//! with optional per-task progress bars and dynamic messages.
//!
//! ## Streams
//!
//! Import the [`StreamExt`](crate::stream::StreamExt) extension trait and call
//! [`progress()`](crate::stream::StreamExt::progress) with a fraction closure. The closure receives
//! the monotonically increasing item number (starting at 1) and a reference to the item, so the
//! fraction can be derived from a known total or from the item itself (e.g. accumulated bytes /
//! `Content-Length`). The returned [`StreamProgressBuilder`](crate::stream::StreamProgressBuilder)
//! accepts a [`with_messages`](crate::stream::StreamProgressBuilder::with_messages) stream for
//! dynamic text.
//!
//! ```rust
//! use futures_lite::{StreamExt as _, stream};
//! use strides::stream::StreamExt;
//! use strides::Theme;
//! use strides::{bar, spinner};
//!
//! let theme = Theme::new()
//! .with_spinner(spinner::styles::DOTS_3)
//! .with_bar(bar::styles::SHADED);
//!
//! # futures_lite::future::block_on(async {
//! let total = 100;
//! stream::iter(0..total)
//! .progress(theme, move |i, _| i as f64 / total as f64)
//! .for_each(|_| {})
//! .await;
//! # });
//! ```
//!
//! ## Output
//!
//! strides currently renders all progress output to `stdout`. When `stdout` is not a terminal (for
//! example, when the program's output is redirected to a file or piped to another command) progress
//! rendering is suppressed entirely. Futures and streams still run to completion, but no spinner,
//! bar, or message bytes are written.
//!
//! [`Future`]: std::future::Future
//! [`Stream`]: futures_lite::Stream
//! [`Group`]: crate::future::Group
//! [`Spinner`]: crate::spinner::Spinner
//! [`Bar`]: crate::bar::Bar
pub use ;
pub use Theme;