screwtop
screwtop

Reputation: 111

Can a non-interactive tclsh be made interactive?

When developing Tcl code, I find the interactive facilities of tclsh very useful, and I'll often launch tclsh interactively, source code from files, and continue to run and debug from there.

What I'm wondering is: is there a way to drop into the interactive shell from a tclsh instance that is not interactive (say because it was run with a script file argument)? I know there's a tcl_interactive variable, which can be set, but doing so does not result in an interactive prompt.

I'd prefer to be able to do this within the same process and terminal (though Tkcon is certainly wonderful).

(I would guess that the tricky thing would be switching Tcl's input from the specified script file to the terminal/pty's stdin. That may be something that requires Expect's magic to work. I've also pondered some trickery using .tclshrc, but that gets messy; I wish tclsh let you specify an rc-file on the command line or via an environment variable.)

Upvotes: 1

Views: 84

Answers (2)

Donal Fellows
Donal Fellows

Reputation: 137577

On all Unix platforms, you get a handle to the terminal by opening /dev/tty. You can then implement your own REPL. The code to do that will look something like this.

set tty [open /dev/tty r+]
fconfigure $tty -buffering none
set buffer ""
while {![eof $tty]} {
    puts -nonewline $tty "> "
    gets $tty line
    append buffer $line "\n"
    if {[info complete $buffer]} {
        try {
            # Or uplevel or interp eval
            eval $buffer
        } on ok result {
            if {$result ne ""} {puts $tty $result}
        } on error {msg opt} {
            puts stderr [dict get $opt -errorinfo]
        }
        set buffer ""
    }
}

Upvotes: 2

Cyan Ogilvie
Cyan Ogilvie

Reputation: 850

You could start up a tclreadline REPL:

proc poll {} {
    puts "doing something"
    if {[incr ::pollnum] == 3} {
        package require tclreadline
        tclreadline::Loop
    }
    after 2000 poll
}

poll

vwait forever
doing something
doing something
doing something
tclsh8.7 [/tmp] puts "hello, repl"
hello, repl
tclsh8.7 [/tmp] 

Upvotes: 0

Related Questions