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

Is there a way to display several progress bars? #62

Closed
yoelp2k opened this issue Jun 27, 2022 · 8 comments
Closed

Is there a way to display several progress bars? #62

yoelp2k opened this issue Jun 27, 2022 · 8 comments

Comments

@yoelp2k
Copy link

yoelp2k commented Jun 27, 2022

Hi!

I really enjoy your code, you are super talented and I learned many cool Kotlin tricks reading your code :)

My issue is:
I want to present several progress bars. Simple use case will be downloading two (or more) files simultaneously - trying to display a progress-bar per file

I tried several approaches utilizing progressAnimation, one terminal with multiple progress bars, and several terminals with progressAnimation each. Digging a little into the code I realized that this is not the way that I should use your code
Sadly my attempts failed miserably :(

My workaround is not using the progress bars at all and using styled text instead - but I feel like there is possibly a better solution

Can you please hint to me about what should I do?

Thanks a bunch!!

(p.s. I don't mind having both progress bars at the same line but I would prefer them one per line)

@ajalt
Copy link
Owner

ajalt commented Jul 3, 2022

Sure, just use one terminal and make two progress animations:

val terminal = Terminal()
val progress = terminal.progressAnimation { progressBar() }
val progress2 = terminal.progressAnimation { progressBar() }

progress.start()
progress2.start()

Or, if you did want two bars on the same line, put them both in the same animation:

val terminal = Terminal()
val progress = terminal.progressAnimation { 
    progressBar()
    progressBar()
}
progress.start()

@ajalt ajalt closed this as completed Jul 3, 2022
@yoelp2k
Copy link
Author

yoelp2k commented Jul 4, 2022

Thank you for your reply.
Following your advice, I tried running your 1st suggestion:

`
fun main() {
val terminal = Terminal()
terminal.info.updateTerminalSize()

val progress0 = terminal.progressAnimation {
    spinner(Spinner.Dots(brightBlue))
    text("my-file0.bin")
    percentage()
    progressBar()
    completed()
    speed("B/s")
    timeRemaining()
}

val progress1 = terminal.progressAnimation {
    spinner(Spinner.Dots(brightBlue))
    text("my-file1.bin")
    percentage()
    progressBar()
    completed()
    speed("B/s")
    timeRemaining()
}

progress0.start()
progress1.start()

// Sleep for a few seconds to show the indeterminate state
Thread.sleep(1000)

// Update the progress as the download progresses
progress0.updateTotal(3_000_000_000)
progress1.updateTotal(3_000_000_000)

repeat(200) {
    progress0.advance(15_000_000)
    progress1.advance(15_000_000)
    Thread.sleep(100)
}

progress0.stop()
progress1.stop()

}
`

The result was not what I expected. Instead of two lines being updated, I got many new lines

⠋ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠋ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠋ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠋ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠋ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠋ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠙ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠙ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠙ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠙ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠙ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ⠙ my-file0.bin 0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/---.- ---.-B/s eta -:--:-- ... ...

What did I do wrong?
Or perhaps should I open a bug?

Thanks, Yoel

p.s. [edit]
also tried the 2nd approach. It resulted with two progress bars advancing at the same pace with no clear way to update one and not the other

@ajalt
Copy link
Owner

ajalt commented Jul 4, 2022

That works correctly for me. What OS/Terminal/JVM are you using? How are you running the program? Does it work if you only use one progress bar, or do you still see many lines?

@yoelp2k
Copy link
Author

yoelp2k commented Jul 4, 2022

With one progress bar everything works perfectly

With two I get the reported error
Here is sample project to demonstrate the problem: https://github.com/yoelp2k/example-mordant-two-progress-bars
Running on windows 10, java17, IntelliJ IDEA 2022.1.3 (Ultimate Edition)

@ajalt
Copy link
Owner

ajalt commented Jul 5, 2022

So the issue is that the IntelliJ terminal doesn't support cursor movement commands, so it's not possible to animate anything that spans more than one line. We special case that terminal for single line animations by using a carriage return.

Try running in a real terminal and it should work.

@yoelp2k
Copy link
Author

yoelp2k commented Jul 11, 2022

OK, tried it on several windows terminals (git-bash, power-shell, cmd)
Fail! all tested windows terminals had no output at all (for the two lines example)
Surprisingly - the intellij terminal did work displaying two lines as expected - but fancy characters replaced with '?'
Running intellij's "run configuration" prints many lines (because of what you said about the one line problem)

Note: I noticed that Gradle somehow manage to display multiple lines correctly. On every terminal I tested, linux, windows - whatever. So there must be some kind of a solution to this nasty annoying bug. Not sure how worth-while it is though

@ajalt
Copy link
Owner

ajalt commented Jul 11, 2022

So again it depends on how you are running the program. I'm guessing you're running through gradle, which redirects stdin and stdout. Since there's no way for mordant to tell whether you're running interactively in gradle vs being redirected to a file, it takes the safe approach and disables animations.

You can force the animations to play by forcing interactive output: Terminal(ansiLevel=AnsiLevel.TRUECOLOR, interactive=true).

For the ? characters, make sure your terminals are set to use UTF-8 code pages, and your JVM file encoding is set to UTF-8 as well (here's how I set the file encoding in the samples).

@yoelp2k
Copy link
Author

yoelp2k commented Jul 12, 2022

Thanks!
I will try the encoding sample
I'll also try the interactive mode
:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants