Skip to content
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

Provide an easy way to define an updated text when creating a spinner #12

Closed
avsaase opened this issue Dec 18, 2022 · 5 comments · Fixed by #13
Closed

Provide an easy way to define an updated text when creating a spinner #12

avsaase opened this issue Dec 18, 2022 · 5 comments · Fixed by #13
Assignees
Labels
enhancement New feature or request

Comments

@avsaase
Copy link

avsaase commented Dec 18, 2022

Is your feature request related to a problem? Please describe.
I want to display a spinner while my application is making a blocking IO call. When the call takes longer than expected (say 2 seconds) I would like to update the spinner text. In single-threaded code this is not possible because there is no way of keeping track of the elapsed time and calling the update_text() method on the spinner.

Describe the solution you'd like
The spinner itself is able to keep track of the elapsed time. When creating the spinner you pass it a starting text, a duration and an updated text that will be displayed once the duration has passed. Alternatively it could be a sequence of updated texts that it will loop through or even another data structure with multiple texts and for how long they will be displayed.

Describe alternatives you've considered
Spawning a separate thread for the blocking IO call so I can keep track of the time and update the spinner manually. The proposed solution would be more convenient though.

@ad4mx ad4mx added the enhancement New feature or request label Dec 21, 2022
@ad4mx ad4mx self-assigned this Dec 21, 2022
@ad4mx
Copy link
Owner

ad4mx commented Dec 21, 2022

Hi, couldn't all this be done on your end? Maybe the blocking IO call doesn't allow you to do that, but my idea is this:

fn update_after_time(txt: String, duration: u64, end_txt: String) {
    let sp = Spinner::new(Spinners::Dots, txt, None);
    std::thread::sleep(std::time::Duration::from_secs(duration));
    sp.update_text(end_txt);
}

Basically just a function that updates the text after a certain amount of time has passed.

@avsaase
Copy link
Author

avsaase commented Dec 21, 2022

How would you use that with a blocking function though? I suppose you could run update_after_time() from a separate thread and the blocking function from the main thread but then you still need to handle calling .succes() on the spinner so it'll get more complex.

My current solution is like this:

use spinoff::{Spinner, Spinners};
use std::{thread, time::Duration, time::Instant};

fn expensive_blocking_function() -> u32 {
    thread::sleep(Duration::from_secs(5));
    42
}

fn main() {
    let mut spinner = Spinner::new(Spinners::Dots, "Loading...", None);
    let now = Instant::now();
    let handle = thread::spawn(|| expensive_blocking_function());

    while !handle.is_finished() {
        if now.elapsed().as_millis() > 3000 {
            spinner.update_text("Still loading...");
            break;
        }
        thread::sleep(Duration::from_millis(10));
    }

    let result = handle.join().unwrap();
    spinner.success("Done");

    println!("{}", result);
}

It works but it's not elegant with the repeated checking if the thread of the blocking function has finished.

I think that what I'm trying to do is quite common so it would make sense to facilitate it from the library.

@ad4mx
Copy link
Owner

ad4mx commented Dec 28, 2022

I'm afraid I can't really help you. The addition to the library that you are suggesting makes sense. However it won't actually solve your problem with the blocked IO. The code block I wrote in my comment is essentially what would be added to the library.

@avsaase
Copy link
Author

avsaase commented Dec 28, 2022

The changes in #13 perfectly solve my issue. Thanks!

Here's my updated example code:

use spinoff::{Spinner, Spinners};
use std::{thread, time::Duration};

fn expensive_blocking_function() -> u32 {
    thread::sleep(Duration::from_secs(5));
    42
}

fn main() {
    let mut spinner = Spinner::new(Spinners::Dots, "Loading...", None);
    spinner.update_after_time("Still loading", Duration::from_secs(2));

    let result = expensive_blocking_function();
    spinner.success("Done");

    println!("{}", result);
}

@ad4mx
Copy link
Owner

ad4mx commented Dec 29, 2022

Ah, I thought it wouldn't solve your issue, but it does! It'll be included in the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
2 participants