每当我在 shell 中使用类似寻呼机less
或类似编辑器(我的 shell 是 GNU bash)时,我都会看到一种无法完全解释的行为,该行为与我使用或等其他工具观察到的行为不同。我想问一下这种行为是如何产生的。nano
cat
ls
不容易解释的行为是,通常所有到 stdout/stderr 的输出最终都会记录在终端仿真器后缓冲区中,因此我可以向后滚动,而(对我来说通常不是这样)在使用less
or的情况下nano
,输出由终端仿真器显示,但退出程序后,内容“神奇地消失”。
我想举这两个例子:
seq 1 200
(在后台缓冲区中生成 200 行)seq 1 200 | less
(让我翻页 200 行,但最终“清理”并且后台缓冲区中没有记录任何内容)
我怀疑某种转义码正在发挥作用,我希望有人能指出我对这种观察到的行为差异的解释。
由于一些评论和答案是措辞的,就好像我希望改变行为一样,这“很高兴知道”,但实际上期望的答案应该是机制的描述,而不是改变它的方法。
答案1
这里有两种世界观:
- 就使用 termcap/terminfo 的程序而言,您的终端可能有两种模式:光标寻址方式和滚动模式。后者是普通模式,当程序需要按行和列地址在屏幕上移动光标时,程序会切换到光标寻址模式,将屏幕视为二维实体。
termcap 和 terminfo 负责将程序所看到的世界观转换为终端所看到的世界观。
- 对于终端(模拟的或真实的)而言,有两个屏幕缓冲区,任何时候都只显示其中之一。有一个主屏幕缓冲区和一个备用屏幕缓冲区。程序发出的控制序列在两者之间切换终端。
- 对于某些终端(通常是模拟终端),备用屏幕缓冲区是根据 termcap/terminfo 的使用而定制的。它们的设计是基于以下知识:切换到光标寻址方式正在切换到备用屏幕缓冲区以及切换到的一部分滚动模式正在切换到主屏幕缓冲区。这就是 termcap/terminfo 翻译事物的方式。因此,当显示备用屏幕缓冲区时,这些终端不会显示滚动用户界面小部件,并且根本没有该屏幕缓冲区的回滚机制。
- 对于其他终端(通常是真实终端),备用屏幕缓冲区与主屏幕缓冲区非常相似。两者在支持的内容方面基本相同。请注意,一些模拟终端属于此类。例如,Unicode rxvt 具有主屏幕缓冲区和备用屏幕缓冲区的回滚功能。
呈现的节目全屏文本用户界面(例如vim
、nano
、less
、mc
等)使用 termcap/terminfo 在启动时切换到光标寻址模式,并在挂起、退出或退出时返回到滚动模式。 ncurses 库可以做到这一点,但更直接构建在 termcap/terminfo 之上的非 ncurses 使用程序也可以做到这一点。
less
由或呈现的 TUI 内的滚动vim
与回滚无关。这是在这些程序内部实现的,这些程序只是在滚动时适当地重新绘制全屏文本用户界面。
请注意,这些程序不要在备用屏幕缓冲区中“不保留任何内容”。终端不再显示他们留下的内容。
- 这在某些平台上的 Unicode rxvt 中尤其值得注意,其中用于切换到光标寻址模式的 termcap/terminfo 序列不会隐式清除备用屏幕缓冲区。因此,连续使用多个此类全屏 TUI 程序最终可能会显示上一个程序留下的备用屏幕缓冲区的旧内容,至少会持续一段时间,直到新程序写入其输出(最明显的是
less
在管道的末端)。 - 使用 xterm,可以从终端仿真器的 GUI 菜单切换到显示备用屏幕缓冲区,并查看仍然存在的内容。
实际的控制顺序是相关标准所说的设置私人模式控制序列。相关的专用模式编号为 47、1047、1048 和 1049。请注意,除了切换到备用屏幕缓冲区或从备用屏幕缓冲区切换之外,每个模式隐含的额外操作之间存在差异。
进一步阅读
答案2
您可以通过几种方式添加 no-clear 。您可以less
通过使用参数调用它来解决清除屏幕的问题-X
。
请注意$
下面命令行中的符号。这是指定普通用户的终端提示符。
$ seq 1 200 | less -X
如果这是您想要的行为,您可以将此less
默认值别名为:
$ alias less='less -X'
其他程序也有类似的解决方法。
或者,您可以添加自己的终端定义,而不是尝试单独配置每个应用程序。在这种情况下我会称之为xterm-noclear对于这个例子。
运行以下步骤来创建新的 xterm 定义:
$ infocmp -I xterm > xterm-noclear.src
$ gedit xterm-noclear.src
现在将编辑器中的第二行从 更改xterm
为xterm-noclear
。
通过搜索删除清除屏幕的指令杯和smcup,并删除这两条指令:
smcup=\E[?1049h,
和
rmcup=\E[?1049l,
保存文件,然后添加终端定义:
$ tic ~/xterm-noclear.src
您可以使用以下命令将其设为系统范围内可用的终端定义:
$ sudo tic ~/xterm-noclear.src
现在您可以将其用于TERM
:
$ export TERM=xterm-noclear
答案3
一个名为curses的库,它知道您正在使用什么终端类型,并发送正确的转义序列。终端被要求切换到不同的垂直缓冲区和允许更多控制的模式。