1

So I'm trying to have a simple terminal application with the following behavior:

  1. On launch, the screen is cleared, and some content is written at the top of the empty screen

  2. Every time "enter" is pressed, the screen is cleared, and new content is presented in its place

I'm trying to achieve this with ANSI escape codes, by clearing the screen and moving the cursor. Currently my approach is like this (in pseudocode)

func clearAndPrintContent() {
    printf("\x[2J")    // clear the entire screen
    printf("\x[1;1f")  // move the cursor to the top left corner of the screen
    printContent() // print some lines of content to the screen
}

main {
    while true {
        clearAndPrintContent() // do the clear and print
        readLine() // wait for enter key
    }
}

What I would expect to happen is that the content here would always be written in-place: i.e. when new content is written, it would over-write the existing content. What I actually get is that all my content is written in serial. In other words, when I scroll through the scrollback, I see each "page" which my program printed, including the blank space and the content which was printed.

So for instance, if I printed the content twice, then I would like for my scrollback to look like this:

- previous scrollback -
$ run my-app

   [result of second printContent from my-app (first has been over-written)]



-end of terminal output -

But what I actually get is this:

- previous scrollback -
$ run my-app

   [result of first printContent from my-app]





   [result of second printContent from my-app]



-end of terminal output -

How can I achieve this result?

sak
  • 193

1 Answers1

1

The behavior on \e[2J differs across terminals. Some, e.g. Xterm clear the screen as you expect. Some others, e.g. VTE (GNOME Terminal and other frontends) scroll out the contents to the scrollback buffer as you experience it.

You could move the cursor home in the first step and then clear with \e[J ("erase below", that is, to the right in the cursor's row, and everything in the rows below). This behaves the same way everywhere.

Another approach is to switch to the alternate screen buffer which doesn't have a scrollback, thus \e[2J does the same thing in every terminal. When quitting the app you need to switch back to the normal screen, you'll be taken to where you were when your app started.

egmont
  • 5,866
  • 1
    Using the alternate screen does mean that the output of the command isn't visible in the scrollback after the program finishes. That can be annoying in some cases, though I'm not sure if they wanted that here. – ilkkachu Nov 07 '19 at 20:27
  • I think the alternate buffer is exactly what I'm looking for, thanks! – sak Nov 07 '19 at 20:47