Version 23 of a way to 'pipe' from an external process into a text widget

Updated 2012-03-09 02:05:18 by AMG

That's what test2.tcl in this [L1 ] "Regular Expressions" [L2 ] column does.

Also see the fileevent page.

The sample chapter 22 from Brent Welch's book can be downloaded from his home page and ( "TK Examples", or "TK by Example" ) [L3 ] also gives an example of this.


The link on top may not clarify this at a glance. I myself was thinking about opportunities with pipes and send, and how to handle remote command execution with both methods. See Playing with Pipes, Send and DDE - RJM

Reference to text widget.


Can anyone point to an example where a text widget displays the stdout and stderr from a command, as it is produced - not waiting until the execution finishes?

Rfox 3/8/2012 - This is done by the NSCLDAQ Readout Gui. The data taking program is a command driven program (Tcl Interpreter), the stdout and stderr of this program, which may be run over an ssh pipe, are captured in an output window as they occur as often experimenters will insert debugging output.

AMG: See How to run external script from Tk and make it throw output to the console? and [L4 ].

package require Tcl 8.6
package require Tk
set shell [list csh]
proc log {text {tags {}}} {
    .output configure -state normal
    .output insert end $text $tags
    .output configure -state disabled
    .output see end
}
ttk::entry .input
ttk::scrollbar .scroll -orient vertical -command {.output yview}
text .output -state disabled -yscrollcommand {.scroll set}
.output tag configure input -background gray
.output tag configure error -background red
pack .input -fill x -side bottom
pack .scroll -fill y -side right
pack .output -fill both -expand 1
focus .input
lassign [chan pipe] rderr wrerr
set stdio [open |[concat $shell [list 2>@ $wrerr]] a+]
foreach {chan tags} [list $stdio "" $rderr error] {
    chan configure $chan -buffering line -blocking 0
    chan event $chan readable [list apply {{chan tags} {
        log [chan read $chan] $tags
        if {[chan eof $chan]} {
            log EOF error
            .input state disabled
            chan close $chan
        }
    }} $chan $tags]
}
bind .input <Return> [list apply {{chan} {
    log [.input get]\n input
    chan puts $chan [.input get]
    .input delete 0 end
}} $stdio]