In my main tcl script, I am calling a tcl proc wrapped in a catch command. This proc in-turn calls 10 more procs.
When there is an error in execution in any of those
catch
won't capture the stdout of a Tcl procedure, it will capture the return value.
A demo in an interactive tclsh:
% proc p {} {puts "some stdout"; return "return value"}
% catch p result
some stdout
0
% set result
return value
The catch
command doesn't intercept I/O at all. To intercept output, the simplest and most method is to put a channel transform on that channel with chan push
.
oo::class create Capture {
variable contents encoding
# Implement the channel interception protocol
method initialize {handle mode} {
set contents {}
return {initialize finalize write}
}
method finalize handle {
# We do nothing here
}
method write {handle buffer} {
append contents $buffer
return $buffer
}
# Methods for ordinary people!
method capture {channel body} {
set encoding [chan configure $channel -encoding]
chan push $channel [self]
try {
uplevel 1 $body
} finally {
chan pop $channel
}
}
method contents {} {
# Careful; need the encoding as channels work with binary data
return [encoding convertfrom $encoding $contents]
}
}
How to use this class:
set capt [Capture new]
$capt capture stdout {
puts "Hello world!"
}
puts "Captured [string length [$capt contents]] characters"
puts [lmap c [split [$capt contents] ""] {scan $c "%c"}]
Output (I assume you recognise ASCII codes; the 13 10
at the end is a carriage-return/new-line sequence):
Hello world!
Captured 14 characters
72 101 108 108 111 32 119 111 114 108 100 33 13 10