Tcl期望“交互".命令从生成的rlwrap进程回显先前的输出 [英] Tcl Expect "interact" command echos previous output from spawned rlwrap process
问题描述
我有一种明显的缺憾,但到目前为止,我的搜索无济于事.
I have a feeling there is something obvious I'm missing, but my searches are coming up fruitless thus far.
我正在尝试使用tcl/expect脚本启动tclsh交互式外壳程序,添加一个过程以轻松地重新加载实用程序进行测试,然后将正常控制权返回给我.
I am trying to use a tcl/expect script to start up a tclsh interactive shell, add a procedure for easily reloading utilities for testing, and then return normal control to me.
到目前为止,我发现使tcl交互式外壳可用"的一种方法是以"rlwrap"启动它,以便我可以使用箭头键等.
So far, the one way I've discovered to make a tcl interactive shell "usable" is to start it with "rlwrap" so that I can use arrow keys, etc.
因此,我尝试了以下脚本,并且与rlwrap有关的某些内容导致在单击交互命令时将先前的输出转储到stdout.
So I tried the following script and something about rlwrap is causing previous output to be dumped to stdout when the interact command is hit.
我可以做些什么来使这种情况不发生吗?
Is there something I can do to make this not happen?
代码:
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命令.一旦发生交互,就会发生这种情况.如果将"interit"替换为"exit",则看不到任何输出.
You can that for some reason it's echoing the proc definition and the entering of the reload command. This occurs as soon as interact occurs. If I replace interact with "exit" I do not see any of this output.
当然,我希望看到的输出是这样:
Of course the output I'm hope to see would be this:
Tcl version : 8.4
Expect version: 5.43.0
Use 'reload' procedure to re-source utility files
%
推荐答案
如果您不介意自己编译一个小型C程序,则可以使用以下代码:
If you don't mind to compile a small C program yourself, you could use this:
#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.
I tested it on windows (CL) and linux (GCC).
To compile it with gcc I used gcc TclSH.c -o TclSHI -ltcl8.6
On windows I used Visual Studio.
它告诉Tcl它没有接收任何参数(Tcl_Main(1,...)
),但是使用此参数填充新的interp并获取文件.完成此步骤后,它将始终显示提示(它从未收到任何参数,对吧?).
It tells Tcl that it did not receive any arguments (Tcl_Main(1,...)
), but populates the new interp with this arguments and sources the file. After this step it will always show the prompt (it never received any arguments, right?).
期望解决方案存在一个小问题,如果指定任何参数,Tcl将执行该脚本,并且从不显示提示.
There is a small problem with your expect solution, if you specify any arguments, Tcl would execute that script, and never show the prompt.
还请注意,我是C语言的新手,因此此解决方案可能不是防弹的.
Also note that I'm a novice C programmer, so this solution might not be bullet proof.
这篇关于Tcl期望“交互".命令从生成的rlwrap进程回显先前的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!