我有一种感觉,很明显我遗漏了什么,但我的搜索到目前为止都是徒劳的。
我正在尝试使用tcl/expect脚本启动一个tclsh交互式shell,添加一个用于轻松重新加载实用程序以进行测试的过程,然后将正常的控制权返回给我。
到目前为止,我发现的使tcl交互式shell“可用”的一种方法是以"rlwrap“开始,这样我就可以使用箭头键,等等。
因此,我尝试了以下脚本,当命中interact命令时,有关rlwrap的某些内容会导致以前的输出转储到stdout。
我能做些什么来避免这种情况发生吗?
代码:
package require Expect
puts "Tcl version : [info tclversion]"
puts "Expect version: [exp_version]"
log_user 0
spawn -noecho rlwrap tclsh
# Create procedure to easily reload utilites after changes have been made
expect "% "
send {
proc reload {} {
# Procedure to reload utility source easily for testing
}
}
# Source utilities
expect "% "
send "reload\r"
send_user "\nUse 'reload' procedure to re-source utility files\n\n"
log_user 1
interact输出:
Tcl version : 8.4
Expect version: 5.43.0
Use 'reload' procedure to re-source utility files
proc reload {} {
# Procedure to reload utility source easily for testing
}
% reload
% 您可以看到,由于某种原因,它正在回显proc定义和输入reload命令。一旦发生交互,就会发生这种情况。如果我将interact替换为"exit“,我看不到任何输出。
当然,我希望看到的输出是这样的:
Tcl version : 8.4
Expect version: 5.43.0
Use 'reload' procedure to re-source utility files
% 发布于 2013-10-15 18:35:20
如果你不介意自己编译一个小的C程序,你可以使用下面的代码:
#include <tcl.h>
#ifdef WIN32
#ifdef UNICODE
#define WIN32_UNICODE
#endif
#endif
int TclSHI_Main(Tcl_Interp*);
static int g_argc;
#ifdef WIN32_UNICODE
#define Tcl_NewStringObj Tcl_NewUnicodeObj
static wchar_t*** g_argv;
void wmain(int argc, wchar_t **argv) {
#else
static char*** g_argv;
void main(int argc, char **argv) {
#endif
g_argc = argc;
g_argv = &argv;
Tcl_FindExecutable(argv[0]);
Tcl_Main(1, argv, TclSHI_Main);
}
int TclSHI_Main(Tcl_Interp* interp) {
Tcl_Obj* lobj;
int i;
if (g_argc > 1) {
Tcl_SetVar2Ex(interp, "argv0", NULL, Tcl_NewStringObj((*g_argv)[1], -1), TCL_GLOBAL_ONLY);
}
lobj = Tcl_NewObj();
Tcl_IncrRefCount(lobj);
for (i = 2; i < g_argc; i++) {
Tcl_ListObjAppendElement(interp, lobj, Tcl_NewStringObj((*g_argv)[i], -1));
}
Tcl_SetVar2Ex(interp, "argv", NULL, lobj, TCL_GLOBAL_ONLY);
Tcl_DecrRefCount(lobj);
Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(g_argc - 2), TCL_GLOBAL_ONLY);
if (g_argc > 1) {
Tcl_Eval(interp, "source $argv0");
}
return TCL_OK;
}我在windows (CL)和linux (GCC)上进行了测试。
为了和gcc一起编译,我用的是gcc TclSH.c -o TclSHI -ltcl8.6
在windows上我使用的是Visual Studio。
它告诉Tcl它没有接收到任何参数(Tcl_Main(1,...)),但是用这个参数填充新的interp并获取文件。在此步骤之后,它将始终显示提示(它从未收到任何参数,对吗?)。
您期望的解决方案有一个小问题,如果您指定了任何参数,Tcl将执行该脚本,并且永远不会显示提示。
还要注意,我是一个C程序员新手,所以这个解决方案可能不是万无一失的。
发布于 2013-10-11 03:45:28
您要做的是等待一个明确的标记,该标记指示从属进程已准备就绪。
# ... your script as above ...
expect "% "
#### NEW STUFF STARTS ####
send "reload;puts READY\r"
expect "READY\r"
# Note that we need to fake the prompt; c'est la vie
send_user "\nUse 'reload' procedure to re-source utility files\n\n% "
# Now start doing things!
log_user 1
interact或者至少当我尝试使用从属进程时,这是有效的,但我没有在混合中使用rlwrap,所以这可能会改变…
https://stackoverflow.com/questions/19290982
复制相似问题