Tcl Expect “interact” command echos previous output from spawned rlwrap process

六眼飞鱼酱① 提交于 2019-12-12 02:35:26

问题


I have a feeling there is something obvious I'm missing, but my searches are coming up fruitless thus far.

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.

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.

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?

Code:

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

Output:

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
%  

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

%  

回答1:


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;
}

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.

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?).

There is a small problem with your expect solution, if you specify any arguments, Tcl would execute that script, and never show the prompt.

Also note that I'm a novice C programmer, so this solution might not be bullet proof.




回答2:


What you want to do is to wait for an unambiguous marker that indicates that the subordinate process is ready.

# ... 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

Or at least that works when I try with a subordinate process, but I wasn't using rlwrap in the mix so that might change things…



来源:https://stackoverflow.com/questions/19290982/tcl-expect-interact-command-echos-previous-output-from-spawned-rlwrap-process

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!