expectr 1.1.1 → 2.0.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/lib/expectr.rb CHANGED
@@ -1,11 +1,15 @@
1
- require 'pty'
2
1
  require 'timeout'
3
2
  require 'thread'
4
3
  require 'io/console'
5
4
 
6
5
  require 'expectr/error'
6
+ require 'expectr/errstr'
7
7
  require 'expectr/version'
8
8
 
9
+ require 'expectr/child'
10
+ require 'expectr/adopt'
11
+ require 'expectr/lambda'
12
+
9
13
  # Public: Expectr is an API to the functionality of Expect (see
10
14
  # http://expect.nist.gov) implemented in ruby.
11
15
  #
@@ -34,7 +38,6 @@ class Expectr
34
38
  DEFAULT_FLUSH_BUFFER = true
35
39
  DEFAULT_BUFFER_SIZE = 8192
36
40
  DEFAULT_CONSTRAIN = false
37
- DEFAULT_FORCE_MATCH = false
38
41
 
39
42
  # Public: Gets/sets the number of seconds a call to Expectr#expect may last
40
43
  attr_accessor :timeout
@@ -44,8 +47,6 @@ class Expectr
44
47
  attr_accessor :buffer_size
45
48
  # Public: Gets/sets whether to constrain the buffer to the buffer size
46
49
  attr_accessor :constrain
47
- # Public: Whether to always attempt to match once on calls to Expectr#expect.
48
- attr_accessor :force_match
49
50
  # Public: Returns the PID of the running process
50
51
  attr_reader :pid
51
52
  # Public: Returns the active buffer to match against
@@ -56,7 +57,7 @@ class Expectr
56
57
  # Public: Initialize a new Expectr object.
57
58
  # Spawns a sub-process and attaches to STDIN and STDOUT for the new process.
58
59
  #
59
- # cmd - A String or File referencing the application to launch
60
+ # cmd - A String or File referencing the application to launch (default: '')
60
61
  # args - A Hash used to specify options for the new object (default: {}):
61
62
  # :timeout - Number of seconds that a call to Expectr#expect has
62
63
  # to complete (default: 30)
@@ -68,39 +69,31 @@ class Expectr
68
69
  # (default: 8192)
69
70
  # :constrain - Whether to constrain the internal buffer from the
70
71
  # sub-process to :buffer_size (default: false)
71
- # :force_match - Whether to always attempt to match against the
72
- # internal buffer on a call to Expectr#expect. This
73
- # is relevant following a failed call to
74
- # Expectr#expect, which will leave the update status
75
- # set to false, preventing further matches until more
76
- # output is generated otherwise. (default: false)
77
- def initialize(cmd, args={})
78
- cmd = cmd.path if cmd.kind_of?(File)
79
- raise ArgumentError, "String or File expected" unless cmd.kind_of?(String)
80
-
72
+ # :interface - Interface Object to use when instantiating the new
73
+ # Expectr object. (default: Child)
74
+ def initialize(cmd = '', args = {})
75
+ setup_instance
81
76
  parse_options(args)
82
- @buffer = ''
83
- @discard = ''
84
- @out_mutex = Mutex.new
85
- @out_update = false
86
- @interact = false
87
-
88
- @stdout,@stdin,@pid = PTY.spawn(cmd)
89
- @stdout.winsize = $stdout.winsize if $stdout.tty?
90
77
 
91
- Thread.new do
92
- process_output
78
+ case args[:interface]
79
+ when :lambda
80
+ interface = call_lambda_interface(args)
81
+ when :adopt
82
+ interface = call_adopt_interface(args)
83
+ else
84
+ interface = call_child_interface(cmd)
93
85
  end
94
86
 
95
- Thread.new do
96
- Process.wait @pid
97
- @pid = 0
87
+ interface.init_instance.each do |spec|
88
+ ->(name, func) { define_singleton_method(name, func.call) }.call(*spec)
98
89
  end
90
+
91
+ Thread.new { output_loop }
99
92
  end
100
93
 
101
94
  # Public: Relinquish control of the running process to the controlling
102
- # terminal, acting as a pass-through for the life of the process. SIGINT
103
- # will be caught and sent to the application as "\C-c".
95
+ # terminal, acting as a pass-through for the life of the process (or until
96
+ # the leave! method is called).
104
97
  #
105
98
  # args - A Hash used to specify options to be used for interaction (default:
106
99
  # {}):
@@ -110,26 +103,12 @@ class Expectr
110
103
  #
111
104
  # Returns the interaction Thread
112
105
  def interact!(args = {})
113
- raise ProcessError if @interact
114
-
115
- blocking = args[:blocking] || false
116
- @flush_buffer = args[:flush_buffer].nil? ? true : args[:flush_buffer]
117
-
118
- interact = Thread.new do
119
- env = prepare_interact_environment
120
- input = ''
121
-
122
- while @pid > 0 && @interact
123
- if select([$stdin], nil, nil, 1)
124
- c = $stdin.getc.chr
125
- send c unless c.nil?
126
- end
127
- end
128
-
129
- restore_environment(env)
106
+ if @interact
107
+ raise(ProcessError, Errstr::ALREADY_INTERACT)
130
108
  end
131
109
 
132
- blocking ? interact.join : interact
110
+ @flush_buffer = args[:flush_buffer].nil? ? true : args[:flush_buffer]
111
+ args[:blocking] ? interact_thread.join : interact_thread
133
112
  end
134
113
 
135
114
  # Public: Report whether or not current Expectr object is in interact mode
@@ -146,32 +125,6 @@ class Expectr
146
125
  @interact=false
147
126
  end
148
127
 
149
- # Public: Kill the running process, raise ProcessError if the pid isn't > 1
150
- #
151
- # signal - Symbol, String, or Fixnum representing the signal to send to the
152
- # running process. (default: :TERM)
153
- #
154
- # Returns true if the process was successfully killed, false otherwise
155
- def kill!(signal=:TERM)
156
- raise ProcessError unless @pid > 0
157
- (Process::kill(signal.to_sym, @pid) == 1)
158
- end
159
-
160
- # Public: Send input to the active process
161
- #
162
- # str - String to be sent to the active process
163
- #
164
- # Returns nothing.
165
- # Raises Expectr::ProcessError if the process isn't running
166
- def send(str)
167
- begin
168
- @stdin.syswrite str
169
- rescue Errno::EIO #Application went away.
170
- @pid = 0
171
- end
172
- raise Expectr::ProcessError unless @pid > 0
173
- end
174
-
175
128
  # Public: Wraps Expectr#send, appending a newline to the end of the string
176
129
  #
177
130
  # str - String to be sent to the active process (default: '')
@@ -184,7 +137,10 @@ class Expectr
184
137
  # Public: Begin a countdown and search for a given String or Regexp in the
185
138
  # output buffer.
186
139
  #
187
- # pattern - String or Regexp representing what we want to find
140
+ # pattern - Object String or Regexp representing pattern for which to
141
+ # search, or a Hash containing pattern -> Proc mappings to be
142
+ # used in cases where multiple potential patterns should map
143
+ # to distinct actions.
188
144
  # recoverable - Denotes whether failing to match the pattern should cause the
189
145
  # method to raise an exception (default: false)
190
146
  #
@@ -202,34 +158,61 @@ class Expectr
202
158
  #
203
159
  # exp.expect(/not there/, true)
204
160
  # # => nil
161
+ #
162
+ # hash = { "First possibility" => -> { puts "option a" },
163
+ # "Second possibility" => -> { puts "option b" },
164
+ # default: => -> { puts "called on timeout" } }
165
+ # exp.expect(hash)
205
166
  #
206
167
  # Returns a MatchData object once a match is found if no block is given
207
168
  # Yields the MatchData object representing the match
208
169
  # Raises TypeError if something other than a String or Regexp is given
209
170
  # Raises Timeout::Error if a match isn't found in time, unless recoverable
210
171
  def expect(pattern, recoverable = false)
172
+ return expect_procmap(pattern) if pattern.is_a?(Hash)
173
+
211
174
  match = nil
212
- @out_update ||= @force_match
213
- pattern = Regexp.new(Regexp.quote(pattern)) if pattern.kind_of?(String)
214
- unless pattern.kind_of?(Regexp)
215
- raise TypeError, "Pattern class should be String or Regexp"
175
+ pattern = Regexp.new(Regexp.quote(pattern)) if pattern.is_a?(String)
176
+ unless pattern.is_a?(Regexp)
177
+ raise(TypeError, Errstr::EXPECT_WRONG_TYPE)
216
178
  end
217
179
 
218
- begin
219
- Timeout::timeout(@timeout) do
220
- match = check_match(pattern)
221
- end
180
+ match = watch_match(pattern, recoverable)
181
+ block_given? ? yield(match) : match
182
+ end
222
183
 
223
- @out_mutex.synchronize do
224
- @discard = @buffer[0..match.begin(0)-1]
225
- @buffer = @buffer[match.end(0)..-1]
226
- @out_update = true
184
+ # Public: Begin a countdown and search for any of multiple possible patterns,
185
+ # performing designated actions upon success/failure.
186
+ #
187
+ # pattern_map - Hash containing mappings between Strings or Regexps and
188
+ # procedure objects. Additionally, an optional action,
189
+ # designated by :default or :timeout may be provided to specify
190
+ # an action to take upon failure.
191
+ #
192
+ # Examples
193
+ #
194
+ # exp.expect_procmap({
195
+ # "option 1" => -> { puts "action 1" },
196
+ # /option 2/ => -> { puts "action 2" },
197
+ # :default => -> { puts "default" }
198
+ # })
199
+ #
200
+ # Calls the procedure associated with the pattern provided.
201
+ def expect_procmap(pattern_map)
202
+ pattern_map, pattern, recoverable = process_procmap(pattern_map)
203
+ match = nil
204
+
205
+ match = watch_match(pattern, recoverable)
206
+
207
+ pattern_map.each do |s,p|
208
+ if s.is_a?(Regexp)
209
+ return p.call if s.match(match.to_s)
227
210
  end
228
- rescue Timeout::Error => details
229
- raise details unless recoverable
230
211
  end
231
212
 
232
- block_given? ? yield(match) : match
213
+ pattern_map[:default].call unless pattern_map[:default].nil?
214
+ pattern_map[:timeout].call unless pattern_map[:timeout].nil?
215
+ nil
233
216
  end
234
217
 
235
218
  # Public: Clear output buffer
@@ -237,17 +220,11 @@ class Expectr
237
220
  # Returns nothing.
238
221
  def clear_buffer!
239
222
  @out_mutex.synchronize do
240
- @buffer = ''
241
- @out_update = false
223
+ @buffer.clear
242
224
  end
243
225
  end
244
226
 
245
- # Public: Return the child's window size.
246
- #
247
- # Returns a two-element array (same as IO#winsize).
248
- def winsize
249
- @stdout.winsize
250
- end
227
+ private
251
228
 
252
229
  # Internal: Print buffer to $stdout if @flush_buffer is true
253
230
  #
@@ -255,7 +232,7 @@ class Expectr
255
232
  #
256
233
  # Returns nothing.
257
234
  def print_buffer(buf)
258
- print buf if @flush_buffer
235
+ $stdout.print buf if @flush_buffer
259
236
  $stdout.flush unless $stdout.sync
260
237
  end
261
238
 
@@ -270,8 +247,6 @@ class Expectr
270
247
  buf.force_encoding('ISO-8859-1').encode('UTF-8', 'UTF-8', replace: nil)
271
248
  end
272
249
 
273
- private
274
-
275
250
  # Internal: Determine values of instance options and set instance variables
276
251
  # appropriately, allowing for default values where nothing is passed.
277
252
  #
@@ -285,109 +260,168 @@ class Expectr
285
260
  # maximum size of the internal buffer as well.
286
261
  # :constrain - Whether to constrain the internal buffer from the
287
262
  # sub-process to :buffer_size.
288
- # :force_match - Whether to always attempt to match against the
289
- # internal buffer on a call to Expectr#expect. This
290
- # is relevant following a failed call to
291
- # Expectr#expect, which will leave the update status
292
- # set to false, preventing further matches until more
293
- # output is generated otherwise.
294
263
  #
295
264
  # Returns nothing.
296
265
  def parse_options(args)
297
266
  @timeout = args[:timeout] || DEFAULT_TIMEOUT
298
267
  @buffer_size = args[:buffer_size] || DEFAULT_BUFFER_SIZE
299
268
  @constrain = args[:constrain] || DEFAULT_CONSTRAIN
300
- @force_match = args[:force_match] || DEFAULT_FORCE_MATCH
301
269
  @flush_buffer = args[:flush_buffer]
302
270
  @flush_buffer = DEFAULT_FLUSH_BUFFER if @flush_buffer.nil?
303
271
  end
304
272
 
305
- # Internal: Read from the process's stdout. Force UTF-8 encoding, append to
306
- # the internal buffer, and print to $stdout if appropriate.
273
+ # Internal: Initialize instance variables to their default values.
274
+ #
275
+ # Returns nothing.
276
+ def setup_instance
277
+ @buffer = ''
278
+ @discard = ''
279
+ @thread = nil
280
+ @out_mutex = Mutex.new
281
+ @interact = false
282
+ end
283
+
284
+ # Internal: Handle data from the interface, forcing UTF-8 encoding, appending
285
+ # it to the internal buffer, and printing it to $stdout if appropriate.
307
286
  #
308
287
  # Returns nothing.
309
- def process_output
310
- while @pid > 0
311
- unless select([@stdout], nil, nil, @timeout).nil?
312
- buf = ''
313
-
314
- begin
315
- @stdout.sysread(@buffer_size, buf)
316
- rescue Errno::EIO #Application went away.
317
- @pid = 0
318
- return
319
- end
320
-
321
- print_buffer(force_utf8(buf))
322
-
323
- @out_mutex.synchronize do
324
- @buffer << buf
325
- if @constrain && @buffer.length > @buffer_size
326
- @buffer = @buffer[-@buffer_size..-1]
327
- end
328
- @out_update = true
329
- end
288
+ def process_output(buf)
289
+ force_utf8(buf)
290
+ print_buffer(buf)
291
+
292
+ @out_mutex.synchronize do
293
+ @buffer << buf
294
+ if @constrain && @buffer.length > @buffer_size
295
+ @buffer = @buffer[-@buffer_size..-1]
330
296
  end
297
+ @thread.wakeup if @thread
331
298
  end
332
299
  end
333
300
 
334
- # Internal: Prepare environment for interact mode, saving original
335
- # environment parameters.
336
- #
337
- # Returns a Hash object with two keys: :tty containing original tty
338
- # information and :sig containing signal handlers which have been replaced.
339
- def prepare_interact_environment
340
- env = {sig: {}}
341
- # Save our old tty settings and set up our new environment
342
- env[:tty] = `stty -g`
343
- `stty -icanon min 1 time 0 -echo`
344
-
345
- # SIGINT should be sent along to the process.
346
- env[:sig]['INT'] = trap 'INT' do
347
- send "\C-c"
301
+ # Internal: Check for a match against a given pattern until a match is found.
302
+ # This method should be wrapped in a Timeout block or otherwise have some
303
+ # mechanism to break out of the loop.
304
+ #
305
+ # pattern - String or Regexp object containing the pattern for which to
306
+ # watch.
307
+ #
308
+ # Returns a MatchData object containing the match found.
309
+ def check_match(pattern)
310
+ match = nil
311
+ @thread = Thread.current
312
+ while match.nil?
313
+ @out_mutex.synchronize do
314
+ match = pattern.match(@buffer)
315
+ @out_mutex.sleep if match.nil?
316
+ end
348
317
  end
318
+ match
319
+ ensure
320
+ @thread = nil
321
+ end
349
322
 
350
- # SIGTSTP should be sent along to the process as well.
351
- env[:sig]['TSTP'] = trap 'TSTP' do
352
- send "\C-z"
353
- end
323
+ # Internal: Call the Child Interface to instantiate the Expectr object.
324
+ #
325
+ # cmd - String or File object referencing the command to be run.
326
+ #
327
+ # Returns the Interface object.
328
+ def call_child_interface(cmd)
329
+ interface = Expectr::Child.new(cmd)
330
+ @stdin = interface.stdin
331
+ @stdout = interface.stdout
332
+ @pid = interface.pid
354
333
 
355
- # SIGWINCH should trigger an update to the child process
356
- env[:sig]['WINCH'] = trap 'WINCH' do
357
- @stdout.winsize = $stdout.winsize
334
+ Thread.new do
335
+ Process.wait @pid
336
+ @pid = 0
358
337
  end
359
338
 
360
- @interact = true
361
- env
339
+ interface
362
340
  end
363
341
 
364
- # Internal: Restore environment post interact mode from saved parameters.
365
- #
366
- # Returns nothing.
367
- def restore_environment(env)
368
- env[:sig].each_key do |sig|
369
- trap sig, env[:sig][sig]
342
+ # Internal: Call the Lambda Interface to instantiate the Expectr object.
343
+ #
344
+ # args - Arguments hash passed per #initialize.
345
+ #
346
+ # Returns the Interface object.
347
+ def call_lambda_interface(args)
348
+ interface = Expectr::Lambda.new(args[:reader], args[:writer])
349
+ @pid = -1
350
+ @reader = interface.reader
351
+ @writer = interface.writer
352
+
353
+ interface
354
+ end
355
+
356
+ # Internal: Call the Adopt Interface to instantiate the Expectr object.
357
+ #
358
+ # args - Arguments hash passed per #initialize.
359
+ #
360
+ # Returns the Interface object.
361
+ def call_adopt_interface(args)
362
+ interface = Expectr::Adopt.new(args[:stdin], args[:stdout])
363
+ @stdin = interface.stdin
364
+ @stdout = interface.stdout
365
+ @pid = args[:pid] || 1
366
+
367
+ if @pid > 0
368
+ Thread.new do
369
+ Process.wait @pid
370
+ @pid = 0
371
+ end
370
372
  end
371
- `stty #{env[:tty]}`
372
- @interact = false
373
+
374
+ interface
373
375
  end
374
376
 
375
- # Internal: Check for a match against a given pattern until a match is found.
376
- # This method should be wrapped in a Timeout block or otherwise have some
377
- # mechanism to break out of the loop.
377
+ # Internal: Watch for a match within the timeout period.
378
+ #
379
+ # pattern - String or Regexp object containing the pattern for which to
380
+ # watch.
381
+ # recoverable - Boolean denoting whether a failure to find a match should be
382
+ # considered fatal.
378
383
  #
379
- # Returns a MatchData object containing the match found.
380
- def check_match(pattern)
384
+ # Returns a MatchData object if a match was found, or else nil.
385
+ # Raises Timeout::Error if no match is found and recoverable is false.
386
+ def watch_match(pattern, recoverable)
381
387
  match = nil
382
- while match.nil?
383
- if @out_update
384
- @out_mutex.synchronize do
385
- match = pattern.match(@buffer)
386
- @out_update = false
387
- end
388
- end
389
- sleep 0.1
388
+
389
+ Timeout::timeout(@timeout) do
390
+ match = check_match(pattern)
390
391
  end
392
+
393
+ @out_mutex.synchronize do
394
+ @discard = @buffer[0..match.begin(0)-1]
395
+ @buffer = @buffer[match.end(0)..-1]
396
+ end
397
+
391
398
  match
399
+ rescue Timeout::Error => details
400
+ raise(Timeout::Error, details) unless recoverable
401
+ nil
402
+ end
403
+
404
+ # Internal: Process a pattern to procedure mapping, producing a sanitized
405
+ # Hash, a unified Regexp and a boolean denoting whether an Exception should
406
+ # be raised upon timeout.
407
+ #
408
+ # pattern_map - A Hash containing mappings between patterns designated by
409
+ # either strings or Regexp objects, to procedures. Optionally,
410
+ # either :default or :timeout may be mapped to a procedure in
411
+ # order to designate an action to take upon timeout.
412
+ #
413
+ # Returns a Hash, Regexp and boolean object.
414
+ def process_procmap(pattern_map)
415
+ pattern_map = pattern_map.reduce({}) do |c,e|
416
+ c.merge((e[0].is_a?(Symbol) ? e[0] : Regexp.new(e[0].to_s)) => e[1])
417
+ end
418
+ pattern = pattern_map.keys.reduce("") do |c,e|
419
+ e.is_a?(Regexp) ? c + "(#{e.source})|" : c
420
+ end
421
+ pattern = Regexp.new(pattern.gsub(/\|$/, ''))
422
+ recoverable = pattern_map.keys.include?(:default)
423
+ recoverable ||= pattern_map.keys.include?(:timeout)
424
+
425
+ return pattern_map, pattern, recoverable
392
426
  end
393
427
  end
metadata CHANGED
@@ -1,62 +1,54 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expectr
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
5
- prerelease:
4
+ version: 2.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Chris Wuest
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-03 00:00:00.000000000 Z
11
+ date: 2013-06-25 00:00:00.000000000 Z
13
12
  dependencies: []
14
13
  description: Expectr is an interface to the functionality of Expect in Ruby
15
14
  email: chris@chriswuest.com
16
- executables: []
15
+ executables:
16
+ - expectr
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
- - Gemfile
21
- - LICENSE
22
- - README.rdoc
23
- - Rakefile
24
- - expectr.gemspec
25
20
  - lib/expectr.rb
21
+ - lib/expectr/adopt.rb
22
+ - lib/expectr/child.rb
26
23
  - lib/expectr/error.rb
24
+ - lib/expectr/errstr.rb
25
+ - lib/expectr/interface.rb
26
+ - lib/expectr/interpreter.rb
27
+ - lib/expectr/lambda.rb
27
28
  - lib/expectr/version.rb
28
- - test/helper.rb
29
- - test/test_core.rb
30
- - test/test_initialization.rb
31
- - test/test_interaction.rb
32
- - test/test_signals.rb
29
+ - bin/expectr
33
30
  homepage: http://github.com/cwuest/expectr
34
31
  licenses:
35
32
  - MIT
33
+ metadata: {}
36
34
  post_install_message:
37
35
  rdoc_options: []
38
36
  require_paths:
39
37
  - lib
40
38
  required_ruby_version: !ruby/object:Gem::Requirement
41
- none: false
42
39
  requirements:
43
- - - ! '>='
40
+ - - '>='
44
41
  - !ruby/object:Gem::Version
45
42
  version: '0'
46
43
  required_rubygems_version: !ruby/object:Gem::Requirement
47
- none: false
48
44
  requirements:
49
- - - ! '>='
45
+ - - '>='
50
46
  - !ruby/object:Gem::Version
51
47
  version: '0'
52
48
  requirements: []
53
49
  rubyforge_project:
54
- rubygems_version: 1.8.25
50
+ rubygems_version: 2.0.3
55
51
  signing_key:
56
- specification_version: 3
52
+ specification_version: 4
57
53
  summary: Expect for Ruby
58
- test_files:
59
- - test/test_core.rb
60
- - test/test_initialization.rb
61
- - test/test_interaction.rb
62
- - test/test_signals.rb
54
+ test_files: []
data/Gemfile DELETED
@@ -1,2 +0,0 @@
1
- source :rubygems
2
- gemspec
data/LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright (c) 2012 Chris Wuest
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.rdoc DELETED
@@ -1,51 +0,0 @@
1
- = Expectr
2
-
3
- Expectr is an API to the functionality of Expect (see http://expect.nist.gov/)
4
- implemented in ruby.
5
-
6
- == Using Expectr
7
-
8
- Effort is taken to make implementation as simple as possible.
9
-
10
- === Automation
11
-
12
- Implementation of task automation should be relatively straightforward. A
13
- lightweight application might look similar to the following:
14
-
15
- # myapp.rb
16
- require 'expectr'
17
-
18
- exp = Expectr.new( '/bin/bash', flush_buffer: false )
19
- exp.send( "ls\n" )
20
- match = exp.expect( %r{bash} ) # => MatchData
21
- match = exp.expect( "this shouldn't match anything" ) # raises Timeout::Error
22
-
23
- === Interaction
24
-
25
- It is possible to allow a user to interact directly with an Expectr object
26
- as with the Expect functionality in TCL
27
-
28
- # logmein.rb
29
- require 'expectr'
30
-
31
- ssh = { host: 'example.com', user: 'example', pass: 'password' }
32
- exp = Expectr.new( "ssh #{ssh[:user]}@#{ssh[:host]}" )
33
- exp.expect( %r{#{ssh[:user]}@#{ssh[:host]}'s password:} )
34
- ssh.send( ssh[:pass] + "\n" )
35
-
36
- ssh.interact!
37
-
38
- == Contributions
39
-
40
- Effort is made to keep external requirements to a minimum. As such, presently
41
- there are no external requirements for development. If you want to
42
- contribute, please:
43
-
44
- * Fork the project.
45
- * Make a branch for your contribution if it's more than a simple fix.
46
- * Add tests for new functionality.
47
- * Send me a pull request on Github
48
-
49
- == Copyright
50
-
51
- Copyright (c) 2012 Chris Wuest. See LICENSE for details.