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

Prevent Animation from clearing the screen #110

Closed
vegidio opened this issue Aug 4, 2023 · 5 comments · Fixed by #111
Closed

Prevent Animation from clearing the screen #110

vegidio opened this issue Aug 4, 2023 · 5 comments · Fixed by #111

Comments

@vegidio
Copy link

vegidio commented Aug 4, 2023

Hey,

I'm using Terminal.textAnimation in my application, but it when the animation starts it clears all text that I printed before. Is there a way to prevent this from happening?

Thanks!

@ajalt
Copy link
Owner

ajalt commented Aug 9, 2023

Animations don't clear the screen when they start. Can you share a minimized version of the code you're trying?

What terminal, os, and target are you using?

@vegidio
Copy link
Author

vegidio commented Aug 9, 2023

Yes, I can give you the entire source code actually since it's in my open source project 😄

  1. The entry point of the project is here Main.kt
  2. On line 24 I call the method getSubmissions.
  3. In the getSubmissions function I print some things on lines 20, 33 and 38.

This is just to give you some context; the code above is the one that will disappear when the animations start:

  1. Now back in the Main.kt file, I call the function downloadMedia on line 30.
  2. The function downloadMedia prints two things on the screen: a progressAnimation and a textAnimation. You can see the code where I update the text animation on line 45 and where I stop it on line 81.

But the problem begins already on step 4 above. As soon as the animation is updated, all the content that I printed on steps 1-3 disappear from the screen. But if I comment out the animation (steps 4-5 above), then the texts that I printed on steps 1-3 are not cleared.

I confirmed that if I comment out the textAnimation code, but I leave the progressAnimation, the progressAnimation does NOT clear the screen. What is clearing the screen seems to be only textAnimation.

I even created a video on asciinema to show what's happening:

asciicast

  • In the video above you will notice in the 00:00:06 mark that I print the message 📝 Collecting 100 posts from user atomicbrunette18
  • But in the 00:00:09 mark, when the progressAnimation and the textAnimation are executed, the text 📝 Collecting 100 posts from user atomicbrunette18 that I printed before is gone.

In the example above my code is running inside a Docker container, but this problem also occurs if I run my program outside Docker, from my Mac terminal (I'm using iTerm2).

I hope this helps you identify the problem. Thanks for helping.

@vegidio
Copy link
Author

vegidio commented Aug 9, 2023

Sorry! After I shared my entire project I realized that it's much simpler to do what you originally asked, which is to share a minimal reproducible code. Here is an example that I just created:

package io.vinicius.rmd

import com.github.ajalt.mordant.animation.Animation
import com.github.ajalt.mordant.animation.progressAnimation
import com.github.ajalt.mordant.animation.textAnimation
import com.github.ajalt.mordant.rendering.TextStyles
import com.github.ajalt.mordant.terminal.Terminal
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlin.random.Random
import kotlin.time.Duration.Companion.seconds

val t = Terminal()

fun main() {
    t.print("\n📝 Test ${TextStyles.bold("Test")} Test")
    
    runBlocking { delay(5.seconds) }

    val words = List(100) {
        (1..100).map { Random.nextInt(97, 123).toChar() }.joinToString("")
    }

    val anim = printMostRecent()

    val progress = t.progressAnimation {
        text("Downloading")
        percentage()
        progressBar(width = 50)
        completed()
        speed(" posts/sec")
        timeRemaining()
    }

    progress.updateTotal(words.size.toLong())
    val current = mutableListOf<String>()

    words.forEachIndexed { index, s ->
        current.add(s)
        progress.update(index + 1)
        anim.update(current.takeLast(5))
    }

    progress.stop()
    anim.stop()
}

fun printMostRecent(): Animation<List<String>> {
    return t.textAnimation { list ->
        list.joinToString("\n", "\n") { it }
    }
}

With this code you will see that Test Test Test string that I print in the very beginning is cleared when the animation starts.

@vegidio
Copy link
Author

vegidio commented Aug 9, 2023

Ok, now I'm feeling stupid, but despite what I've said before, it seems that progressAnimation is also clearing any text printed before. I could swear it was not doing this before 🤔

In any case, it seems that both progressAnimation and textAnimation are clearing the screen.

Also, sorry for spamming your mailbox with multiple updates on this issue.

@ajalt
Copy link
Owner

ajalt commented Aug 10, 2023

Here's a fully minimized repro:

t.println("xxxxxxx")
val b = t.textAnimation<String> { it }
b.update("foo")
b.update("foo\nbar")

The issue was that you were changing the size of the animation while it was running and mordant was trying to move the cursor to clear a space the size of the new frame, not the previous frame.

BTW, animations assume the cursor is on the start of a line before they draw for the first time, so you should use t.println instead of t.print to avoid the first frame of the animation drawing incorrectly.

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

Successfully merging a pull request may close this issue.

2 participants