man、screen 和 vim 等程序如何创建临时覆盖?

jvr*_*sem 1 shell terminal tput

几个* NIX命令,比如screenmanvim和其他人,创建一个临时帆布/屏幕/在shell环境的覆盖。当此类程序执行时,它们会覆盖或隐藏之前在终端中显示的任何内容——几乎就像终端窗口内的“全屏”模式。然而,当它们终止时,它们会显示或恢复之前在终端上的任何内容。

在下面的示例中,我在屏幕上创建了一些填充文本,然后调用man bash. 手册页打开并覆盖终端显示屏上的所有其他字符。当我关闭手册页时,被覆盖的字符再次显示。

运行 <code>man bash</code> 之前的终端屏幕截图

当一个示例全屏程序正在运行时

Bash 手册页的屏幕截图

运行 <code>man bash</code> 后终端的屏幕截图

我希望写入 stdout/stderr 的程序可以完成第一步(用程序特定的内容替换终端的内容),但随后它会产生大量我可以滚动浏览的文本,因此无法执行第二步:恢复终端内容。这意味着程序以某种方式记住屏幕的先前内容并重新输出它们(我怀疑它?),或者它在终端内创建某种子窗口,并且其他东西跟踪终端的先前内容.

我的问题

我怎样才能在我自己的程序和/或脚本中实现这种行为?

也许我应该使用curses/ncurses、tput、termcap/terminfo 或ANSI 转义序列?

更新:

这个修改后的问题与https://unix.stackexchange.com/questions/27941/show-output-on-another-screen-and-return-to-normal-when-done基本相同。(尽管进行了大量搜索,但我在写这个问题时还没有找到它。)不同之处在于我的问题更笼统(任何语言),而该问题特定于 Bash。这两个问题的答案基本相同。如果它与另一个站点上的问题太相似,请出于这个原因在这里关闭它。

ogu*_*ail 5

这些程序如何实现这种行为?

ANSI 转义序列。尝试运行此脚本:

#/bin/bash -
tput smcup
echo 'Hello world!'
sleep 3
tput rmcup
Run Code Online (Sandbox Code Playgroud)

使用infocmp,您可以看到创建这种叠加效果的底层序列,例如:

$ infocmp -1 | grep 'rmcup\|smcup'
        rmcup=\E[?1049l\E[23;0;0t,
        smcup=\E[?1049h\E[22;0;0t,
Run Code Online (Sandbox Code Playgroud)

这种行为是依赖于外壳还是依赖于系统?

无,这取决于终端模拟器是否支持保存/恢复操作。