author | Pierre-Yves David <pierre-yves.david@octobus.net> |
Tue, 11 Mar 2025 02:29:42 +0100 | |
branch | stable |
changeset 53042 | cdd7bf612c7b |
parent 52306 | a876ab6c3fd5 |
permissions | -rw-r--r-- |
52037
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
1 |
//! Progress-bar related things |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
2 |
|
52038
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
3 |
use std::{ |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
4 |
sync::atomic::{AtomicBool, Ordering}, |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
5 |
time::Duration, |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
6 |
}; |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
7 |
|
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
8 |
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle}; |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
9 |
|
52037
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
10 |
/// A generic determinate progress bar trait |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
11 |
pub trait Progress: Send + Sync + 'static { |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
12 |
/// Set the current position and optionally the total |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
13 |
fn update(&self, pos: u64, total: Option<u64>); |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
14 |
/// Increment the current position and optionally the total |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
15 |
fn increment(&self, step: u64, total: Option<u64>); |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
16 |
/// Declare that progress is over and the progress bar should be deleted |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
17 |
fn complete(self); |
3ae7c43ad8aa
rust: add `Progress` trait for progress bars
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
18 |
} |
52038
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
19 |
|
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
20 |
const PROGRESS_DELAY: Duration = Duration::from_secs(1); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
21 |
|
52306
a876ab6c3fd5
rust: fix `cargo doc` warnings
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52038
diff
changeset
|
22 |
/// A generic (determinate) progress bar. Stays hidden until `PROGRESS_DELAY` |
52038
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
23 |
/// to prevent flickering a progress bar for super fast operations. |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
24 |
pub struct HgProgressBar { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
25 |
progress: ProgressBar, |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
26 |
has_been_shown: AtomicBool, |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
27 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
28 |
|
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
29 |
impl HgProgressBar { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
30 |
// TODO pass config to check progress.disable/assume-tty/delay/etc. |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
31 |
/// Return a new progress bar with `topic` as the prefix. |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
32 |
/// The progress and total are both set to 0, and it is hidden until the |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
33 |
/// next call to `update` given that more than a second has elapsed. |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
34 |
pub fn new(topic: &str) -> Self { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
35 |
let template = |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
36 |
format!("{} {{wide_bar}} {{pos}}/{{len}} {{eta}} ", topic); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
37 |
let style = ProgressStyle::with_template(&template).unwrap(); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
38 |
let progress_bar = ProgressBar::new(0).with_style(style); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
39 |
// Hide the progress bar and only show it if we've elapsed more |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
40 |
// than a second |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
41 |
progress_bar.set_draw_target(ProgressDrawTarget::hidden()); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
42 |
Self { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
43 |
progress: progress_bar, |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
44 |
has_been_shown: false.into(), |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
45 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
46 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
47 |
|
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
48 |
/// Called whenever the progress changes to determine whether to start |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
49 |
/// showing the progress bar |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
50 |
fn maybe_show(&self) { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
51 |
if self.progress.is_hidden() |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
52 |
&& self.progress.elapsed() > PROGRESS_DELAY |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
53 |
{ |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
54 |
// Catch a race condition whereby we check if it's hidden, then |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
55 |
// set the draw target from another thread, then do it again from |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
56 |
// this thread, which results in multiple progress bar lines being |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
57 |
// left drawn. |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
58 |
let has_been_shown = |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
59 |
self.has_been_shown.fetch_or(true, Ordering::Relaxed); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
60 |
if !has_been_shown { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
61 |
// Here we are certain that we're the only thread that has |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
62 |
// set `has_been_shown` and we can change the draw target |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
63 |
self.progress.set_draw_target(ProgressDrawTarget::stderr()); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
64 |
self.progress.tick(); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
65 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
66 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
67 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
68 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
69 |
|
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
70 |
impl Progress for HgProgressBar { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
71 |
fn update(&self, pos: u64, total: Option<u64>) { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
72 |
self.progress.update(|state| { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
73 |
state.set_pos(pos); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
74 |
if let Some(t) = total { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
75 |
state.set_len(t) |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
76 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
77 |
}); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
78 |
self.maybe_show(); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
79 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
80 |
|
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
81 |
fn increment(&self, step: u64, total: Option<u64>) { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
82 |
self.progress.inc(step); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
83 |
if let Some(t) = total { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
84 |
self.progress.set_length(t) |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
85 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
86 |
self.maybe_show(); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
87 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
88 |
|
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
89 |
fn complete(self) { |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
90 |
self.progress.finish_and_clear(); |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
91 |
} |
92e23ba257d1
rust-hg-cpython: add an `HgProgressBar` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52037
diff
changeset
|
92 |
} |