使用 ANSI 转义序列“就地”编辑终端内容的正确方法是什么?

使用 ANSI 转义序列“就地”编辑终端内容的正确方法是什么?

因此,我尝试创建一个具有以下行为的简单终端应用程序:

  1. 启动时,屏幕被清除,一些内容被写入空屏幕的顶部

  2. 每按一次“回车”,屏幕就会被清空,新的内容就会出现在它的位置上

我试图通过清除屏幕并移动光标,使用 ANSI 转义码来实现此目的。目前我的方法是这样的(伪代码)

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
    }
}

我期望发生的是,这里的内容将始终就地写入:即,当写入新内容时,它将覆盖现有内容。我实际上得到的是我的所有内容都是连续写的。换句话说,当我滚动回滚时,我看到程序打印的每个“页面”,包括空白区域和打印的内容。

例如,如果我将内容打印两次,那么我希望回滚看起来像这样:

- previous scrollback -
$ run my-app

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



-end of terminal output -

但我实际得到的是这样的:

- previous scrollback -
$ run my-app

   [result of first printContent from my-app]





   [result of second printContent from my-app]



-end of terminal output -

我怎样才能达到这个结果?

答案1

不同终端的行为\e[2J有所不同。有些(例如 Xterm)会按照您的预期清除屏幕。其他一些,例如 VTE(GNOME 终端和其他前端),会在您体验时将内容滚动到回滚缓冲区。

您可以在第一步中将光标移至原处,然后使用\e[J(“擦除下方”,即光标所在行的右侧以及下面行中的所有内容)清除。这在任何地方都是一样的。

另一种方法是切换到没有回滚功能的备用屏幕缓冲区,因此\e[2J在每个终端中都执行相同的操作。退出应用程序时,您需要切换回正常屏幕,您将被带到应用程序启动时所在的位置。

相关内容