1$expect_verbose = false
2
3# Expect library adds the IO instance method #expect, which does similar act to
4# tcl's expect extension.
5#
6# In order to use this method, you must require expect:
7#
8#   require 'expect'
9#
10# Please see #expect for usage.
11class IO
12  # call-seq:
13  #   IO#expect(pattern,timeout=9999999)                  ->  Array
14  #   IO#expect(pattern,timeout=9999999) { |result| ... } ->  nil
15  #
16  # Reads from the IO until the given +pattern+ matches or the +timeout+ is over.
17  #
18  # It returns an array with the read buffer, followed by the matches.
19  # If a block is given, the result is yielded to the block and returns nil.
20  #
21  # When called without a block, it waits until the input that matches the
22  # given +pattern+ is obtained from the IO or the time specified as the
23  # timeout passes. An array is returned when the pattern is obtained from the
24  # IO. The first element of the array is the entire string obtained from the
25  # IO until the pattern matches, followed by elements indicating which the
26  # pattern which matched to the anchor in the regular expression.
27  #
28  # The optional timeout parameter defines, in seconds, the total time to wait
29  # for the pattern.  If the timeout expires or eof is found, nil is returned
30  # or yielded.  However, the buffer in a timeout session is kept for the next
31  # expect call.  The default timeout is 9999999 seconds.
32  def expect(pat,timeout=9999999)
33    buf = ''
34    case pat
35    when String
36      e_pat = Regexp.new(Regexp.quote(pat))
37    when Regexp
38      e_pat = pat
39    else
40      raise TypeError, "unsupported pattern class: #{pat.class}"
41    end
42    @unusedBuf ||= ''
43    while true
44      if not @unusedBuf.empty?
45        c = @unusedBuf.slice!(0).chr
46      elsif !IO.select([self],nil,nil,timeout) or eof? then
47        result = nil
48        @unusedBuf = buf
49        break
50      else
51        c = getc.chr
52      end
53      buf << c
54      if $expect_verbose
55        STDOUT.print c
56        STDOUT.flush
57      end
58      if mat=e_pat.match(buf) then
59        result = [buf,*mat.to_a[1..-1]]
60        break
61      end
62    end
63    if block_given? then
64      yield result
65    else
66      return result
67    end
68    nil
69  end
70end
71
72