-
Notifications
You must be signed in to change notification settings - Fork 241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can I implement a progress bar for this kind of screen scrolling? #543
Comments
I don't have an opinion off the top of my head. Just try to implement it? |
Sorry~, perhaps I didn't express myself well. Using Is there a more elegant way to achieve this scrolling effect? It's like every time I use This may not be feasible, as you know, I lack knowledge of terminal display. |
What you could do to achieve that effect is, for keeping track of the message, use
Note that for 1., it would mean either:
I can't think of a way to avoid allocations for the message when setting it on the progress bar with the current API. |
I did something kind off similar on a project, that's not open-sourced so I can't share the code, I had a |
I apologize for the delayed response as it appears my email forgot about me. As for what was previously mentioned, I implemented the function using an unsightly piece of code as follows. use std::{thread, time};
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
const N: usize = 3;
struct MyMultiProgress {
m: MultiProgress,
main: ProgressBar,
pbs: Vec<ProgressBar>,
msgs: Vec<String>,
cnt: usize,
}
impl MyMultiProgress {
fn new(len: u64) -> Self {
let spinner_style = ProgressStyle::with_template("{wide_msg}").unwrap();
let m = MultiProgress::new();
let mut pbs = Vec::with_capacity(N);
for _ in 0..N {
let pb = m.add(ProgressBar::new(0));
pb.set_style(spinner_style.clone());
pbs.push(pb);
}
let main = m.add(ProgressBar::new(len));
Self {
m,
main,
pbs,
msgs: Vec::with_capacity(N),
cnt: 0,
}
}
fn add_msg(&mut self, msg: String) {
if self.msgs.len() < N {
self.msgs.push(msg);
} else {
self.msgs[self.cnt % N] = msg;
}
self.cnt += 1;
self.show();
}
fn show(&mut self) {
if self.msgs.len() < N {
for i in 0..self.msgs.len() {
self.pbs[i].set_message(self.msgs[i].clone());
}
} else {
for i in 0..N {
self.pbs[i].set_message(self.msgs[(self.cnt + i) % N].clone());
}
}
}
fn inc(&mut self, n: u64) {
self.main.inc(n);
}
fn clean(&mut self) {
for pb in &mut self.pbs {
pb.finish();
}
self.main.finish();
self.m.clear().unwrap();
}
}
#[test]
fn multiple_bar() {
let interval = time::Duration::from_millis(1000);
let mut m = MyMultiProgress::new(100);
for i in 0..100 {
m.add_msg(format!("hello: {}", i));
m.inc(1);
thread::sleep(interval);
}
m.clean();
} However, besides the inconvenience of having to copy strings every time, there are some unexpected issues, such as messages not immediately displaying on the terminal every time they are set. Specifically, if the interval is set to 1000ms, it works perfectly. However, if it is set to 100ms or lower, there may be some overlapping. |
Does this resemble what I showed above? |
heya, I'm not sure why the numbers overlap are you using otherwise it needs some investigation into |
I did not use I try to use |
This probably happens because of indicatif's drawing rate limits. |
I am using Docker and I find its progress bar very cool. Can Indicatif implement this feature?
Maybe I can use
MultiProgress
to achieve it: use one as the main progress bar and the others as secondary progress bars which only displaying personalized messages.However, to implement the scrolling function, I need to continuously scroll the message of the secondary progress bar, so
clone
the message every time. Is this a good implementation approach?The text was updated successfully, but these errors were encountered: