交互式命令行实用程序如何实际工作

时间:2011-10-17 15:40:04

标签: command-line terminal

我掌握了stdin,stdout,stderr的基本概念以及程序如何使用命令行/终端。

但是,我一直想知道Linux和less中的git log等实用程序是如何工作的,因为它们是交互式的。

我目前的想法是程序不会退出,写入stdout,侦听键事件并向stdout写入更多内容,直到用户退出按q或发送关闭信号。

我的直觉是对的还是还有更多?他们是否检测每行的行数和字符数以确定输出量?他们在输出之前总是清除屏幕吗?

1 个答案:

答案 0 :(得分:0)

非常有趣的问题,即使它有点开放。

如@tripleee所述,ncurses是交互式CLI应用程序的基础库。


有点历史......

终端==“打印机”......

要了解POSIX“终端”,你必须考虑他们的历史...更具体地说,你需要考虑70年代的“终端”是什么意思,你有一个键盘+打印机连接到串行电缆。在您键入时,一个字节流流向主机,它将它们回送到打印机,使打印机在您键入命令时回显该命令。然后,通常在按ENTER后,主机将关闭并执行一些工作,然后将输出发送回打印。由于它基本上是一个美化的点阵打印机,我们在这里只是附加说法。没有“画屏”或任何类似的东西。

试试这个:

echo -e "Hi  there\rBye"

你会看到它打印“再见”。 “\ r”是没有换行的回车。 carriage是打印机部件,它在旧的点阵打印机中来回移动并实际进行打印。因此,如果您将托架返回到页面的左侧并且无法前进纸张(即“换行”),那么您将开始在当前文本行上打印。 “terminal”==“printer”。

监视器和软件终端......仍然是面向行的

所以闪现一点,一个名为“监视器”的革命性技术出现在你有一个可以重写的虚拟化终端显示器的地方。因此,与所有优秀的技术一样,我们通过添加越来越多的特殊转义码来逐步创新。例如,查看ANSI color codes。如果你在一个无法识别这些转义码的终端上,你会在那些未解释的代码的输出中看到一堆乱码:

    "methodName": ESC[32m"newInstance"ESC[39m,
    "fileName": ESC[32m"NativeConstructorAccessorImpl.java"ESC[39m,
    "className": ESC[32m"sun.reflect.NativeConstructorAccessorImpl"ESC[39m,
    "nativeMethod": ESC[33mfalseESC[39m,

当您的终端看到'\ 033'(ESC),'[',...,'m'时,它会将其解释为更改颜色的命令。试试这个:

 echo  -e "\033[32mgreen\033[39m"

所以,无论如何,这是Unix终端系统的历史/遗产,然后由Linux和BSD(例如,macs)继承,并且半标准化为POSIX。查看termio.h,它定义了与终端交互的内核接口。几乎可以肯定,Linux / BSD有许多未完全标准化为POSIX的高级功能。在谈论“标准”时,还有一些事实上的终端设备协议标准,如古老的VT100。像SSH或PuTTY这样的软件“终端模拟器”知道如何说VT100,通常还有一堆更高级的方言。

Shoe-horning“互动”到“面向行”的界面......

所以...互动...这与世界的行式打印机视图不太匹配。它分层顶部。输入很简单;而不是自动回显键入的每个击键并等待ENTER(ala "readline"),我们让程序在从TTY进入时消耗击键。输出更复杂。即使基本抽象是输出的 stream ,但有足够的转义代码,您可以通过定位"caret"并在旧文本之上写入新文本来重新绘制屏幕(就像我的“ \ r“例子)。这些都不是很有趣,尤其是当您想要支持具有不同转义码的多个环境时。 ....因此,图书馆,其中ncurses是最知名的之一。要了解有效将动态屏幕渲染为面向行的TTY所做的时髦魔术,请查看“黑客入侵NCURSES”中的Output and Screen Updating