Make cli spinner like emerge (gentoo linux) with candy

Hi everyone, I have a question. I try actually to make a spinner similar to the candy feature of emerge for who know Gentoo Linux. I almost done it, but I don’t get how to delete previous/next character without moving the cursor.

These are the functions use to do this animation actually in my project:

def resetCalculationAnimation
            @calculationStartingTime = Time.monotonic
            @frameIndex = 0
            @reverseAnimation = false
        end

        def playCalculationAnimation(@text = ISM::Default::CommandLine::CalculationWaitingText)
            currentTime = Time.monotonic

            if (currentTime - @calculationStartingTime).milliseconds > 40
                if @frameIndex == @text.size && !@reverseAnimation
                    @reverseAnimation = true
                end

                if @frameIndex < 1
                    @reverseAnimation = false
                end

                if @reverseAnimation
                    print "\033[1D"
                    print " "
                    print "\033[1D"
                    @frameIndex -= 1
                end

                if !@reverseAnimation
                    print "#{@text[@frameIndex].colorize(:green)}"
                    @frameIndex += 1
                end

                @calculationStartingTime = Time.monotonic
            end
        end

        def cleanCalculationAnimation
            loop do
                if @frameIndex > 0
                    print "\033[1D"
                    print " "
                    print "\033[1D"
                    @frameIndex -= 1
                else
                    break
                end
            end
        end

You can use GitHub - crystal-term/spinner: A terminal spinner for tasks that have a non-deterministic time frame (or some other spinner shards out there) or at least look at the code.

Hi @Fulgurance

I’m not familiar with Gentoo Linux or the candy feature of emerge, so I might not be the best person to answer. However,

how to delete previous/next character without moving the cursor.

I don’t think it is actually possible to delete a character without moving the cursor. In practice, you would need to move the cursor, and then quickly return it to make it appear as if the cursor hasn’t moved.

See ANSI escape code

@Fulgurance I played around with a few different examples here: GitHub - mgomes/progress_bar: CLI progress bar library for Crystal. Might give you some ideas.

I did a gif of the animation I try to do to make you understand :

ezgif-6-d5711fd3ba

So how can I do that ?

1 Like

I find how to do ah ah

def playCalculationAnimation(@text = ISM::Default::CommandLine::CalculationWaitingText)
            currentTime = Time.monotonic

            if (currentTime - @calculationStartingTime).milliseconds > 40

                if @frameIndex == @text.size && !@reverseAnimation
                    @reverseAnimation = true
                end

                if @frameIndex < 1
                    @reverseAnimation = false
                end

                if @reverseAnimation

                    print "\b "
                    print "\033[1D"
                    print "\b#{@text[@frameIndex-1].colorize(:green)}"

                    @frameIndex -= 1

                end

                if !@reverseAnimation

                    print "\b "
                    print "#{@text[@frameIndex].colorize(:green)}"
                    @frameIndex += 1

                end

                @calculationStartingTime = Time.monotonic
            end
        end