Problem Behavior changes due to line wrapping caused by terminal width

When the terminal width is sufficient to accommodate the length of the third line of the program output, it works as expected, but when the width is insufficient, problems occur.
Specifically, when using Termux on Android with the smartphone held vertically, the width is insufficient for the text, and it is treated as if a different line has been added, resulting in incomplete line deletion using ANSIescape.
When I searched for a solution to this problem, I found a way to know the cursor position, but it seemed very tricky and I couldn’t process it and use it well.
This is how the keyword x1b[6n appears.
Therefore, since the terminal width can be obtained relatively easily, I am thinking of calculating the number of times that width is exceeded (taking into account east asian width characters), and then using ANSIescape to move the cursor and delete the corresponding number of times.
I would like to know if there are any other clever solutions, such as changing the behavior depending on the terminal width so that it is not treated as a line break, and I am asking this question.

import time

# ANSI escape
MOVU = "\033[1A"
CRTN = "\033[2K"


# test text
sampletx = "text line 1 start\ntext line second here\nlong line long long line test one long line test two long line hello world here is long line third line\nhello\n"


def fspinner(rndrstr):
    """my spinner"""

    # List rndrstr by line break
    efline = rndrstr.splitlines()

    # line in operation
    cur = 0

    lgl = len(efline[cur])

    hdpos = 0

    # vislist = " " * lgl  # it was same id all
    vislist = [" " for _ in range(lgl)]
    print(f"{len(vislist)=}")

    for list in efline:

        lgl = len(efline[cur])
        vislist = [" " for _ in range(lgl)]

        for list in efline[cur]:

            # Character judgment and put in the list.
            if efline[cur][hdpos] == " ":
                vislist[hdpos] = "░"  # white space transform to symbol for testing
            else:
                vislist[hdpos] = efline[cur][hdpos]

            # print(f"{vislist=}")

            hdpos += 1

            # Display
            print(f'{"".join(vislist)}')
            time.sleep(0.015)
            # and erase
            print(MOVU+CRTN, end="")

        print(f"{''.join(vislist)}")
        cur += 1
        hdpos = 0

fspinner(sampletx)

To reproduce the abnormality on a computer, please extend the third line, which says “long long line” , as it too short.
So I think that would recreate the unintended output of the pyramid…

Can you take a screenshot of the problem on your phone and post that image here? That may help someone visualize the problem. Some people are just more visual.

If you hold it vertically, it will look like this. Line breaks are inserted at the width of the screen,(P.S. I was wrong, it seems that the vislist exceeds the screen width including whitespace every time)
so I think this is because the behavior of the ANSIescape cursor moving up one line and the carriage return (deleting a line) is different from other screens and becomes strange.

When I copied it, it looked different from the screen. I will prepare the image. Please wait. It is very long vertically.

~ $ python3 tmptmp.py
len(vislist)=17
text░line░1░start
text░line░second░here
l                                                          lo                                                         lon                                                        long                                                       long░                                                      long░l                                                     long░li                                                    long░lin                                                   long░line                                                  long░line░                                                 long░line░l                                                long░line░lo                                               long░line░lon                                              long░line░long                                             long░line░long░                                            long░line░long░l                                           long░line░long░lo                                          long░line░long░lon                                         long░line░long░long                                        long░line░long░long░                                       long░line░long░long░l                                      long░line░long░long░li                                     long░line░long░long░lin                                    long░line░long░long░line                                   long░line░long░long░line░                                  long░line░long░long░line░t                                 long░line░long░long░line░te                                long░line░long░long░line░tes                               long░line░long░long░line░test                              long░line░long░long░line░test░                             long░line░long░long░line░test░o                            long░line░long░long░line░test░on                           long░line░long░long░line░test░one                          long░line░long░long░line░test░one░                         long░line░long░long░line░test░one░l                        long░line░long░long░line░test░one░lo                       long░line░long░long░line░test░one░lon                      long░line░long░long░line░test░one░long                     long░line░long░long░line░test░one░long░                    long░line░long░long░line░test░one░long░l                   long░line░long░long░line░test░one░long░li                  long░line░long░long░line░test░one░long░lin                 long░line░long░long░line░test░one░long░line                long░line░long░long░line░test░one░long░line░               long░line░long░long░line░test░one░long░line░t              long░line░long░long░line░test░one░long░line░te             long░line░long░long░line░test░one░long░line░tes            long░line░long░long░line░test░one░long░line░test           long░line░long░long░line░test░one░long░line░test░          long░line░long░long░line░test░one░long░line░test░t         long░line░long░long░line░test░one░long░line░test░tw        long░line░long░long░line░test░one░long░line░test░two       long░line░long░long░line░test░one░long░line░test░two░      long░line░long░long░line░test░one░long░line░test░two░l     long░line░long░long░line░test░one░long░line░test░two░lo    long░line░long░long░line░test░one░long░line░test░two░lon   long░line░long░long░line░test░one░long░line░test░two░long  long░line░long░long░line░test░one░long░line░test░two░long░ long░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░llong░line░long░long░line░test░one░long░line░test░two░long░line░hello░world░here░is░long░line░third░line
hello
~ $

Sorry for the poor quality of the image, but when I selected and copied it, it looked like the code above.

The workaround I took was
Add the following to the first for loop to calculate the terminal width and the number of overflows to display.

        tsize = os.get_terminal_size()
        wad = len(vislist) // tsize[0]

In reality my code, it is get_east_asian_width_count(vislist) // tsize[0]

Increase the number of times to delete lines depending on the number of times.

              for i in range(wad+1):
                  print(MOVU+CRTN, end="")

I’m starting to think that this is fine now.
I wondered why line breaks were added just by holding the smartphone vertically, but they are actually there
and I think ANSI escape just trying to work correctly. Yes, I am now convinced :smiley: