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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#![deny(unsafe_code)]
/*!
Prodash is a dashboard for displaying the progress of concurrent application.

It consists of two parts

* a `Tree` to gather progress information and messages
* a terminal user interface which displays this information, along with optional free-form information provided by the application itself

Even though the `Tree` is not async, it's meant to be transparent and non-blocking performance wise, and benchmarks seem to indicate this
is indeed the case.

The **terminal user interface** seems to be the least transparent part, but can be configured to refresh less frequently.

# Terminal User Interface

By default, a TUI is provided to visualize all state. Have a look at [the example provided in the tui module](./tui/index.html).

**Please note** that it is behind the `tui-renderer` feature toggle, which is enabled by default.

# Logging

If the feature `log-renderer` is enabled (default), most calls to `progress` will also be logged.
That way, even without a terminal user interface, there will be progress messages.
Please note that logging to stdout should not be performed with this feature enabled and a terminal user interface is shown, as this will
seriously interfere with the TUI.

# A demo application

Please have a look at the [dashboard demo](https://github.com/Byron/crates-io-cli-rs/blob/master/prodash/examples/dashboard.rs).

[![asciicast](https://asciinema.org/a/301838.svg)](https://asciinema.org/a/301838)

Run it with `cargo run --example dashboard` and see what else it can do by checking out `cargo run --example dashboard -- --help`.

# Changelog

## v5.0.0 - Support for windows by using Crossbeam by default

A first low-effort move to the latest version should be to set the dependency to
`default-features = false, features = ["tui-renderer", "with-termion", "localtime", "log-renderer"]`
to get the same configuration as before.

To try crossbeam, use `with-crossbeam` instead of `with-termion`.

If you have been using the event stream to send your own keys, swap `termion::event::Key` with `prodash::tui::input::Key`.

## v4.1.0 - Allow the TUI to automatically stop if there is no progress to display

This way, it's easier to use `prodash::tui` for visualizing finite tasks, which originally it wasn't intended for.

Previously, in order to achieve the same, one would have to initialize the TUI with an event stream and send the Event
for shutting down once the task at hand is complete.

## v4.0.5 - Fix delayed reset of the terminal

Previously even after the future was dropped, it seemed like the terminal wasn't reset and the user was required
to explicitly flush stdout to make the changes appear. This is due to the flushing previously happening too early,
that is, before the `terminal` was dropped which emits the respective terminal escape codes at this time.

Now the terminal instance is dropped explicitly right before emitting a flush.
One might argue that the flush should happen in the terminal instance itself, but fixing that is out of scope.

## v4.0.4 - Simplify `message()` trait bounds

## v4.0.3 - Remove piper in favor of futures-channel (which was included anyway)

## v4.0.2 - Upgrade to latest TUI and TUI-react crates

## v4.0.1 - Reduce theoretical direct dependencies by not using 'futures' crate directly

## v4.0.0 - Switch from futures executor to smol

This actually simplifies some parts of the implementation, while fixing issues along futures not being dropped while they
were on a thread pool. Now, for the example, no threadpool is used anymore.

**Note** that this also means that in order for each frame to be drawn, one would have to invoke `smol::run` in one thread to
activate the reactor which processes the timeout/ticker. Alternatively, one would send `Tick` events through a channel to trigger
a redraw manually.

## v3.6.3 - Fix out-of-bounds access (and panic) due to new and more precise progress bars

## v3.6.2 - More horizontally precise progress bars; progress bars are now have lines between them vertically

## v3.6.1 - Properly respond to state changes even when 'redraw_only_on_state_change' is enabled

## v3.6.0 - A TUI option to only redraw if the progress actually changed. Useful if the change rate is lower than the frames per second.

## v3.5.1 - Don't copy messages if the message pane is hidden, saving time

## v3.5.0 - Cleaner visuals for hierarchical progress items, these won't show lines if there are no direct children with progress

## v3.4.1 - Enable localtime support by default

## v3.4.0 - Even nicer tree rendering, along with screen space savings

## v3.3.0 - Much nicer task tree visualization

## v3.2.0 - Application can control if the GUI will respond to interrupt requests

## v3.1.1 - Bugfix (really): Finally delayed column resizing works correctly.

## v3.1.0 - Tree::halted(…) indicates interruptable tasks without progress. Tree::blocked(…) means non-interruptable without progress.

## v3.0.2 - Bugfix: Allow column-width computation to recover from becoming 0

## v3.0.1 - Bugfix: Don't allow values of 0 for when to recompute task column widths

## v3.0.0 - New TUI option to delay computation of column width for stability with rapidly changing tasks

## v2.1.0 - Optional cargo feature "localtime" shows all times in the local timezone

## v2.0.1 - fix integer underflow with graphemes that report width of 0

## v2.0.0

* BREAKING: `progress.blocked(eta)` now takes a statically known reason for the blocked state `progress.blocked(reason, eta)`. This is
  useful to provide more context.

## v1.2.0

* Support for eta messages in blocked unbounded tasks

## v1.1.6

* improve API symmetry by providing a `Tree::name()` to accompany `Tree::set_name(…)`

## v1.1.5

* Flush stdout when the TUI stopped running. That way, the alternate/original screen will be shown right away.

## v1.1.4

* Don't pretend to use &str if in fact an owned string is required. This caused unnecessary clones for those who pass owned strings.

## v1.1.3

* hide cursor or a nicer visual experience

## v1.1.0

* fix toggles - previously prodash, withoug tui, would always build humantime and unicode width
* add support for logging as user interface

*/
mod config;
pub mod tree;

pub use config::TreeOptions;
pub use tree::Root as Tree;

#[cfg(test)]
mod tree_tests;

#[cfg(feature = "tui-renderer")]
pub mod tui;

#[cfg(feature = "log-renderer")]
pub use log::info;
#[cfg(feature = "log-renderer")]
pub use log::warn;

#[cfg(not(feature = "log-renderer"))]
mod log {
    /// Stub
    #[macro_export(local_inner_macros)]
    macro_rules! warn {
        (target: $target:expr, $($arg:tt)+) => {};
        ($($arg:tt)+) => {};
    }
    /// Stub
    #[macro_export(local_inner_macros)]
    macro_rules! info {
        (target: $target:expr, $($arg:tt)+) => {};
        ($($arg:tt)+) => {};
    }
}