Skip to content

Commit aa4b0a9

Browse files
committed
Big docs update
1 parent ea70fed commit aa4b0a9

File tree

2 files changed

+82
-53
lines changed

2 files changed

+82
-53
lines changed

README.md

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,3 @@ fn main() -> std::io::Result<()> {
6464
```
6565

6666
[![asciicast](https://asciinema.org/a/oPI37ohOY8yhDxomTzHCsR4sw.svg)](https://asciinema.org/a/oPI37ohOY8yhDxomTzHCsR4sw)
67-
68-
## Project status
69-
70-
This is a young library. The API will not break gratuitously, but it may change
71-
as we learn how to better express application needs.
72-
73-
Changes are described in the changelog in the top-level Rustdoc (in
74-
`src/lib.rs`).
75-
76-
Constructive feedback on integrations that work well, or that don't work well,
77-
is welcome.
78-
79-
When the API has settled this will be promoted to 1.0 and then we'll avoid API
80-
breakage.

src/lib.rs

Lines changed: 82 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,75 @@
22

33
/*!
44
5-
Nutmeg draws terminal progress bars whose appearance is completely controlled
6-
by the application.
5+
Nutmeg draws multi-line terminal progress bars to an ANSI terminal.
6+
7+
By contrast to other Rust progress-bar libraries, Nutmeg has no built-in
8+
concept of what the progress bar or indicator should look like: the application
9+
has complete control.
710
811
# Concept
912
10-
By contrast to other Rust progress-bar libraries, Nutmeg has no built-in
11-
concept of what the progress bar or indicator should look like: this is
12-
entirely under the control of the application.
13+
Nutmeg has three key types: Model, View, and Options.
1314
14-
The application is responsible for:
15+
## Model
1516
16-
1. Defining a "model" type that holds whatever information is relevant to drawing
17-
progress bars: the time elapsed, number of things processed, currently active tasks,
18-
total expected work, whatever...
19-
2. Implementing the [Model] trait for your model. This has only one mandatory method,
20-
[Model::render], which renders the model into styled text.
21-
3. Constructing a [View] to draw a progress bar.
22-
4. Updating the model when appropriate by calling [View::update], passing a callback
23-
that mutates the state.
24-
5. Printing any messages while the [View] is in use
25-
via `writeln!(view, ...)` or [View::message].
17+
A type implementing the [Model] trait holds whatever information is needed to draw the
18+
progress bars. This might be the start time of the operation, the number of things
19+
processed, the amount of data transmitted or received, the currently active tasks, whatever...
2620
27-
Some applications might find the provided [models] suit their needs, in which case they
28-
can skip steps 1 and 2.
21+
The Model can be any of these things, from simplest to most powerful:
2922
30-
The application can control colors and styling by including ANSI
31-
escape sequences in the rendered string, for example by using the
32-
`yansi` crate.
23+
1. Any type that implements [std::fmt::Display], such as a String or integer.
24+
2. One of the provided [models].
25+
3. An application-defined struct (or enum or other type) that implements [Model].
26+
27+
The model is responsible for rendering itself into a String, optionally with ANSI styling,
28+
by implementing [Model::render] (or [std::fmt::Display]). Applications might
29+
choose to use any of the Rust crates that can render ANSI control codes into a
30+
string, such as yansi.
3331
3432
The application is responsible for deciding whether or not to
35-
color its output, for example by consulting `$CLICOLORS`.
33+
color its output, for example by consulting `$CLICOLORS` or its own command line.
34+
35+
Models can optionally provide a "final message" by implementing
36+
[Model::final_message], which will be left on the screen when the view is finished.
37+
38+
If one overall operation represents several concurrent operations then the
39+
application can, for example, represent them in a collection within the Model, and
40+
render them into multiple lines, or multiple sections in a single line.
41+
(See `examples/multithreaded.rs`.)
3642
37-
The Nutmeg library is responsible for:
43+
## View
3844
39-
* Periodically drawing the progress bar in response to updates, including
40-
horizontally truncating output to fit on the screen.
41-
* Removing the progress bar when the view is finished or dropped.
42-
* Coordinating to hide the bar to print text output, and restore it
43-
afterwards.
44-
* Limiting the rate at which updates are drawn to the screen.
45-
* Disabling progress bars if stdout is not a terminal.
45+
To get the model on to the terminal the application must create a [View], typically
46+
with [View::new], passing the initial model. The view takes ownership of the model.
47+
48+
The application then updates the model state via [View::update], which may decide
49+
to paint the view to the terminal, subject to rate-limiting and other constraints.
50+
51+
The view has an internal mutex and is `Send` and `Sync`,
52+
so it can be shared freely across threads.
53+
54+
The view automatically erases itself from the screen when it is dropped.
55+
56+
While the view is on the screen, the application can print messages interleaved
57+
with the progress bar by either calling [View::message], or treating it as a [std::io::Write]
58+
destination, for example for [std::writeln].
4659
4760
Errors in writing to the terminal cause a panic.
4861
49-
Nutmeg only supports ANSI terminals, which are supported on all Unix
50-
and Windows 10 and later.
62+
## Options
63+
64+
A small [Options] type, passed to the View constructor, allows turning progress bars
65+
off, setting rate limits, etc.
66+
67+
In particular applications might choose to construct all [Options] from a single function
68+
that respects an application-level option for whether progress bars should be drawn.
69+
70+
## Utility functions
71+
72+
This crate also provides a few free functions such as [estimate_remaining],
73+
that can be helpful in implementing [Model::render].
5174
5275
# Example
5376
@@ -96,16 +119,36 @@ fn main() -> std::io::Result<()> {
96119
97120
See the `examples/` directory for more.
98121
99-
# Other features
122+
# Performance
100123
101-
The [models] module provides some predefined models, for example counting `i` of `n` items
102-
of work complete with an extrapolated ETA.
124+
Nutmeg's goal is that [View::update] is cheap enough that applications can call it
125+
fairly freely when there are small updates. The library takes care of rate-limiting
126+
updates to the terminal, as configured in the [Options].
103127
104-
Models can optionally provide a "final message" by implementing [Model::final_message], which
105-
will be left on the screen when the view is finished.
128+
Each call to [View::update] will take a `parking_lot` mutex and check the
129+
system time, in addition to running the callback and some function-call overhead.
106130
107-
This crate also provides a few free functions such as [estimate_remaining],
108-
that can be helpful in rendering progress bars.
131+
The model is only rendered to a string, and the string printed to a terminal, if
132+
sufficient time has passed since it was last painted.
133+
134+
The `examples/bench.rs` sends updates as fast as possible to a model containing a
135+
single `u64`, from a single thread. As of 2022-03-22, on a 2019 Core i9 Macbook Pro,
136+
it takes about 500ms to send 10e6 updates, or 50ns/update.
137+
138+
# Project status
139+
140+
Nutmeg is a young library. Although the API will not break gratuitously,
141+
it may evolve in response to experience and feedback in every pre-1.0 release.
142+
143+
If the core ideas prove useful and the API remains stable for an extended period
144+
then the author intends to promote it to 1.0, after which the API will respect
145+
Rust stability conventions.
146+
147+
Changes are described in the [changelog](#Changelog) in the top-level Rustdoc,
148+
below.
149+
150+
Constructive feedback on integrations that work well, or that don't work well,
151+
is welcome.
109152
110153
# Potential future features
111154

0 commit comments

Comments
 (0)