indicatif is a Rust library designed to provide user-friendly progress indicators for command-line applications. It allows developers to easily display progress bars, spinners, and other visual cues for long-running operations, significantly enhancing the user experience.
Key features and concepts of indicatif include:
1. ProgressBar: The core component for displaying progress. It can be configured to show a definite progress (e.g., 0% to 100%) or an indefinite progress (a spinner).
2. Customizable Styles: `indicatif` offers extensive customization options for progress bar appearance. You can define custom templates using placeholders like `{spinner}`, `{msg}`, `{pos}`, `{len}`, `{percent}`, `{elapsed}`, `{eta}`, `{per_sec}`, etc., to control what information is displayed and how it's formatted.
3. Spinners: For tasks where the total duration is unknown, `indicatif` can display a spinner. Spinners cycle through a set of characters to indicate ongoing activity. These are also created using `ProgressBar` but with a spinner style.
4. Messages: Progress bars can display dynamic messages alongside the progress, which can be updated during execution to provide more context to the user.
5. MultiProgress: For applications performing multiple concurrent or sequential tasks, `MultiProgress` allows you to manage and display several progress bars simultaneously, stacking them neatly in the terminal.
6. Automatic Rate and ETA: `indicatif` automatically calculates and displays the current processing rate (items per second) and estimated time of arrival (ETA) based on the progress made.
7. Thread Safety: `indicatif` components are thread-safe, making them suitable for use in multi-threaded applications where progress updates might come from different threads.
8. Logging Integration: It can also integrate with logging systems, allowing progress updates to be part of the application's overall log output.
Using `indicatif` typically involves:
* Creating a `ProgressBar` instance, often from a total length or using a spinner style.
* Iterating through your work, calling `inc()` or `set_position()` on the `ProgressBar` to update its state.
* Calling `finish()` or `finish_with_message()` when the task is complete to finalize the progress bar's display.
It's an invaluable library for any CLI application that involves tasks that aren't instantaneous, providing users with clear visual feedback and improving the perceived responsiveness of the software.
Example Code
use indicatif::{ProgressBar, ProgressStyle};
use std::{thread, time::Duration};
fn main() {
// --- Example 1: Basic Progress Bar ---
println!("\n--- Demonstrating a basic progress bar ---");
let total_items = 100;
let pb = ProgressBar::new(total_items);
// You can customize the style. This is a common one.
pb.set_style(ProgressStyle::default_bar()
.template("[{elapsed_precise}] {bar:40.cyan/blue} {pos}/{len} ({percent}%) {msg}")
.progress_chars("-"));
for i in 0..total_items {
// Simulate some work being done
thread::sleep(Duration::from_millis(50));
pb.inc(1);
if i == total_items / 2 {
pb.set_message("Halfway there!");
}
}
pb.finish_with_message("Download complete!");
// --- Example 2: Spinner for indefinite tasks ---
println!("\n--- Demonstrating a spinner for an indefinite task ---");
let spinner = ProgressBar::new_spinner();
spinner.set_style(ProgressStyle::default_spinner()
.template("{spinner:.green} {msg}")
.tick_chars("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏")); // Custom spinner characters
spinner.set_message("Processing files...");
spinner.enable_steady_tick(Duration::from_millis(100)); // Update spinner every 100ms
// Simulate an indefinite task that takes some time
thread::sleep(Duration::from_secs(3));
spinner.finish_with_message("Files processed successfully!");
// --- Example 3: ProgressBar with custom message update ---
println!("\n--- Demonstrating a progress bar with dynamic messages ---");
let steps = 5;
let pb2 = ProgressBar::new(steps);
pb2.set_style(ProgressStyle::default_bar()
.template("[{elapsed_precise}] {bar:25.yellow/red} {pos}/{len} {msg}")
.progress_chars("-> "));
pb2.set_message("Initializing...");
thread::sleep(Duration::from_millis(500));
pb2.inc(1);
pb2.set_message("Loading configuration...");
thread::sleep(Duration::from_millis(700));
pb2.inc(1);
pb2.set_message("Connecting to database...");
thread::sleep(Duration::from_millis(1000));
pb2.inc(1);
pb2.set_message("Fetching data...");
thread::sleep(Duration::from_millis(1200));
pb2.inc(1);
pb2.set_message("Finalizing...");
thread::sleep(Duration::from_millis(800));
pb2.inc(1);
pb2.finish_with_message("Task complete!");
println!("\nAll demonstrations finished.");
}








indicatif