Hi
I am writing a tee function for ruby and am pretty close.
The problem I am having now is that I don't know
how to extend $stdout#write and have it survive
a system (or exec) call.
Below is some code illustrating what I have:
> cat tee.rb
module M
def write(a)
super("fred\n")
end
end
$stdout.extend(M)
puts "puts: should be fred" # prints twice for some reason
system("echo", "system: should be fred") # no fred
> ruby tee.rb
fred
fred
system: should be fred
If this is not possible, maybe there is a way with alias_method,
but I haven't been able to get that going either.
TIA
···
--
Jim Freeze
Code Red. Code Ruby
Jim Freeze wrote:
Hi
I am writing a tee function for ruby and am pretty close.
The problem I am having now is that I don't know
how to extend $stdout#write and have it survive
a system (or exec) call.
Below is some code illustrating what I have:
> cat tee.rb
module M
def write(a)
super("fred\n")
end
end
$stdout.extend(M)
puts "puts: should be fred" # prints twice for some reason
system("echo", "system: should be fred") # no fred
> ruby tee.rb
fred
system: should be fred
If this is not possible, maybe there is a way with alias_method,
but I haven't been able to get that going either.
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.
Probably the only hope is to $stdout.reopen into something you can read and do what you want with. Never tried it tho.
Jim Freeze wrote:
Hi
I am writing a tee function for ruby and am pretty close.
Does Sean Chittenden's io-tee package not work? It's on the RAA.
Regards,
Dan
* 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).
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.
···
--
Jim Freeze
Code Red. Code Ruby
* Daniel Berger <djberg96@hotmail.com> [2005-02-25 14:20:00 +0900]:
Does Sean Chittenden's io-tee package not work? It's on the RAA.
Don't know. rubynet.org seems to be down. I wrote Sean about
it this morning, but no reply.
···
--
Jim Freeze
Code Red. Code Ruby
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.
Jim Freeze wrote:
* Daniel Berger <djberg96@hotmail.com> [2005-02-25 14:20:00 +0900]:
> Does Sean Chittenden's io-tee package not work? It's on the RAA.
Don't know. rubynet.org seems to be down. I wrote Sean about
it this morning, but no reply.
--
Jim Freeze
Code Red. Code Ruby
Ah, you're right. In any case, if you can read Perl it's probably
worth your while to look at Chung-chieh Shan's IO::Tee module, on CPAN.
Regards,
Dan
Joel VanderWerf wrote:
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"
system("echo", "from system")
end
Head.whack! I forgot to show that this does work with system calls...
* Daniel Berger <djberg96@hotmail.com> [2005-02-26 04:39:58 +0900]:
Ah, you're right. In any case, if you can read Perl it's probably
worth your while to look at Chung-chieh Shan's IO::Tee module, on CPAN.
Thanks. I'll take a look
···
--
Jim Freeze
Code Red. Code Ruby
* Joel VanderWerf <vjoel@PATH.Berkeley.EDU> [2005-02-25 08:27:04 +0900]:
Joel VanderWerf wrote:
>class IO
> def tee
> IO.popen("-") do |pipe| # Won't work on mswin.
Windows shmwindows. So what? 
> 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"
system("echo", "from system")
end
Nice twist on this. I like it, but maybe I'm too tired.
How would I integrate capturing stderr also?
I tried popen3, but couldn't get that to work either.
···
--
Jim Freeze
Code Red. Code Ruby