在 Ubuntu/gnome-terminal 中,如果我运行:
$ stty -icrnl
Run Code Online (Sandbox Code Playgroud)
然后启动 GHC 交互环境(一个 Haskell 控制台):
$ ghci
Run Code Online (Sandbox Code Playgroud)
然后按Return不提交行;然而,Enter确实如此。
但是,与:
$ stty icrnl
Run Code Online (Sandbox Code Playgroud)
双方Return并Enter提交该行。
我不太理解这种行为;Return在这两种情况下肯定会提交换行符吗?
Gil*_*il' 11
理解发生了什么的第一步是意识到实际上有两个“换行”字符。有回车(CR,Ctrl+ M)和换行(LF,Ctrl+ J)。在电传打字机上,CR 将打印头移动到行首,而 LF 将纸张向下移动一行。对于用户输入,只有一个相关的概念,即“用户已经输入完一行”,但不幸的是出现了一些分歧:Unix系统,以及非常流行的C语言,使用换行来表示换行;但是当用户按下Return或Enter键时,终端会发送回车。
该icrnl
设置告诉内核中的终端驱动程序在输入时将 CR 字符转换为 LF。这样,应用程序只需要关心一个换行符;在文件中结束行的同一个换行符也会结束终端上用户输入的行,因此应用程序不需要为此设置特殊情况。
默认情况下,ghci,或者更确切地说它使用的haskeline库,有一个键绑定Ctrl+ J,即 LF,以停止累积输入并开始处理它。它对Ctrl+M即 CR没有约束力。因此,如果终端未将 CR 转换为 LF,则 ghci 不知道如何处理该字符。
Haskeline 指示终端报告带有转义序列的键盘键。它查询终端的terminfo 设置以了解这些转义序列是什么(kent
terminfo 数据库中的条目)。(terminfo 数据库也知道如何启用键盘转义:它发送smkx
转义序列,并rmkx
在退出时发送以恢复默认的键盘字符模式。)当您Enter在 ghci 中按下键盘上的键时,会发送转义sequence \eOM
,haskeline 将其识别为停止累积输入并开始处理它的绑定。
提到Return和Enter听起来好像你分别描述了键盘主要部分和数字小键盘上的键,通常位于主要部分的右侧:
但是,只有第一个对应于(未修改的)发送的密钥controlM。数字小键盘上的键可能会发送回车或其他任何内容,但实际上可能会发送转义序列,例如escapeOM,对于类似 VT100 的终端。
您可以通过回显它们来查看不同的键值,例如,使用cat -v
.