Version 0 of Interrupting loops

Updated 1999-08-17 12:25:42

Q. Is there a way a user can press a "stop" button, for example, to stop the running script without killing the main application?

A1. by mailto:[email protected] : You can get much of the effect you want by selectively redefining key TCL commands. You could, for instance, have the cancel button set a "cancelled" global. Then, you can define a cancelled function which checks for the existence of this global and calls "error" if it is exists. Finally, you can redefine commands like while so that they will insert a call to the cancelled command at the top of each loop. It might look something like this...

 proc cancelled {} {
    global cancelled
    # give the user a chance to hit the cancel button
    update
     if [info exists cancelled] {
         error "Script Cancelled by User"
     }
 }

 rename while _while
 proc while {condition body} {
        uplevel [list _while $condition "cancelled;$body"]
 }

If you redefine the proc command and the loop commands then you will get pretty good coverage. You might also want use the after command to set a time limit on the execution. Something like...

 set timeLimit 1000
 set timerId [after $timeLimit {set timedOut 1}]

Then you would have the cancelled function check this variable as well. Just be sure that you run "after cancel $timerId" and unset the cancelled and timedOut variables when you return from the users scripts.

A2. by Michael Barth mailto:[email protected] : The solution I have implemented is simple: create a new process with the user script. Additionally you can redirect the standard output of the "user process" to a text widget.

 # tcl code not tested:
 button .interrupt -command {close $FID}
 pack .interrupt

 set FID [open |userscript r]
 fileevent readable $FID writeToTextWidget

(From posts in news:comp.lang.tcl , slightly adapted by RS. Note however that frequent updates make long runs last even longer ;-)