由于我可以访问程序的 Tcl shell,是否可以启用错误时失败?
让我试着用我的话来总结一下:您想在出错时退出交互式 Tcl shell,而不是再次提供提示?
更新
我正在使用 Tcl 8.3,就可用工具而言,这是一个严重的限制 [...] 只有 C 代码的源补丁。
由于您似乎深陷于那个兔子洞,为什么不添加另一个源补丁呢?
--- tclMain.c 2002-03-26 03:26:58.000000000 +0100
+++ tclMain.c.mrcalvin 2019-10-23 22:49:14.000000000 +0200
@@ -328,6 +328,7 @@
Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
Tcl_WriteChars(errChannel, "\n", 1);
}
+ Tcl_Exit(1);
} else if (tsdPtr->tty) {
resultPtr = Tcl_GetObjResult(interp);
Tcl_GetStringFromObj(resultPtr, &length);
这是未经测试的,Tcl 8.3.5 源不为我编译。但是这部分Tcl的内部和现在的源码相当,使用我的Tcl 8.6源码安装测试。
对于记录
有了股票壳(tclsh
),这恐怕有点繁琐。以下可能对您有用(不过,我可以想象这可能会让您失望的情况)。这个想法是
- 拦截写入
stderr
(这是交互式 shell 在返回提示之前重定向错误消息的位置)。
- 为了区分任意写入
stderr
和错误情况,可以使用全局变量::errorInfo
作为哨兵。
第 1 步:定义通道拦截器
oo::class create Bouncer {
method initialize {handle mode} {
if {$mode ne "write"} {error "can't handle reading"}
return {finalize initialize write}
}
method finalize {handle} {
# NOOP
}
method write {handle bytes} {
if {[info exists ::errorInfo]} {
# This is an actual error;
# 1) Print the message (as usual), but to stdout
fconfigure stdout -translation binary
puts stdout $bytes
# 2) Call on [exit] to quit the Tcl process
exit 1
} else {
# Non-error write to stderr, proceed as usual
return $bytes
}
}
}
stderr
第 2 步:在交互式 shell 中注册拦截器
if {[info exists ::tcl_interactive]} {
chan push stderr [Bouncer new]
}
注册后,这将使您的交互式 shell 的行为如下:
% puts stderr "Goes, as usual!"
Goes, as usual!
% error "Bye, bye"
Bye, bye
一些备注
- 您需要小心
Bouncer
'swrite
方法,错误消息已经针对字符编码进行了按摩(因此,fconfigure
调用)。
- 您可能希望将其放入 Tcl 包或 Tcl 模块中,以使用
package req
.
- 我可以想象您的程序写入
stderr
并且errorInfo
变量恰好被设置(作为剩余),这将触发意外退出。