Differences

This shows you the differences between two versions of the page.

Link to this comparison view

rubyexpect [2014/10/26 01:52] (current)
Line 1: Line 1:
 +===== Ruby Expect =====
 +Original from [[http://​www.rubygarden.org/​ruby?​RExpect|RubyGarden]]
 +
 +<code ruby>
 +#​!/​usr/​bin/​ruby
 +#
 +# $Id$
 +#
 +# RExpect.rb
 +#
 +
 +require '​pty'​
 +require '​thread'​
 +require '​timeout'​
 +
 +$expect_verbose = true
 +
 +Thread.abort_on_exception = true
 +
 +class RExpect
 +  attr_reader :pid
 +
 +  def RExpect.spawn(cmd)
 +    mutex = Mutex.new
 +    mutex.synchronize do
 +      ​
 +      resultResource = ConditionVariable.new
 +      result = nil
 +      Thread.new do
 +        pid = nil
 +        mutex.synchronize do
 +          inf, outf, pid, fileName = PTY.spawn(cmd)
 +          result = RExpect.new( inf, outf, pid, fileName)
 +          resultResource.signal
 +        end
 +        result.inputData
 +      end
 +      ​
 +      resultResource.wait( mutex)
 +      return result
 +    end
 +  end
 +  ​
 +  def log(a)
 +    @log.puts "#​{caller(1)[0]}:#​{a}"​ unless @log.nil?
 +  end
 +
 +  def initialize(inf,​outf,​pid,​fileName)
 +    @inf,​@outf,​@pid,​@fileName = inf,​outf,​pid,​fileName
 +    if $expect_verbose then
 +      @log = File.open( "​rexpect.log.#​{@pid}",​ "​w"​)
 +      @log.sync = true
 +    else
 +      @log = nil
 +    end
 +
 +    @outf.sync=true
 +    @buffer = ''​
 +    @mutex = Mutex.new
 +    @bufferResource = ConditionVariable.new
 +  end
 +
 +  def wait
 +    Process.waitpid(@pid,​0)
 +  rescue
 +  end
 +
 +  def kill
 +    kill( "​SIGTERM",​ @pid)
 +    wait
 +  end
 +
 +  def inputData
 +    while true
 +      data = @inf.sysread( 65536)
 +      @mutex.synchronize do
 +        log( "​BUFFER:#​{@buffer}\nNEWDATA:#​{data}"​ )
 +        @buffer << data
 +
 +        # Alternately:​ if !@e_pat.nil?​ && (md = @e_pat.match(@buffer))
 +        if !@e_pat.nil?​ && @buffer =~ @e_pat then
 +          # Alternately (if using the above) @result = [@buffer, *md.to_a[1 .. -1]]
 +          @result = [@buffer,​$1,​$2,​$3,​$4,​$5,​$6,​$7,​$8,​$9]
 +          @buffer = $'
 +          log( "​Buffer matched#​{@e_pat.source}"​)
 +          @e_pat = nil
 +          @bufferResource.signal
 +        end
 +      end
 +    end
 +  rescue SystemCallError,​ EOFError => details
 +    log( details)
 +    log( details.backtrace.join("​\n"​))
 +    @mutex.synchronize do
 +      @bufferResource.signal
 +    end
 +  rescue RuntimeError => details
 +    raise details if details.to_s !~ /​Child_changed/​
 +  ensure
 +    @log.close
 +  end
 +  ​
 +  def expect(pat,​time_out=5)
 +    @result = nil
 +
 +    @mutex.synchronize do
 +      case pat
 +      when String
 +        @e_pat = Regexp.new(Regexp.quote(pat))
 +      when Regexp
 +        @e_pat = pat
 +      end
 +      log( @e_pat.source)
 +      ​
 +      if @buffer =~ @e_pat then
 +        @result = [@buffer,​$1,​$2,​$3,​$4,​$5,​$6,​$7,​$8,​$9]
 +        @buffer = $'
 +        log( "​Existing buffer matched#​{@e_pat.source}"​)
 +        @e_pat = nil
 +        return @result
 +      end
 +      timeout( time_out) do
 +        @bufferResource.wait( @mutex)
 +        raise EOFError if @result.nil?​
 +      end
 +    end
 +    return @result
 +  end
 +
 +  def puts(str)
 +    log( str)
 +    @outf.puts str
 +  end 
 +
 +end
 +
 +
 +if (__FILE__ == $0)
 +  #
 +  # Here is a silly example....
 +  #
 +  $log = File.open( "​hello.log",​ "​w"​)
 +  $me = RExpect.new( STDIN, STDOUT, Process.ppid,​ "​stdio"​)
 +
 +  Thread.new do
 +    # Note this _must_ run in its own thread! ​
 +    # Spawn creates its own thread to do this...
 +    $me.inputData
 +  end
 +
 +  def try( pat)
 +    $log.puts "​Seeking:#​{pat.source}"​
 +    result = $me.expect( pat, 6)
 +    $log.puts "​Found:#​{result}"​
 +    return result
 +  end
 +
 +  def say( s)
 +    $log.puts "Say: #{s}"
 +    $me.puts s
 +  end
 +
 +  say "Hello world"
 +  say "​Expecting me?"
 +  try( /You again!/)
 +  say "Ah well, since you're here, whats your name then?"
 +  result = try( /​[\n\r]([^\n\r]+)/​)
 +  if result.nil? then
 +    say "Cat got your tongue?"​
 +  else 
 +    if result[1] =~ /John/ then
 +      say "Not you again"
 +    else
 +      say "​Please to meet you"
 +    end
 +  end
 +  try( /Go away!/)
 +  say "Will do"
 +  $log.puts "​Exiting"​
 +  $log.close
 +end
 +</​code>​
 +----
 +[[start|Back to Ruby]]
  
rubyexpect.txt ยท Last modified: 2014/10/26 01:52 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0