在 Ubuntu/gnome-terminal 中,如果我运行:
$ stty -icrnl
然后启动 GHC 交互环境(Haskell 控制台):
$ ghci
然后按下Return不会提交该行;但是,Enter会。
然而,随着:
$ stty icrnl
两者都Return提交Enter行。
我不太理解这种行为;在这两种情况下肯定Return都会提交换行符吗?
答案1
理解正在发生的事情的第一步是要意识到实际上有两个“换行”字符。有回车(CR, Ctrl+ M) 和换行(LF,Ctrl+ J)。上一个电传打字机, CR 将打印头移动到行首,而 LF 将纸张向下移动一行。对于用户输入来说,只有一个相关的概念,那就是“用户已经输入完一行”,但不幸的是存在一些分歧:Unix系统以及非常流行的C语言,使用换行符来表示换行符;但当用户按Return或Enter键时终端会发送回车符。
该icrnl
设置告诉内核中的终端驱动程序在输入时将 CR 字符转换为 LF。这样,应用程序只需担心一个换行符;结束文件中的行的同一换行符也会结束终端上用户输入的行,因此应用程序不需要为此有特殊情况。
默认情况下,ghci,或者更确切地说哈斯凯莱恩它使用的库有一个Ctrl+的键绑定J,即 LF,以停止累积输入并开始处理它。它没有Ctrl+M即 CR 的绑定。因此,如果终端没有将 CR 转换为 LF,ghci 就不知道如何处理该字符。
Haskeline 指示终端报告带有转义序列的键盘按键。它查询终端的术语信息设置了解这些转义序列是什么(kent
terminfo 数据库中的条目)。 (terminfo 数据库也是它知道如何启用键盘转义的方式:它发送smkx
转义序列,并在退出时发送rmkx
以恢复默认键盘字符模式。)当您Enter在 ghci 中按键盘上的键时,会发送转义序列\eOM
,haskline 将其识别为一个绑定,以停止累积输入并开始处理它。