rust statusbars are actually pretty amazing
cargo devel CI / cargo CI (push) Successful in 3m16s Details

This commit is contained in:
Christoph J. Scherr 2024-06-27 15:45:29 +02:00
parent 84db59d290
commit c84672cf78
4 changed files with 208 additions and 0 deletions

42
Cargo.lock generated
View File

@ -1224,12 +1224,34 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "indicatif"
version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3"
dependencies = [
"console",
"instant",
"number_prefix",
"portable-atomic",
"unicode-width",
]
[[package]]
name = "inflections"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a"
[[package]]
name = "instant"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
dependencies = [
"cfg-if",
]
[[package]]
name = "intl-memoizer"
version = "0.5.2"
@ -1565,6 +1587,12 @@ dependencies = [
"libc",
]
[[package]]
name = "number_prefix"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
name = "object"
version = "0.36.0"
@ -1790,6 +1818,12 @@ dependencies = [
"plotters-backend",
]
[[package]]
name = "portable-atomic"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
[[package]]
name = "powerfmt"
version = "0.2.0"
@ -2227,6 +2261,14 @@ dependencies = [
"rusqlite",
]
[[package]]
name = "statusline"
version = "0.1.0"
dependencies = [
"indicatif",
"rand",
]
[[package]]
name = "strsim"
version = "0.11.1"

View File

@ -25,9 +25,11 @@ members = [
"members/diesel-demo",
"members/ptlog",
"members/hello-world",
"members/statusline",
]
default-members = [
".",
"members/statusline",
"members/ptlog",
"members/diesel-demo",
"members/onlytoken",

View File

@ -0,0 +1,8 @@
[package]
name = "statusline"
version = "0.1.0"
edition = "2021"
[dependencies]
indicatif = "0.17.8"
rand = "0.8.5"

View File

@ -0,0 +1,156 @@
// most of this is stolen from the indicatif examples (also MIT)
use std::cmp::min;
use std::fmt::Write;
use std::thread::{self, sleep_ms};
use std::time::Duration;
use indicatif::{MultiProgress, ProgressBar, ProgressIterator, ProgressState, ProgressStyle};
use rand::Rng;
fn main() {
// b0();
// b1();
// b2();
b3();
b4();
b5();
b6();
}
fn b0() {
let bar = ProgressBar::new(1_000);
for _ in 0..1_000 {
bar.inc(1);
sleep_ms(1);
}
bar.finish();
}
fn b1() {
let bar = ProgressBar::new_spinner();
bar.enable_steady_tick(Duration::from_millis(100));
for _ in 0..1_000 {
bar.inc(1);
sleep_ms(1);
}
bar.finish();
}
fn b2() {
for _ in (0..1_000).progress() {
sleep_ms(1);
}
}
fn b3() {
let bar = ProgressBar::new(1_000);
bar.set_style(
ProgressStyle::with_template(
"[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}",
)
.unwrap()
.progress_chars("▄▌_"),
);
for _ in 0..1_000 {
bar.inc(1);
sleep_ms(1);
}
bar.finish();
}
fn b4() {
use indicatif::{HumanBytes, HumanCount, HumanDuration, HumanFloatCount};
assert_eq!("3.00 MiB", HumanBytes(3 * 1024 * 1024).to_string());
assert_eq!(
"8 seconds",
HumanDuration(Duration::from_secs(8)).to_string()
);
assert_eq!("33,857,009", HumanCount(33857009).to_string());
assert_eq!(
"33,857,009.1235",
HumanFloatCount(33857009.123456).to_string()
);
}
fn b5() {
let mut downloaded = 0;
let total_size = 231331;
let pb = ProgressBar::new(total_size);
pb.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})")
.unwrap()
.with_key("eta", |state: &ProgressState, w: &mut dyn Write| write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap())
.progress_chars("#>-"));
while downloaded < total_size {
let new = min(downloaded + 223211, total_size);
downloaded = new;
pb.set_position(new);
thread::sleep(Duration::from_millis(12));
}
pb.finish_with_message("downloaded");
}
fn b6() {
let m = MultiProgress::new();
let sty = ProgressStyle::with_template(
"[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}",
)
.unwrap()
.progress_chars("##-");
let n = 20;
let pb = m.add(ProgressBar::new(n));
pb.set_style(sty.clone());
pb.set_message("todo");
let pb2 = m.add(ProgressBar::new(n));
pb2.set_style(sty.clone());
pb2.set_message("finished");
let pb3 = m.insert_after(&pb2, ProgressBar::new(1024));
pb3.set_style(sty);
m.println("starting!").unwrap();
let mut threads = vec![];
let m_clone = m.clone();
let h3 = thread::spawn(move || {
for i in 0..1024 {
thread::sleep(Duration::from_millis(2));
pb3.set_message(format!("item #{}", i + 1));
pb3.inc(1);
}
m_clone.println("pb3 is done!").unwrap();
pb3.finish_with_message("done");
});
for i in 0..n {
thread::sleep(Duration::from_millis(15));
if i == n / 3 {
thread::sleep(Duration::from_secs(2));
}
pb.inc(1);
let m = m.clone();
let pb2 = pb2.clone();
threads.push(thread::spawn(move || {
let spinner = m.add(ProgressBar::new_spinner().with_message(i.to_string()));
spinner.enable_steady_tick(Duration::from_millis(100));
thread::sleep(
rand::thread_rng().gen_range(Duration::from_secs(1)..Duration::from_secs(5)),
);
pb2.inc(1);
}));
}
pb.finish_with_message("all jobs started");
for thread in threads {
let _ = thread.join();
}
let _ = h3.join();
pb2.finish_with_message("all jobs done");
m.clear().unwrap();
}