Joel VanderWerf
2/24/2005 11:23:00 PM
Jim Freeze wrote:
> * Joel VanderWerf <vjoel@PATH.Berkeley.EDU> [2005-02-25 07:19:12 +0900]:
>
>
>>How could this work if echo is not even a ruby program? Maybe if you run
>>echo with popen, and print the output of that... But if you want it to
>>work with arb. ruby code, this won't help.
>
>
> It may not be possible. My knowledge of $stdout doesn't run too deep.
> So far, I have wrapped the write call, so puts is captured and I
> have reopened stdout to write to a file. So, I figured there should
> be a way to capture a system call (since it inherits $stdout from the
> current process).
A child process inherits the file handle that $stdout refers to, but not
the ruby object itself, even if the child process is ruby.
> The idea is to do the following:
>
> IO::Tee(file) {
> # all output is to go to file and screen
> puts "from ruby puts"
> system("echo", "from system")
> exec("echo", "from system")
> }
>
> and have the contents of file and the screen be identical.
You'll be disappointed by the following if you are using windows, but
what else is new.
------
class IO
def tee
IO.popen("-") do |pipe| # Won't work on mswin.
if pipe # parent
while (str = pipe.gets)
puts str
$stdout.puts str
end
else # child
yield
end
end
end
end
f=File.open("/tmp/tee-example-output", "w+")
f.tee do
puts "something"
puts "something else"
end
f.rewind
puts "The contents of file is:\n#{f.read.inspect}"
-------
output:
something
something else
The contents of file is:
"something\nsomething else\n"
Note that the "tee" block is executed in a child process, so state (e.g.
local vars) will not be changed when you get back to the main process.