ajalt/mordant

Prevent Animation from clearing the screen

vegidio opened this issue ยท 5 comments

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 commented

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?

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.

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.

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 commented

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.