set pipe [open "|$command |& cat" r+]
fconfigure $pipe -buffering line
which returns both stdout and stderr from $command. Can I open a second
pipe (to stderr) so that I can add stderr messages into my text widget
with a red tag, for instance ? Or is there some other way I can
differentiate the two channels when I read from the pipe ? I'd like to
be able to read from both pipes simultaneously (i.e. not wait until
$command has finished to get stderr)
I found a message on Deja saying this could possibly be done with tclX
'pipe' command, but I'm using tcl/tk 8.0.5 (on Linux RH 5.2). Any
suggestions would be very helpful.
Thanks,
Mark /
On unix it's easy: simulate the [pipe] command with a [open "|cat" r+],
then use the given channel in a 2>@ redirection; the stdout comes the
normal way:
set p [open "|cat" r+]
set f [open "|$command 2>@ $p" r+]
fileevent $p readable [list from_stderr $p]
fileevent $f readable [list from_stdout $f]
-Alex
: I want to exec a command and put the output into a text widget. I'm
: using the command:
: set pipe [open "|$command |& cat" r+]
: fconfigure $pipe -buffering line
: which returns both stdout and stderr from $command. Can I open a second
: pipe (to stderr) so that I can add stderr messages into my text widget
: with a red tag, for instance ? Or is there some other way I can
: differentiate the two channels when I read from the pipe ? I'd like to
: be able to read from both pipes simultaneously (i.e. not wait until
: $command has finished to get stderr)
: I found a message on Deja saying this could possibly be done with tclX
: 'pipe' command, but I'm using tcl/tk 8.0.5 (on Linux RH 5.2). Any
: suggestions would be very helpful.
The "bgexec" command in BLT lets you do this in a simple,
straight-forward way.
text .text
.text tag configure stdoutTag -foreground green
.text tag configure stderrTag -foreground red
proc DisplayOutput { string } {
.text insert end $string stdoutTag
}
proc DisplayErrors { string } {
.text insert end $string stderrTag
}
bgexec myVar \
-onoutput DisplayOutput -onerror DisplayErrors \
$command &
The -onoutput and -onerror switches specify procedures that get called
whenever data is available on that channel. Both procedures take one
argument that is the new data.
The varible "myVar" gets set when the command is done executing. It
will contain the return code, message, etal. of the command. So you
can get the command run in the background (using "&" as the last
argument of the command) and still know when it finishes by putting a
trace on that variable.
If you need to stop the command while its running, just set the
"myVar" and the program will be killed. "bgexec" accepts all the same
syntax as the "exec" command. And it works the same way under both
Unix and Windows.
--gah
Except for the buffering introduced by "cat" itself. Easiest solution
is to write a replacement for cat in Tcl that doesn't buffer its
output. I leave this as an exercise in the use of [gets], [eof] and
[fconfigure]...
Donal.
--
Donal K. Fellows http://www.cs.man.ac.uk/~fellowsd/ fell...@cs.man.ac.uk
-- The small advantage of not having California being part of my country would
be overweighed by having California as a heavily-armed rabid weasel on our
borders. -- David Parsons <o r c @ p e l l . p o r t l a n d . o r . u s>
Good answer. It would be nice if Tcl came packaged with a cross platform
pipe package.
--
Paul Duffin
DT/6000 Development Email: pdu...@hursley.ibm.com
IBM UK Laboratories Ltd., Hursley Park nr. Winchester
Internal: 7-246880 International: +44 1962-816880
Right. Much faster and easier when available, is 'cat -u' (I don't know
its platform coverage though - I need it so often that I've written one
for NT :).
Another alternative which is nearly as fast, nearly as easy, but
conceptually awful is connecting a socket to the 'echo' port of the
local host...
All this to say, "Please, [pipe] in the core, fast !!!"
-Alex
There is a tool built to accomplish this and a whole lot more called
tkWorld. Check it out at www.tkworld.org.
Wes Bailey
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
No. Just a way to get hold of stderr out of a program started with
[open |...] in the core "fast !!!" as the current behaviour of only
getting the errors at pipe closure is not all that useful if you are
trying to automate a program (since many programs that want
interaction also generate errors on stderr as they go that need
responding to.) What we've got now is a solution that is too close
(IMO) to [exec] in this respect.
I'm not too sure that the other fancier features of [bgexec] are
needed at the moment though. Having them in an extension is possibly
better for now.
Oh, and the reason that [pipe] is possibly harmful is that it is very
easy to tie yourself into knots with that (remembering the bad old
days of C hacking.) Simpler and clearer solutions are probably better
from the PoV of making the language easy enough to be comprehendable
by non-gurus...
Another nice outcome of a generic pipe command is that it also solves
the 'half-close':
set p1 [pipe]
set p2 [open "|cmd <@ $p1" r]
...
close $p1
gets $p2 postmortem
Donal, I don't understand your reservations here; you seem to be
advocating an Occam-like minimization, but in a skewed way since you end
up proposing a very specific fix instead of a very generic tool (which
is by the way readily available in all OSes where redirection makes
sense)
> Oh, and the reason that [pipe] is possibly harmful is that it is very
> easy to tie yourself into knots with that (remembering the bad old
> days of C hacking.)
As soon as you give a powerful thing, you'll find bad uses - so don't
provide *any* tool, right ?
Loops are expected to kill an algorithm designed for acyclic graphs, and
so on. Should we forbid any graph structure for that ?
[pipe] is just the building block for rich IPC, the basic edge of the
graph...
And BTW, even with the existing [open "|cmd" r+] it is easy to get a
deadlock:
set p [open "|cat" r+]
fconfigure $p -buffering none -translation binary
puts -nonewline $p $MORE_THAN_TWICE_PIPEBUF
# you'll never get here anyway
read $p 1
-Alex