Artzog
Artzog

Reputation: 13

How to get immediate output in my IDE from a Tcl script?

I have just started to use the tcl language and I need to create a script with several functions triggered every 2 seconds. I have been searching an answer on the internet and found several topics about it. For instance, I found this code on StackOverlow (How do I use "after ms script" in TCL?):

#!/usr/bin/tclsh

proc async {countdown} {
        puts $countdown
        incr countdown -1
        if {$countdown > 0} {
                after 1000 "async $countdown"
        } else {
                after 1000 {puts Blastoff!; exit}
        }
}

async 5

# Don't exit the program and let async requests
# finish.
vwait forever

This code could very easily be adapted to what I want to do but it doesn't work on my computer. When I copy paste it on my IDE, the code waits several second before giving all the outputs in one go. I had the same problem with the other code I found on the internet.

It would be great if someone could help me. Thanks a lot in advance.

Upvotes: 1

Views: 164

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137567

I've just pasted the exact script that you gave into a tclsh (specifically 8.6) running in a terminal on macOS, and it works. I would anticipate that your script will work on any version from about Tcl 7.6 onwards, which is going back nearly 25 years.

It sounds instead like your IDE is somehow causing the output to be buffered. Within your Tcl script, you can probably fix that by either putting flush stdout after each puts call, or by the (much easier) option of putting this at the start of your script:

fconfigure stdout -buffering line
# Or do this if you're using partial line writes:
#      fconfigure stdout -buffering none

The issue is that Tcl (in common with many other programs) detects whether its standard output is going to a terminal or some other destination (file or pipe or socket or …). When output is to a terminal, it sets the buffering mode to line and otherwise it is set to full. (By contrast, stderr always has none buffering by default so that whatever errors that occur make it out before a crash; there's nothing worse than losing debugging info by default.) When lots of output is being sent, it doesn't matter — the buffer is only a few kB long and this is a very good performance booster — but it's not what you want when only writing a very small amount at time. It sounds like the IDE is doing something (probably using a pipe) that's causing the guess to be wrong.

(The tcl_interactive global variable is formally unrelated; that's set when there's no script argument. The buffering rule applies even when you give a script as an argument.)


The truly correct way for the IDE to fix this, at least on POSIX systems, is for it to use virtual terminal to run scripts instead of a pipeline. But that's a much more complex topic!

Upvotes: 1

Related Questions