Progress Bars¶
Fast-Rich provides a powerful progress bar system for tracking long-running tasks with multi-bar support, spinners, ETA, and customizable columns.
Quick Example¶
use fast_rich::prelude::*;
use std::thread;
use std::time::Duration;
fn main() {
let progress = Progress::new();
let task = progress.add_task("Processing...", Some(100));
for _ in 0..100 {
thread::sleep(Duration::from_millis(50));
progress.advance(task, 1);
}
}
Multi-Task Progress¶
Track multiple tasks simultaneously:
use fast_rich::prelude::*;
use std::thread;
use std::time::Duration;
fn main() {
let progress = Progress::new();
let download = progress.add_task("Downloading", Some(100));
let extract = progress.add_task("Extracting", Some(50));
let install = progress.add_task("Installing", Some(200));
// Simulate work
for i in 0..100 {
thread::sleep(Duration::from_millis(30));
progress.advance(download, 1);
if i % 2 == 0 {
progress.advance(extract, 1);
}
if i % 1 == 0 {
progress.advance(install, 2);
}
}
}
Output:
Downloading ━━━━━━━━━━━━━━━━━━━━ 100% 00:00
Extracting ━━━━━━━━━━━━━━━━━━━━ 100% 00:00
Installing ━━━━━━━━━━━━━━━━━━━━ 100% 00:00
Task Management¶
Adding Tasks¶
// Known total (shows percentage)
let task1 = progress.add_task("Download", Some(total_bytes));
// Unknown total (shows spinner)
let task2 = progress.add_task("Scanning", None);
Updating Progress¶
// Advance by amount
progress.advance(task_id, 10);
// Set absolute progress
progress.set_completed(task_id, 50);
// Mark as complete
progress.set_completed(task_id, total);
Updating Description¶
Spinners¶
For tasks with unknown duration, use spinners:
use fast_rich::prelude::*;
fn main() {
let spinner = Spinner::new()
.message("Loading...")
.style(SpinnerStyle::Dots);
// Use with Status for single-task indication
let status = Status::new("Processing data");
// ... do work ...
}
Spinner Styles¶
| Style | Pattern |
|---|---|
SpinnerStyle::Dots |
⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏ |
SpinnerStyle::Line |
- \ | / |
SpinnerStyle::Braille |
⣾ ⣽ ⣻ ⢿ ⡿ ⣟ ⣯ ⣷ |
Customizable Columns¶
Progress bars can display different information columns:
use fast_rich::progress::*;
let progress = Progress::new()
.with_columns(vec![
ProgressColumn::Description,
ProgressColumn::Bar,
ProgressColumn::Percentage,
ProgressColumn::TimeRemaining,
]);
Available Columns¶
| Column | Description |
|---|---|
Description |
Task description text |
Bar |
Visual progress bar |
Percentage |
Completion percentage |
Completed |
Completed/Total count |
TimeRemaining |
Estimated time remaining |
TransferSpeed |
Transfer speed (bytes/sec) |
Spinner |
Animated spinner |
Snapshot Rendering¶
For non-interactive output or logging, render progress as a string:
let progress = Progress::new();
let task = progress.add_task("Working...", Some(100));
progress.advance(task, 50);
// Get rendered string
let output = progress.render_to_string();
println!("{}", output);
This is useful for: - Logging progress state - Testing - Non-interactive environments
Real Terminal Output¶
Progress bar in action
Code
use fast_rich::prelude::*;
use std::thread;
use std::time::Duration;
fn main() {
let progress = Progress::new();
let download = progress.add_task("Downloading", Some(100));
let extract = progress.add_task("Extracting", Some(50));
let install = progress.add_task("Installing", Some(200));
for i in 0..100 {
thread::sleep(Duration::from_millis(30));
progress.advance(download, 1);
if i % 2 == 0 { progress.advance(extract, 1); }
progress.advance(install, 2);
}
}
Run it
What you'll see

Tips¶
Use with Live Display
For the smoothest animations, combine Progress with Live:
Update Rate
Don't update progress too frequently. For very fast iterations, batch updates or use a timer to limit refresh rate.
Terminal Compatibility
Progress bars use ANSI cursor control. They work best in interactive terminals. In CI environments, consider using snapshot rendering or simpler output.