TCL使用-nohang选项获取命令?
下面是一段代码,它只是通过命令提示符TCL使用-nohang选项获取命令?,tcl,stdin,interactive,gets,Tcl,Stdin,Interactive,Gets,下面是一段代码,它只是通过命令提示符MyShell>实现了一个交互式TCL会话 puts -nonewline stdout "MyShell > " flush stdout catch { eval [gets stdin] } got if { $got ne "" } { puts stderr $got } 此代码在终端提示MyShell>,并等待按下回车按钮;虽然没有命中,但代码什么也不做。这就是获取命令的作用 我需要的是gets命令的替代方法,比如coolget。c
MyShell>
实现了一个交互式TCL会话
puts -nonewline stdout "MyShell > "
flush stdout
catch { eval [gets stdin] } got
if { $got ne "" } {
puts stderr $got
}
此代码在终端提示MyShell>
,并等待按下回车按钮;虽然没有命中,但代码什么也不做。这就是获取
命令的作用
我需要的是gets
命令的替代方法,比如coolget
。coolget
命令不应该等待回车按钮,而是注册一些在点击时调用的插槽,然后继续执行。所需的代码应如下所示:
proc evaluate { string } \
{
catch { eval $string } got
if { $got ne "" } {
puts stderr $got
}
}
puts -nonewline stdout "MyShell > "
flush stdout
coolgets stdin evaluate; # this command should not wait for the enter button
# here goes some code which is to be executed before the enter button is hit
以下是我需要的:
proc prompt { } \
{
puts -nonewline stdout "MyShell > "
flush stdout
}
proc process { } \
{
catch { uplevel #0 [gets stdin] } got
if { $got ne "" } {
puts stderr $got
flush stderr
}
prompt
}
fileevent stdin readable process
prompt
while { true } { update; after 100 }
我认为您需要查看fileevent、fconfigure和vwait命令。使用这些,您可以执行以下操作:
proc GetData {chan} {
if {[gets $chan line] >= 0} {
puts -nonewline "Read data: "
puts $line
}
}
fconfigure stdin -blocking 0 -buffering line -translation crlf
fileevent stdin readable [list GetData stdin]
vwait x
这段代码将GetData注册为stdin的可读文件事件处理程序,因此只要有数据可读取,就会调用它。Tcl将类似“nohang”的功能应用于整个通道,通过将通道配置为非阻塞来完成。在此之后,任何
读取
都将只返回那里的数据,获取
将只返回无需等待即可使用的完整行,放置
(在可写通道上)将安排将其输出异步发送到操作系统。这取决于正在运行的事件循环
建议对已注册的文件事件处理程序使用非阻塞通道。您可以将其与非阻塞相结合,以实现您的coolget
想法:
proc coolget {channel callback} {
fileevent $channel readable [list apply {{ch cb} {
if {[gets $ch line] >= 0} {
uplevel [lappend cb $line]
} elseif {[eof $ch]} {
# Remove handler at EOF: important!
fileevent $ch readable {}
}
}} $channel $callback]
}
这样就可以很好地工作了,除了您必须调用vwait
或update
来处理事件(除非您也使用了Tk;Tk是特殊的),因为Tcl不会在后台神奇地处理事情;神奇的背景处理带来的麻烦太多了
<>如果你在异步事件处理中陷入了深深的纠结,请考虑使用TCL 8.6来重新构造代码。特别是像这样的代码可以帮助很多。然而,这在很大程度上依赖于Tcl 8.6,因为早期的Tcl实现根本不支持协同路由;底层实现必须从简单的C调用重写为continuations来启用这些特性,这是不可能的