From: Shea Martin <null / void.0>
Subject: tk app, reading output from command and put it in a text widget
Date: Thu, 6 Oct 2005 05:31:49 +0900
Message-ID: <XIW0f.104652$Ph4.3184945 / ursa-nb00s0.nbnet.nb.ca>
> I have a button which launches and externcal command.  I want to capture 
> the output of that command and append it to my text area.  Can I do this 
> with events?

Hmmm... 
Maybe, TkTextIO class (a Tk sample included in Ruby-1.8.3) is useful. 
For example, 
-----------------------------------------------------------------------
require 'tk'
require 'open3'

# use TkTextIO class which is one of the sample scripts on Ruby source archive.
tk_sample_dir = '/usr/local/src/ruby-1.8.3/ext/tk/sample'
require File.join(tk_sample_dir, 'tktextio.rb')

f = TkFrame.new.pack
tio = TkTextIO.new(f, :show=>:pos){
  yscrollbar(TkScrollbar.new(f).pack(:side=>:right, :fill=>:y))
  pack(:side=>:left, :fill=>:both, :expand=>true)
}

org_stdout = $stdout
$stdout = tio
$stderr = tio

# execute an external command
# ( In this way, cannot determine the output order between stdout and stderr. )
def ex_cmd(cmd)
  p_in, p_out, p_err = *Open3.popen3(cmd)

  [
    p_in, 
    Thread.new{ p_out.each{|line| print(line) } },
    Thread.new{ p_err.each{|line| print(line) } }
  ]
end

f = TkFrame.new.pack(:fill=>:x, :padx=>40)

cmd = '/bin/cat - nofile' # external command

TkButton.new(f, :text=>'exec external command'){|b|
  command {
    b.state(:disabled)    # disable the button while ex_cmd is running
    Thread.new{           # create a thread to avoid hang-up of the eventloop
      begin
        p_in, out_th, err_th = ex_cmd(cmd)
        p_in.print("foo foo foo\n")
        p_in.print("bar bar bar\n")
        p_in.print("baz baz baz\n")
        p_in.print("hoge hoge hogw\n")
        p_in.print("fuga fuga fuga\n")
        p_in.close_write
        out_th.join
        err_th.join
      ensure
        b.state(:normal)  # enable the button
      end
    }
  }
}.pack(:side=>:left)

# TkTextIO is a subclass of TkText
TkButton.new(f, :text=>'print log to console', 
             :command=>proc{org_stdout.print(tio.value)}).pack(:side=>:right)

Tk.mainloop
-----------------------------------------------------------------------
-- 
Hidetoshi NAGAI (nagai / ai.kyutech.ac.jp)