Tcl - 从标准输入中读取字符而无需在 Tcl 中按回车

Tcl - Reading characters from stdin without having to press enter in Tcl

我想在不刷新 stdin 的情况下按字符读取 stdin。调整了几个小时后,我找不到如何做到这一点。即使在 fconfigure stdin -blocking 0 -buffering none 中,Tcl 似乎总是等待通道被刷新。真的吗?否则我该如何处理?

更多解释:
想象一个 Tcl 程序在后台使用一些线程 运行 代码生成自己的提示。我希望此提示对单个击键做出反应,例如:当您按 'p'(不按 enter)时,提示会读取该字符并暂停线程,当您按 'q' prompt 杀死线程并停止程序。最干净和最接近的解决方案在以下代码片段中进行了简短演示。

proc readPrompt { } { 
    set in [ read stdin 1 ] 
    if { $in eq "q" } { 
        puts "Quitting..."
        set ::x 1
    } { 
        puts "Given unknown command $in"
    }
}

fconfigure stdin -blocking 0 -buffering none 
fileevent stdin readable { readPrompt }

vwait x

运行 的结果是:

a
Given unknown command a
Given unknown command 

按下'a'后,没有任何反应。我的猜测是 stdin 没有刷新或什么的。按 enterCTRL-d 会触发文件事件,然后提示会读取字符 'a' 和 'enter'。

理想情况下,我希望不需要 enter-press。我怎样才能做到这一点?

编辑:我在 Python 中找到了有关相关用途的问题和解决方案: 这大约是我正在寻找的行为,但在 Tcl 中。

如果你有 8.7(目前处于 alpha 阶段)那么 this is “trivial”:

fconfigure stdin -inputmode raw

这会向您传送 所有 个字符,而不回显它们。 (还有模式 normalpassword,这两种模式都在传送前对数据进行预处理,并且只有一种模式会回显。)您必须自己注意向用户提供视觉反馈,并注意所有 包括通常仅用于行编辑目的的所有字符。

否则,在 Unixes(Linux、macOS)上你会:

exec stty raw -echo <@stdin >@stdout

将模式切换到相同的配置,并且:

exec stty -raw echo <@stdin >@stdout

切换回来。 (并非所有 Unix 都需要输入和输出重定向,但有些确实需要。)


Windows 控制台在 8.7 中有类似的东西,但在以前的版本中没有;使用 TWAPI console support 可能有解决方法,但这是一个非常低的级别 API(我不知道细节)。