On Wed, Aug 07, 2002 at 08:22:48AM +0900, alex f wrote: > In particular, I'm interested in doing things similar to what I did in Perl > with select and tie-ing STD filehandles to classes temporarily then > returning to program default values. I've seen an interesting example of a > string-based class implementing IO-like behaviour in 'The Ruby Way' > (223-225), but I'm not sure how to manipulate Ruby's STDOUT and $stdout to > do useful things with these sort of classes (using .reopen()?), so I'd > appreciate pointers to threads or example code. There's been some discussion (http://www.rubygarden.org/article.php?sid=179) about changing IO to make this task (and other tasks) easier. At the moment, reopen() can only be using with real IO objects (and won't work with a StringIO object). The following will work, but the solution is not ideal. I'd like to make it buffered (for better performance), and I'm not sure what should happen if stop() is called when there is still data to be read. And if you want to be able to make this work during a system call, then you'll need to use a separate process instead of a thread. Hope this helps, Paul # A *very* basic StringIO implementation class StringIO attr_reader :str def initialize @str = '' end def write(str) @str << str end end # A class to redirect $stdout (or other IO object) to a StringIO object # (or other object with a write() method) class Redirector def initialize(from, to) tmp = from.dup r, w = IO.pipe from.reopen(w) @t = Thread.new do begin loop do s = r.read(1) # TODO: can I make this buffered? to.write(s) end ensure from.reopen(tmp) end end end def stop @t.kill end def self.redirect(from, to) s = self.new(from, to) begin yield ensure s.stop end end end if __FILE__ == $0 then Thread.abort_on_exception = true s = StringIO.new r = Redirector.redirect($stdout, s) do $stdout.puts "this is a test" $stdout.puts "of the StringIO redirection system" end puts "Done redirecting." puts "Result:\n#{s.str}" end