Fork style of little programs

Hello everybody,

I would like to build some small ruby programs, that will work
together as the unix shell commands. Eg the following could be used
inside a Cygwin shell:

$ ruby evallog.rb | ruby sum.rb "Log: (.*)"

which will evaluate a logfile, dump the result in lines, and the
second program will sum up the entries beginning with "Log: ". Just
to give you a sample how to do it.

I now try to combine the two little programs in one program without
redefining the way their methods work. The first just writes out its
result by "puts ...", the second uses the variable $stdin. But how
could a new method look that combines the two? I have no idea how to
write it down. Is there something to "fork" the first one, so that
the second one can read from standard input while the first writes to
standard output?

Thank you very much for your patience ...

···

--
Markus Email: markus.liebelt@online.de

IO.popen("-") do | pipe |
  if (pipe) then
    # in parent; communicate with child through pipe
  else
    # in child; communicate with parent through stdio
  end
end

  Sean O'Dell

···

On Monday 12 July 2004 14:32, Markus Liebelt wrote:

I now try to combine the two little programs in one program without
redefining the way their methods work. The first just writes out its
result by "puts ...", the second uses the variable $stdin. But how
could a new method look that combines the two? I have no idea how to
write it down. Is there something to "fork" the first one, so that
the second one can read from standard input while the first writes to
standard output?

maybe you want IO.popen ?

···

il Mon, 12 Jul 2004 23:30:30 +0200, Markus Liebelt <markus.liebelt@online.de> ha scritto::

"Markus Liebelt" <markus.liebelt@online.de> schrieb im Newsbeitrag
news:ufz7wdibt.fsf@online.de...

Hello everybody,

I would like to build some small ruby programs, that will work
together as the unix shell commands. Eg the following could be used
inside a Cygwin shell:

$ ruby evallog.rb | ruby sum.rb "Log: (.*)"

which will evaluate a logfile, dump the result in lines, and the
second program will sum up the entries beginning with "Log: ". Just
to give you a sample how to do it.

I now try to combine the two little programs in one program without
redefining the way their methods work. The first just writes out its
result by "puts ...", the second uses the variable $stdin. But how
could a new method look that combines the two? I have no idea how to
write it down. Is there something to "fork" the first one, so that
the second one can read from standard input while the first writes to
standard output?

You could use a Queue (or an in process pipe implementation, if there is
such a thing in ruby) and two threads within the same process.

Regards

    robert

Hello Sean,

your input gave me a solution that might be used in the future.

Because I think other's may have the same issue as I had, I want to
give a sketch of the solution.

>

My original question was a little bit misleading. I can restructure
my programs, but I want to use them both directly in the shell as
well as components in a bigger ruby program.

I now try to combine the two little programs in one program without
redefining the way their methods work. The first just writes out
its result by "puts ...", the second uses the variable $stdin. But
how could a new method look that combines the two? I have no idea
how to write it down. Is there something to "fork" the first one,
so that the second one can read from standard input while the first
writes to standard output?

IO.popen("-") do | pipe |
  if (pipe) then
    # in parent; communicate with child through pipe
  else
    # in child; communicate with parent through stdio
  end
end

I tried forth and back with your solution, but to no avail. But I
read a lot in programming ruby (section IO), so I got a new idea.

If I have a file tf.rb with definition of class TestFirst with method
test_out, which normally writes on $stdout, and I have a second file
ts.rb with definition of class TestSecond with method test_in, which
normally reads from $stdin, the following will work:
1. change the second definition by providing an argument io
2. use it in the file usage of ts.rb (is there a name for that??):
   if __FILE__ == $0
     puts TestSecond.new.test_in($stdin)
   end
3. Combine then the two programs in the following way:
  def test_both
    rd, wr = IO.pipe
    tmp_out = $stdout
    $> = wr
    TestFirst.new.test_out
    wr.close
    $> = tmp_out
    return TestSecond.new.test_in(rd)
  end
4. I'm sure there could be a way to abstract the surrounding away so
   that something like the following remains:

   use_read_writer(
     { TestFirst.new.test_out },
     { | reader |
       TestSecond.new.test_in(reader) })

   Anyone to help out :wink:
       
The equivalent in the shell could look like this:
$ ruby tf.rb | ruby ts.rb

So the base idea is to open for each pipe in the usage in the shell a
pipe in ruby, and redirect the $stdout to the writer of the pipe,
give the IO object that is normally $stdin as argument to the method
you want to call.

I have tested this version with the cygwin shell under Win-XP and
even in the DOS Shell (shudder) with ruby-1-8-1, it works (wow).

I'm not sure that this is the simplest solution, but it is doable for
me and I see no drawback of it.

  Sean O'Dell

Many thank's to all the people that helped me and other rookies to
get the right ideas. And thank' to the creator of ruby to that
wonderful language (never thought that I will find something more
consistent and elegant than Smalltalk).

Bye

···

On Monday 12 July 2004 14:32, Markus Liebelt wrote:

--
Markus Email: markus.liebelt@online.de