cexpect 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1ccc43da0141c2168408e3a9f931f58e37c0a71edab8b2bcd40066396ed8dfbe
4
+ data.tar.gz: 543082cfb8016426f41aad970df5cadee7109f285aec39b8062cb097662ab49a
5
+ SHA512:
6
+ metadata.gz: faf35c685141bbe365000a483594932614fc9b5873b152a5fff7fdbdc961b769f62c91f69b8553f6265b31cf4d9beaf5913f0736e5d21c4f9e644d48b27c98cb
7
+ data.tar.gz: '0383c442a569ac777e57f9bd38b2c63025ad2d1bfb2748ddc6adf0859f32cdc85c755a66d9dfc6c15a336ed5258bafd2566652299954d56d357d3fcb6d9f025f'
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.7.1
6
+ before_install: gem install bundler -v 2.1.4
@@ -0,0 +1,2 @@
1
+ # Changelog for the `cexpect` gem
2
+ * cexpect 0.1.0: First version
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in cexpect.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "rspec", "~> 3.0"
@@ -0,0 +1,34 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cexpect (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.3)
10
+ rake (12.3.3)
11
+ rspec (3.9.0)
12
+ rspec-core (~> 3.9.0)
13
+ rspec-expectations (~> 3.9.0)
14
+ rspec-mocks (~> 3.9.0)
15
+ rspec-core (3.9.1)
16
+ rspec-support (~> 3.9.1)
17
+ rspec-expectations (3.9.1)
18
+ diff-lcs (>= 1.2.0, < 2.0)
19
+ rspec-support (~> 3.9.0)
20
+ rspec-mocks (3.9.1)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.9.0)
23
+ rspec-support (3.9.2)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ cexpect!
30
+ rake (~> 12.0)
31
+ rspec (~> 3.0)
32
+
33
+ BUNDLED WITH
34
+ 2.1.4
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2017, Christer Jansson (christer@janssons.org)
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions are met:
5
+
6
+ 1. Redistributions of source code must retain the above copyright notice, this
7
+ list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright notice,
9
+ this list of conditions and the following disclaimer in the documentation
10
+ and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
16
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,89 @@
1
+ # CExpect
2
+
3
+ The `IO#expect` in the `expect` ruby module is very useful for
4
+ automating interaction with interactive shell scripts. However, it has
5
+ a few shortcomings:
6
+
7
+ * Its return value is not as useful as it could be
8
+ * Logging can only be achieved by setting a global variable
9
+ * Using regexps for matching becomes slow with large amounts of data
10
+ * The default expect timeout is a very large number (this doesn't
11
+ actually affect the functionality negatively, it just feels awkward)
12
+
13
+ To adress this, the CExpect (Christer's Expect) gem offers a different
14
+ interface:
15
+
16
+ * The exposed `expect` method returns or yields the match data when a
17
+ match is found, which makes it possible to e.g. use capturing in a
18
+ meaningful way (see Usage below)
19
+ * It also returns the return value of the block, when a block is given
20
+ * Logging can be achieved by adding observers
21
+ * There is an alternate `fexpect` method (the f can be thought of as
22
+ "fixed" or "fast"), which is useful for capturing large outputs from
23
+ shell commands
24
+ * The default timeout is `nil`, which will cause `expect` to wait
25
+ indefinitely (again, this merely makes more sense to someone reading
26
+ the code)
27
+
28
+ ## Installation
29
+
30
+ Add this line to your application's Gemfile:
31
+
32
+ ```ruby
33
+ gem 'cexpect'
34
+ ```
35
+
36
+ And then execute:
37
+
38
+ $ bundle install
39
+
40
+ Or install it yourself as:
41
+
42
+ $ gem install cexpect
43
+
44
+ ## Usage
45
+
46
+ ```ruby
47
+ require 'cexpect'
48
+
49
+ # Same semantics as PTY.spawn
50
+ rd, wr, pid = CExpect.spawn('sh')
51
+
52
+ rd.fexpect('$ ')
53
+ wr.puts('ls -1')
54
+ md = rd.expect(/ls -1\r\n(?<files>.*)\$ /m)
55
+ files = md[:files].split
56
+
57
+ # Or, equivalently
58
+ rd.expect(/ls -1\r\n(?<files>.*)\$ /m) do |md|
59
+ files = md[:files].split
60
+ # do something with files
61
+ end
62
+
63
+ wr.puts('cat very-large-file')
64
+ contents = rd.fexpect('$ ')
65
+ ```
66
+
67
+ ## Development
68
+
69
+ After checking out the repo, run `bin/setup` to install
70
+ dependencies. Then, run `rake spec` to run the tests. You can also run
71
+ `bin/console` for an interactive prompt that will allow you to
72
+ experiment.
73
+
74
+ To install this gem onto your local machine, run `bundle exec rake
75
+ install`. To release a new version, update the version number in
76
+ `version.rb`, and then run `bundle exec rake release`, which will
77
+ create a git tag for the version, push git commits and tags, and push
78
+ the `.gem` file to [rubygems.org](https://rubygems.org).
79
+
80
+ ## Contributing
81
+
82
+ Bug reports and pull requests are welcome on GitHub at
83
+ https://github.com/kondensatorn/cexpect.
84
+
85
+
86
+ ## License
87
+
88
+ The gem is available as open source under the terms of the [BSD 2-Clause
89
+ License](https://opensource.org/licenses/BSD-2-Clause).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "cexpect"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,27 @@
1
+ require_relative 'lib/cexpect/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "cexpect"
5
+ spec.version = Cexpect::VERSION
6
+ spec.authors = ["Christer Jansson"]
7
+ spec.email = ["christer@janssons.org"]
8
+
9
+ spec.summary = %q{An improved expect method}
10
+ spec.description = %q{An expect method with more reasonable return values and logging functionality}
11
+ spec.homepage = "https://github.com/kondensatorn/cexpect"
12
+ spec.license = "BSD 2-clause"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = spec.homepage
17
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGELOG.md"
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
22
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
+ end
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ["lib"]
27
+ end
@@ -0,0 +1,83 @@
1
+ require 'delegate'
2
+ require 'observer'
3
+ require 'pty'
4
+
5
+ module CExpect
6
+ def self.spawn(*args)
7
+ original_rd, wr, pid = PTY.spawn(*args)
8
+ rd = CExpect::Reader.new(original_rd)
9
+ if block_given?
10
+ yield(rd, wr, pid)
11
+ else
12
+ [rd, wr, pid]
13
+ end
14
+ end
15
+
16
+ class Reader < SimpleDelegator
17
+ include Observable
18
+
19
+ def initialize(_original)
20
+ @leftovers = ''
21
+ super
22
+ end
23
+
24
+ def expect(pat, timeout = nil, match_method: :_expect_re_match)
25
+ buf = +''
26
+
27
+ result = catch(:result) do
28
+ loop { _expect_try(pat, buf, timeout, match_method) }
29
+ end
30
+
31
+ if block_given?
32
+ yield result
33
+ else
34
+ result
35
+ end
36
+ end
37
+
38
+ def fexpect(pat, timeout = nil)
39
+ expect(pat, timeout, match_method: :_expect_string_match)
40
+ end
41
+
42
+ private
43
+
44
+ def _expect_try(pat, buf, timeout, match_method)
45
+ c = _expect_getc(timeout)
46
+
47
+ if c.nil?
48
+ @leftovers = buf
49
+ throw(:result, nil)
50
+ end
51
+
52
+ buf << c
53
+
54
+ _expect_log(pat, buf)
55
+
56
+ result = send(match_method, buf, pat)
57
+ throw(:result, result) if result
58
+ end
59
+
60
+ def _expect_getc(timeout)
61
+ return @leftovers.slice!(0).chr unless @leftovers.empty?
62
+
63
+ return nil if !IO.select([self], nil, nil, timeout) || eof?
64
+
65
+ getc.chr
66
+ end
67
+
68
+ def _expect_log(pat, buf)
69
+ return if count_observers.zero?
70
+
71
+ changed
72
+ notify_observers("pat: #{pat.inspect}\nbuf: #{buf.inspect}\n")
73
+ end
74
+
75
+ def _expect_re_match(buf, pat)
76
+ buf.match(pat)
77
+ end
78
+
79
+ def _expect_string_match(buf, pat)
80
+ buf[0, buf.size - pat.size] if buf.end_with?(pat)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,3 @@
1
+ module Cexpect
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cexpect
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Christer Jansson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-04-28 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: An expect method with more reasonable return values and logging functionality
14
+ email:
15
+ - christer@janssons.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".rspec"
22
+ - ".travis.yml"
23
+ - CHANGELOG.md
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - LICENSE.txt
27
+ - README.md
28
+ - Rakefile
29
+ - bin/console
30
+ - bin/setup
31
+ - cexpect.gemspec
32
+ - lib/cexpect.rb
33
+ - lib/cexpect/version.rb
34
+ homepage: https://github.com/kondensatorn/cexpect
35
+ licenses:
36
+ - BSD 2-clause
37
+ metadata:
38
+ homepage_uri: https://github.com/kondensatorn/cexpect
39
+ source_code_uri: https://github.com/kondensatorn/cexpect
40
+ changelog_uri: https://github.com/kondensatorn/cexpect/CHANGELOG.md
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 2.3.0
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubygems_version: 3.1.2
57
+ signing_key:
58
+ specification_version: 4
59
+ summary: An improved expect method
60
+ test_files: []