parley 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ # gem "shoulda", ">= 0"
10
+ gem "rdoc", "~> 3.12"
11
+ # gem "bundler", "~> 1.0.0"
12
+ gem "bundler"
13
+ gem "jeweler", "~> 1.8.4"
14
+ # gem "rcov", ">= 0"
15
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Ben Stoltz
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ parley
2
+ ======
3
+
4
+ An Expect-like gem for Ruby
5
+
6
+ Parley is an implementation of an expect-like API. It is designed to
7
+ help port away from Perl Expect based applications. The name "expect"
8
+ is already well established in ruby. Those of you who have wrestled
9
+ with the interactive, text-mode, APIs of the world will appreciate the
10
+ meaning of the word:
11
+
12
+ From http://www.thefreedictionary.com/parley "A discussion or conference, especially one between enemies over terms of truce or other matters."
13
+
14
+ See http://www.nist.gov/el/msid/expect.cfm for references to the original Expect language based on Tcl.
15
+
16
+ See http://search.cpan.org/~rgiersig/Expect-1.21/Expect.pod for information on Expect.pm
17
+
18
+ Known Issues
19
+ ------------
20
+
21
+ * need to generatate adequte documentation. See test/test_parley.rb for now
22
+ * :restart_timeout from IO::parley() doesn't have the desired effect, it isn't re-establishing the timeout.
23
+
24
+ Contributing to parley
25
+ ----------------------
26
+
27
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
28
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
29
+ * Fork the project.
30
+ * Start a feature/bugfix branch.
31
+ * Commit and push until you are happy with your contribution.
32
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
33
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
34
+
35
+ Copyright
36
+ ---------
37
+
38
+ Copyright (c) 2013 Ben Stoltz.
39
+ See LICENSE.txt for further details.
data/README.rdoc ADDED
@@ -0,0 +1,35 @@
1
+ = parley
2
+
3
+ An Expect-like gem for Ruby
4
+
5
+ Parley is an implementation of an expect-like API. It is designed to
6
+ help port away from Perl Expect based applications. The name "expect"
7
+ is already well established in ruby. Those of you who have wrestled
8
+ with the interactive, text-mode, APIs of the world will appreciate the
9
+ meaning of the word:
10
+
11
+ From http://www.thefreedictionary.com/parley "A discussion or conference, especially one between enemies over terms of truce or other matters."
12
+
13
+ See http://www.nist.gov/el/msid/expect.cfm for references to the original Expect language based on Tcl.
14
+
15
+ See http://search.cpan.org/~rgiersig/Expect-1.21/Expect.pod for information on Expect.pm
16
+
17
+ == Known Issues
18
+
19
+ * need to generatate adequte documentation. See test/test_parley.rb for now
20
+ * :restart_timeout from IO::parley() doesn't have the desired effect
21
+
22
+ == Contributing to parley
23
+
24
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
25
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
26
+ * Fork the project.
27
+ * Start a feature/bugfix branch.
28
+ * Commit and push until you are happy with your contribution.
29
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
30
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
31
+
32
+ == Copyright
33
+
34
+ Copyright (c) 2013 Ben Stoltz.
35
+ See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "parley"
18
+ gem.homepage = "http://github.com/lzrd/parley"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{An expect-like gem, modeled after Perl's Expect.pm}
21
+ gem.description = %Q{An expect-like gem, modeled after Perl's Expect.pm}
22
+ gem.email = "stoltz@lzrd.com"
23
+ gem.authors = ["Ben Stoltz"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ #require 'rcov/rcovtask'
36
+ #Rcov::RcovTask.new do |test|
37
+ # test.libs << 'test'
38
+ # test.pattern = 'test/**/test_*.rb'
39
+ # test.verbose = true
40
+ # test.rcov_opts << '--exclude "gems/*"'
41
+ #end
42
+
43
+ task :default => :test
44
+
45
+ require 'rdoc/task'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "parley #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/parley.rb ADDED
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # = parley.rb - An expect library for Ruby modled after Perl's Expect.pm
4
+ #
5
+ require 'pty'
6
+
7
+ # TODO: line oriented reading option
8
+ # Greediness control
9
+ module Parley
10
+ # VERSION = '0.1.0'
11
+
12
+ # Initialize() is usually not called or doesn't call super(), so
13
+ # do implicit instance variable initialization
14
+ def unused_buf= (v)
15
+ @unused_buf = v
16
+ end
17
+
18
+ def unused_buf
19
+ @unused_buf = nil unless defined? @unused_buf
20
+ @unused_buf
21
+ end
22
+
23
+ def parley_verbose= (v)
24
+ @parley_verbose = (v ? true : false)
25
+ end
26
+
27
+ def parley_verbose
28
+ @parley_verbose = false unless defined? @parley_verbose
29
+ @parley_verbose
30
+ end
31
+
32
+ def parley_maxread= (v)
33
+ @parley_maxread = (v > 0) ? v : 1
34
+ end
35
+
36
+ def parley_maxread
37
+ @parley_maxread = 1 unless defined? @parley_maxread
38
+ @parley_maxread
39
+ end
40
+
41
+ def parley (t_out, *actions)
42
+ # t_out = nil; # wait forever for next data
43
+ # t_out = 0; # timeout immediately if no data available
44
+ # t_out > 0; # timeout after t_out seconds
45
+ # t_out < 0; # deadline is in the past, same as t_out = 0
46
+ STDOUT.print "\n------\nparley t_out=#{t_out}\n" if parley_verbose
47
+ if (t_out == nil)
48
+ deadline = nil
49
+ else
50
+ deadline = Time.now + t_out
51
+ end
52
+ buf = ''
53
+ unused_buf = '' if not unused_buf
54
+
55
+ loop_count = 0
56
+
57
+ # STDOUT.puts "class=#{self.class}"
58
+
59
+ # Compatible hack. There are changes coming w.r.t. respond_to? for
60
+ # protected methods. Just do a simple poll, and see if it works.
61
+ begin
62
+ result = IO.select([self], [], [], 0)
63
+ has_select = true;
64
+ rescue Exception
65
+ has_select = false;
66
+ # STDOUT.puts "Exception: #{Exception}"
67
+ end
68
+ # STDOUT.puts "has_select=#{has_select}"
69
+
70
+ begin
71
+ loop_count = loop_count + 1
72
+ # If it is possible to wait for data, then wait for data
73
+ t = (deadline ? (deadline - Time.now) : nil)
74
+ t = (t.nil? || t >= 0) ? t : 0
75
+ if unused_buf.length == 0 && has_select && !IO.select([self], nil, nil, t)
76
+ # Timeout condition returns nil
77
+ STDOUT.print "TIMEOUT=\"#{buf}\"\n" if parley_verbose
78
+ timeout_handled = nil
79
+ result = nil
80
+ result = actions.each do|act|
81
+ case act[0]
82
+ when :timeout
83
+ timeout_handled = true
84
+ if act[1].respond_to?(:call)
85
+ /.*/.match(buf) # get the buffer contents into a Regexp.last_match
86
+ result = act[1].call(Regexp.last_match)
87
+ else
88
+ result = act[1]
89
+ end
90
+ break result
91
+ end
92
+ end
93
+ if (!timeout_handled)
94
+ # XXX need to prepend buf to @unusedbuf
95
+ unused_buf = buf # save data for next time
96
+ raise "timeout" # XXX use TimeoutException
97
+ end
98
+ STDOUT.print "TIMEOUT RESULT=\"#{result}\"\n" if parley_verbose
99
+ return result unless result == :reset_timeout
100
+ else
101
+
102
+ # We've waited, if that was possible, check for data present
103
+ if unused_buf.length == 0 && eof?
104
+ STDOUT.print "EOF Buffer=\"#{buf}\"\n" if parley_verbose
105
+ result = nil
106
+ eof_handled = false
107
+ actions.each do |act|
108
+ case act[0]
109
+ when :eof
110
+ eof_handled = true
111
+ if act[1].respond_to?(:call)
112
+ /.*/m.match(buf) # Game end, match everything remaining
113
+ result = act[1].call(Regexp.last_match)
114
+ else
115
+ result = act[1]
116
+ end
117
+ break result
118
+ end
119
+ end
120
+ if not eof_handled
121
+ # XXX need to prepend buf to @unusedbuf
122
+ unused_buf = buf # save data for next time
123
+ raise :eof if not eof_handled
124
+ end
125
+ return result
126
+ end
127
+
128
+ # Greedy read:
129
+ # buf << self.read_nonblock(maxlen)
130
+ if (unused_buf.length > 0)
131
+ c = unused_buf.slice!(0..parley_maxread)
132
+ elsif (parley_maxread > 1 && self.respond_to?(:read_nonblock))
133
+ c = read_nonblock(parley_maxread)
134
+ else
135
+ c = getc.chr
136
+ end
137
+ buf << c
138
+
139
+ # Look for matches to the current buffer content
140
+ result = :continue
141
+ matched = false
142
+ result = actions.each_with_index do |act,i|
143
+ # STDOUT.print "buf=\"#{buf}\"\tact=#{act[0]}\n" if parley_verbose
144
+ m = case act[0]
145
+ when Regexp
146
+ act[0].match(buf) and Regexp.last_match
147
+ when String
148
+ act[0] = Regexp.new(act[0]) # caching the regexp conversion, XXX any problem?
149
+ act[0].match(buf) and Regexp.last_match
150
+ else
151
+ nil
152
+ end
153
+ if m
154
+ STDOUT.print "match[#{i}]=\"#{buf}\"\n" if parley_verbose
155
+ matched = true
156
+ if act[1]
157
+ if act[1].respond_to?(:call)
158
+ result = act[1].call(m)
159
+ else
160
+ result = act[1] # no block, just a result
161
+ end
162
+ else
163
+ result = m # no action supplied, return last match
164
+ end
165
+ buf = '' # consume the buffer (XXX only the part that matched?)
166
+ # XXX if the regex had post context, don't consume that.
167
+ STDOUT.puts "result=#{result}" if parley_verbose
168
+ break result
169
+ end
170
+ result
171
+ end
172
+ end
173
+
174
+ if matched == true
175
+ result = case result
176
+ when :continue
177
+ :continue
178
+ when nil # explicit end
179
+ break nil
180
+ when :reset_timeout
181
+ deadline = Time.now + t_out # XXX vs deadline in lambda closure?
182
+ STDOUT.puts "deadline=#{deadline.to_s}, continue" if parley_verbose
183
+ :continue
184
+ else # return with result
185
+ break result
186
+ end
187
+ else
188
+ result = :continue
189
+ end
190
+ end while result == :continue
191
+ end
192
+ end
193
+
194
+ class IO
195
+ include Parley
196
+ end
data/parley.gemspec ADDED
@@ -0,0 +1,57 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "parley"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ben Stoltz"]
12
+ s.date = "2013-02-15"
13
+ s.description = "An expect-like gem, modeled after Perl's Expect.pm"
14
+ s.email = "stoltz@lzrd.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "Gemfile",
23
+ "LICENSE.txt",
24
+ "README.md",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "lib/parley.rb",
29
+ "parley.gemspec",
30
+ "test/helper.rb",
31
+ "test/test_parley.rb"
32
+ ]
33
+ s.homepage = "http://github.com/lzrd/parley"
34
+ s.licenses = ["MIT"]
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = "1.8.24"
37
+ s.summary = "An expect-like gem, modeled after Perl's Expect.pm"
38
+
39
+ if s.respond_to? :specification_version then
40
+ s.specification_version = 3
41
+
42
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
43
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
44
+ s.add_development_dependency(%q<bundler>, [">= 0"])
45
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
46
+ else
47
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
48
+ s.add_dependency(%q<bundler>, [">= 0"])
49
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
50
+ end
51
+ else
52
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
53
+ s.add_dependency(%q<bundler>, [">= 0"])
54
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
55
+ end
56
+ end
57
+
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ # require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'parley'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,213 @@
1
+ require 'helper'
2
+ require "test/unit"
3
+ require 'parley'
4
+ require 'stringio'
5
+
6
+ #class TestParley < Test::Unit::TestCase
7
+ # should "probably rename this file and start testing for real" do
8
+ # flunk "hey buddy, you should probably rename this file and start testing for real"
9
+ # end
10
+ #end
11
+
12
+ class StringIO
13
+ include Parley
14
+ end
15
+
16
+ class TestIO < Test::Unit::TestCase
17
+
18
+ def setup
19
+ @text = "red apple\nbright white\nthree dogs\nblue sky\nafter glow\n"
20
+ @test_verbose = false # Set to true if you want to see conversations
21
+ end
22
+
23
+ def teardown
24
+ # no teardown required
25
+ end
26
+
27
+ def test_timeout
28
+ read, write, pid = PTY.spawn('/bin/sleep 20')
29
+ result = read.parley(5, [:timeout, :timeout])
30
+ assert(result == :timeout, "** ERROR result = #{result}")
31
+ end
32
+
33
+ def test_eof_constant
34
+ io = File.new("/dev/null", "r")
35
+ result = io.parley(20, [:eof, :eof])
36
+ assert(result == :eof, "** ERROR result = #{result}")
37
+ end
38
+
39
+ def test_eof_call
40
+ io = File.new("/dev/null", "r")
41
+ found_eof = false
42
+ result = io.parley(20, [:eof, lambda {|m| found_eof = true; nil}])
43
+ assert(result.nil?, "** ERROR result = <<#{result}>>")
44
+ assert(found_eof == true, "** ERROR found_eof = #{found_eof}")
45
+ end
46
+
47
+ def test_strings
48
+ count = 0
49
+ io = StringIO.open(@text, "r")
50
+ result = io.parley(0,
51
+ ['red apple', lambda{|m| count += 1; :continue }],
52
+ ['three dogs', lambda{|m| count += 1; :continue }],
53
+ [:eof, lambda{|m| count}] # XXX need to verify unused portion of buffer
54
+ )
55
+ assert(count == 2, "** ERROR count = #{count}")
56
+ assert(result == 2, "** ERROR result = #{result.inspect}")
57
+ end
58
+
59
+ def test_strings_maxread
60
+ count = 0
61
+ io = StringIO.open(@text, "r")
62
+ io.parley_maxread = 10
63
+ result = io.parley(0,
64
+ ['red apple', lambda{|m| count += 1; :continue }],
65
+ ['three dogs', lambda{|m| count += 1; :continue }],
66
+ [:eof, lambda{|m| count}] # XXX need to verify unused portion of buffer
67
+ )
68
+ assert(count == 2, "** ERROR count = #{count}")
69
+ assert(result == 2, "** ERROR result = #{result.inspect}")
70
+ end
71
+
72
+ def test_patterns
73
+ colors = ['red\s*?(.*)$', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
74
+ count = 0
75
+ io = StringIO.open(@text, "r")
76
+ result = io.parley(0,
77
+ [Regexp.new(colors.join('|')), lambda{|m| count += 1; :continue}],
78
+ [:eof, lambda{|m| count}] # XXX need to verify unused portion of buffer
79
+ )
80
+ assert(count == 2, "** ERROR count = #{count}")
81
+ assert(result == 2, "** ERROR result = #{result.inspect}")
82
+ end
83
+
84
+ #
85
+ # Test the effect of reading more characters in at a time.
86
+ # This means you'll have to be more careful of your patterns so that you
87
+ # don't match more than you really want to
88
+ #
89
+ def test_patterns_maxread
90
+ colors = ['red\s*?(.*)$', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
91
+ count = 0
92
+ io = StringIO.open(@text, "r")
93
+ io.parley_maxread = 64 # Note: Up to 64 characters read at a time, so only 1 match
94
+ result = io.parley(0,
95
+ [Regexp.new(colors.join('|')), lambda{|m| count += 1; :continue}],
96
+ [:eof, lambda{|m| count}] # XXX need to verify unused portion of buffer
97
+ )
98
+ assert(count == 1, "** ERROR count = #{count}")
99
+ assert(result == 1, "** ERROR result = #{result.inspect}")
100
+ end
101
+
102
+ #
103
+ # Test the effect of reading more characters in at a time.
104
+ # This means you'll have to be more careful of your patterns so that you
105
+ # don't match more than you really want to
106
+ # XXX doesn't work as expected: "\Z matches end of string or just before a \n"
107
+ # ? indicates lazy match as opposed to greedy
108
+ #
109
+ def test_patterns_careful_maxread
110
+ re = /
111
+ red.*\n | # "red" on a single line
112
+ orange.*\n |
113
+ yellow.*\n |
114
+ green.*\n |
115
+ blue.*\n |
116
+ indigo.*\n |
117
+ violet.*\n
118
+ /x
119
+ count = 0
120
+ io = StringIO.open(@text + @text + @text, "r")
121
+ io.parley_maxread = 64 # Note: Up to 64 characters read at a time, so only 1 match
122
+ buf_end = nil
123
+ io.parley_verbose = true if @test_verbose
124
+ result = io.parley(0,
125
+ [re, lambda{|m|
126
+ count = count + 1;
127
+ # puts "COUNT=#{count} MATCH=\"#{m.pre_match}/#{m[0]}/#{m.post_match}\""
128
+ :continue}
129
+ ],
130
+ [:eof, lambda{|m|
131
+ buf_end = m[0];
132
+ count
133
+ }
134
+ ] # XXX need to verify unused portion of buffer
135
+ )
136
+ assert(count == 3, "** ERROR count = #{count}")
137
+ assert(result == 3, "** ERROR result = #{result.inspect}")
138
+ # assert(buf_end.length > 0, "** Error buf_end.length=#{buf_end.length}, buf=#{buf_end}")
139
+ end
140
+
141
+ def test_empty_string
142
+ colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
143
+ count = 0
144
+ io = StringIO.open("", "r")
145
+ result = io.parley(0,
146
+ [Regexp.new(colors.join('|')), lambda{|m| count += 1; :continue}],
147
+ [:eof, lambda{|m| count}])
148
+ assert(count == 0, "** ERROR count = #{result.inspect}")
149
+ assert(result == 0, "** ERROR result = #{result.inspect}")
150
+ end
151
+
152
+ def test_ruby_current_version
153
+ fnames = []
154
+ ftp_to = 20
155
+ PTY.spawn("ftp ftp.ruby-lang.org") do |r_f, w_f, pid|
156
+ r_f.parley_verbose = true if @test_verbose
157
+ hostname = ENV['HOSTNAME']
158
+ hostname ||= ""
159
+ if !ENV['USER'].nil?
160
+ username = ENV['USER']
161
+ elsif !ENV['LOGNAME'].nil?
162
+ username = ENV['LOGNAME']
163
+ else
164
+ username = 'guest'
165
+ end
166
+
167
+ # Name (ftp.ruby-lang.org:yourNameHere): ftp
168
+ # ftp\n
169
+ # Password:
170
+ # #{username}\n
171
+ # ftp>
172
+ # cd pub/ruby\n
173
+ r_f.parley(ftp_to,
174
+ [/^Name.*:/, lambda {|m| w_f.puts("ftp"); :continue }],
175
+ [/ssword:/, lambda {|m| w_f.puts("#{username}@#{hostname}"); :continue }],
176
+ [/> /, lambda {|m| w_f.puts("cd pub/ruby"); nil }]
177
+ )
178
+
179
+ # >
180
+ # dir\n
181
+ r_f.parley(ftp_to, ["> ", lambda {|m| w_f.print "dir\r"}])
182
+
183
+ # lrwxrwxrwx 1 1014 100 27 Feb 18 12:52 ruby-1.8.7-p334.tar.bz2 -> 1.8/ruby-1.8.7-p334.tar.bz2
184
+ r_f.parley(ftp_to,
185
+ [/^ftp> /, lambda {|m|
186
+ for x in m.pre_match.split("\n")
187
+ if x =~ /(ruby.*?\.tar\.gz)/ then
188
+ fnames.push $1
189
+ end
190
+ end
191
+ begin
192
+ w_f.print "quit\n"
193
+ rescue
194
+ end
195
+ :nil
196
+ }],
197
+ [:eof, nil])
198
+ end
199
+ puts "The latest ruby interpreter is #{fnames.sort.pop}"
200
+ end
201
+
202
+ def test_reset_timeout
203
+ read, write, pid = PTY.spawn(
204
+ # XXX fire off a ruby program, not bash, to get the test behavoir we want
205
+ '/bin/bash -x -c "for x in wait done too_late; do sleep 3; echo $x; done"')
206
+ read.parley_verbose = true if @test_verbose
207
+ result = read.parley(5,
208
+ [/wait/, :reset_timeout],
209
+ [/done/, :pass ],
210
+ [:timeout, :timeout])
211
+ assert(result == :pass, "** ERROR result = #{result}")
212
+ end
213
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: parley
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ben Stoltz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rdoc
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.12'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.12'
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: jeweler
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.8.4
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.8.4
62
+ description: An expect-like gem, modeled after Perl's Expect.pm
63
+ email: stoltz@lzrd.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files:
67
+ - LICENSE.txt
68
+ - README.md
69
+ - README.rdoc
70
+ files:
71
+ - .document
72
+ - Gemfile
73
+ - LICENSE.txt
74
+ - README.md
75
+ - README.rdoc
76
+ - Rakefile
77
+ - VERSION
78
+ - lib/parley.rb
79
+ - parley.gemspec
80
+ - test/helper.rb
81
+ - test/test_parley.rb
82
+ homepage: http://github.com/lzrd/parley
83
+ licenses:
84
+ - MIT
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ segments:
96
+ - 0
97
+ hash: -1353724432284273081
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 1.8.24
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: An expect-like gem, modeled after Perl's Expect.pm
110
+ test_files: []