checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8d84b5194e0e060985310712fb4bb3babbd1433bf3d05d5b897340df509f23fe
4
+ data.tar.gz: 5924d05b401baefbec39d49c870a7500b0bb9de4e212c980d3da8f2a56f7b935
5
+ SHA512:
6
+ metadata.gz: 6a013a5ee6be8d4d6bb1e319939c5028e9905069d4dbe5a1dd7ebc1025f1b3560ef51027dd3f3b58c68b6386c2b54a3ef238fe36a286ee8eb9f0e5dfcfd978a9
7
+ data.tar.gz: 814d7956dc9aceb546982e5faf89795b7ab4d119b5e75ab8d460f760a8e6d95f80962de527120be63a7c814484320eabac554311c563262e5bf78d645db0d639
data/.gitignore ADDED
@@ -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
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.5
7
+ before_install: gem install bundler -v 2.0.2
8
+ install: bundle install
9
+ script: bundle exec rake spec
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project **may some day** to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.0.1] - 2019-12-02
8
+ ### Added
9
+ - Initial version of ShellB
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in shellb.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ shellb (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ byebug (11.0.1)
10
+ coderay (1.1.2)
11
+ diff-lcs (1.3)
12
+ method_source (0.9.2)
13
+ pry (0.12.2)
14
+ coderay (~> 1.1.0)
15
+ method_source (~> 0.9.0)
16
+ pry-byebug (3.7.0)
17
+ byebug (~> 11.0)
18
+ pry (~> 0.10)
19
+ rake (10.5.0)
20
+ rspec (3.9.0)
21
+ rspec-core (~> 3.9.0)
22
+ rspec-expectations (~> 3.9.0)
23
+ rspec-mocks (~> 3.9.0)
24
+ rspec-core (3.9.0)
25
+ rspec-support (~> 3.9.0)
26
+ rspec-expectations (3.9.0)
27
+ diff-lcs (>= 1.2.0, < 2.0)
28
+ rspec-support (~> 3.9.0)
29
+ rspec-mocks (3.9.0)
30
+ diff-lcs (>= 1.2.0, < 2.0)
31
+ rspec-support (~> 3.9.0)
32
+ rspec-support (3.9.0)
33
+
34
+ PLATFORMS
35
+ ruby
36
+
37
+ DEPENDENCIES
38
+ bundler (~> 2.0)
39
+ pry-byebug (~> 3.0)
40
+ rake (~> 10.0)
41
+ rspec (~> 3.0)
42
+ shellb!
43
+
44
+ BUNDLED WITH
45
+ 2.0.2
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Ryan Duryea
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # ShellB
2
+
3
+ `ShellB` (pronounced Shelby) is a shell script builder. The goal is to be a (near) drop-in replacement for Ruby's `Shell` class
4
+
5
+
6
+ ## FAQ
7
+
8
+ ### Wha? Why?
9
+
10
+ I've long loved Ruby's `Shell` class, essentially a DSL for building a shell script.
11
+
12
+ Imagine my dismay when I realized that piping information between commands in `Shell` is done _through_ Ruby, making my beautiful shell scripts _slow_ and _hungry_ for memory.
13
+
14
+ I wanted something that would build out my shell scripts like `Shell`, but would _stay_ in the shell where commands and pipes work quickly and smoothly.
15
+
16
+ ### I used `ShellB` in place of `Shell` and it didn't work
17
+
18
+ Yikes. I'm not surprised. The library Works For Me in that the few places I use it and I haven't really developed it beyond my own needs.
19
+
20
+ Also, there are some differences I can't figure out how to avoid.
21
+
22
+ ### Why are there so many \\\\\\\\'s in my script?
23
+
24
+ Ruby's `Shellwords` library does that. If you know of a better library for properly escaping shell-related strings, let me know!
25
+
26
+ ## Installation
27
+
28
+ Add this line to your application's Gemfile:
29
+
30
+ ```ruby
31
+ gem 'shellb'
32
+ ```
33
+
34
+ And then execute:
35
+
36
+ $ bundle
37
+
38
+ Or install it yourself as:
39
+
40
+ $ gem install shellb
41
+
42
+ ## Usage
43
+
44
+ `ShellB` is intended to work similarly to Shell. There are a few differences:
45
+
46
+ 1. All commands you intend to use must be defined via `ShellB.def_system_command`
47
+ 2. Unlike `Shell`, `ShellB` will not run any commands on its own. You must either
48
+ - Call `#run` on a `ShellB::Shell` instance
49
+ - Call `ShellB::Shell#run { <commands here> }` which will immediately execute the script
50
+
51
+ See the examples below.
52
+
53
+ ## Examples
54
+
55
+ ```
56
+ %w[a b c d e f g].each do |cmd|
57
+ ShellB.def_system_command(cmd)
58
+ end
59
+
60
+ # Support Shell's #transact method -- my favorite way to build a script
61
+ shb = ShellB.new
62
+ script = shb.transact do
63
+ a | b | c("--last", "--delimiter", "\t")
64
+ end
65
+ puts script # a | b | c --last --delimiter "\t"
66
+
67
+ # Invoke methods directly on ShellB::Shell instance
68
+ shb = ShellB.new
69
+ shb.a("--help") | shb.e("last")
70
+ puts shb.to_sh # => a --help | e last
71
+
72
+ # Mix transact and direct methods
73
+ shb = ShellB.new
74
+ shb.a("--help") | shb.transact do
75
+ e("last") > dest.txt
76
+ end
77
+ puts shb.to_sh # => a --help | e last > dest.txt
78
+
79
+ # Run a script
80
+ shb = ShellB.new
81
+ shb.a("--help") | shb.e("last")
82
+ shb.run # creates a temporary script file and invokes it using Bash
83
+
84
+ # Immediately run a script after building it
85
+ ShellB.new.run do
86
+ a | b
87
+ c
88
+ end
89
+
90
+ # Support `cd` ala Shell
91
+ # NOT YET IMPLEMENTED
92
+ shb.cd("/tmp") do
93
+ pwd
94
+ end # => (cd /tmp ; pwd)
95
+
96
+ # Handle Multiple Inputs into a Command
97
+ # Allow variable names as arguments
98
+ # NOT YET IMPLEMENTED
99
+ file1_csv = "/tmp/file1.csv"
100
+ file2_csv = "/tmp/file2.csv"
101
+ shb.transact do
102
+ diff \
103
+ < transact(do
104
+ xsv("sort", file1_csv) | head
105
+ end) \
106
+ < transact({
107
+ xsv("sort", file2_csv) | tail
108
+ })
109
+ end # => diff <(xsv sort /tmp/file1.csv | head) <(xsv sort /tmp/file2.csv | tail)
110
+ ```
111
+
112
+ ## Future Ideas
113
+
114
+ Some ideas I'm toying with:
115
+
116
+ ### Support for hash => switches
117
+
118
+ It might be handy to feed a hash to a command and have that generate the appropriate switches for a command.
119
+
120
+ Something like:
121
+
122
+ ```
123
+ shb = ShellB.new
124
+ shb.transact do
125
+ e(long_switch: "value", s: true)
126
+ end
127
+ puts shb.to_sh # => e --long-switch value -s
128
+ ```
129
+
130
+ However, how do we handle some of the following?
131
+
132
+ - Underscore vs dash in long names?
133
+ - E.g. does `long_switch_name` become `--long-switch-name` or `--long_switch_name`
134
+ - For long switches, do we include an equals sign if a value is included?
135
+ - E.g. does `long_switch_name: "value"` become `--long-switch-name=value` or `--long-switch-name value`
136
+ - For switches without arguments, do we relegate those to an array only, or allow them in the hash?
137
+ - E.g. does `s: true` become `-s`
138
+
139
+ ## Development
140
+
141
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
142
+
143
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
144
+
145
+ ## Contributing
146
+
147
+ Bug reports and pull requests are welcome on GitHub at https://github.com/aguynamedryan/shellb.
148
+
149
+ ## License
150
+
151
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -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
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "shellb"
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__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=#x27;\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/shellb.rb ADDED
@@ -0,0 +1,25 @@
1
+ require "shellb/version"
2
+ require "shellb/shell"
3
+ begin
4
+ require "pry-byebug"
5
+ rescue LoadError
6
+ end
7
+
8
+ module ShellB
9
+ class Error < StandardError; end
10
+ class ExecutionError < StandardError; attr_accessor :script ; end
11
+ # Your code goes here...
12
+ class << self
13
+ def new(*args)
14
+ Shell.new(*args)
15
+ end
16
+
17
+ def def_system_command(*args)
18
+ Shell.def_system_command(*args)
19
+ end
20
+
21
+ def alias_command(*args)
22
+ Shell.alias_command(*args)
23
+ end
24
+ end
25
+ end
data/lib/shellb/command.rb ADDED
@@ -0,0 +1,69 @@
1
+ require "shellwords"
2
+
3
+ module ShellB
4
+ class Command
5
+ attr_reader :name, :opts, :shell, :block
6
+ attr_accessor :downstream
7
+
8
+ def initialize(shell, name, *opts)
9
+ @shell = shell
10
+ @name = name
11
+ @opts = opts
12
+ end
13
+
14
+ def |(command)
15
+ shell.drop_command(command)
16
+ self.downstream = command
17
+ end
18
+
19
+ def >(to)
20
+ @output = to
21
+ self
22
+ end
23
+
24
+ def >>(to)
25
+ @append = to
26
+ self
27
+ end
28
+
29
+ def <(from)
30
+ @input = from
31
+ self
32
+ end
33
+
34
+ def redirection_parts
35
+ return [">", @output.to_s] if @output
36
+ return [">>", @append.to_s] if @append
37
+ return ["<", @input.to_s] if @input
38
+ return []
39
+ end
40
+
41
+ def to_s
42
+ "<Command: #{name} #{opts.join(" ")}>"
43
+ end
44
+
45
+ def to_sh
46
+ parts = []
47
+ parts << Shellwords.shelljoin([name, *opts])
48
+
49
+ unless (rd_parts = redirection_parts.join(" ")).empty?
50
+ parts.last << " " + rd_parts
51
+ end
52
+
53
+ parts << downstream.to_sh if downstream
54
+ parts.join(" | ")
55
+ end
56
+
57
+ def pretty_print(pp)
58
+ pp.object_group(self) do
59
+ pp.breakable
60
+ pp.text "@name="
61
+ pp.pp @name
62
+
63
+ pp.breakable
64
+ pp.text "@opts="
65
+ pp.pp @opts
66
+ end
67
+ end
68
+ end
69
+ end
data/lib/shellb/commander.rb ADDED
@@ -0,0 +1,32 @@
1
+ require_relative "command"
2
+
3
+ module ShellB
4
+ class Commander
5
+ attr_reader :shell
6
+
7
+ class << self
8
+ def def_system_command(name, path = nil)
9
+ define_method(name) do |*args|
10
+ Command.new(shell, path || name, *args)
11
+ end
12
+ end
13
+
14
+ def alias_command(name, *args)
15
+ define_method(name) do |*opts|
16
+ Command.new(shell, *args, *opts)
17
+ end
18
+ end
19
+ end
20
+
21
+ DEFAULT_COMMANDS = %w[
22
+ cd
23
+ pwd
24
+ ].each do |cmd|
25
+ def_system_command(cmd)
26
+ end
27
+
28
+ def initialize(shell)
29
+ @shell = shell
30
+ end
31
+ end
32
+ end
data/lib/shellb/shell.rb ADDED
@@ -0,0 +1,122 @@
1
+ require "tempfile"
2
+ require_relative "commander"
3
+
4
+ module ShellB
5
+ class Shell
6
+ class << self
7
+ def def_system_command(name, path = nil)
8
+ Commander.def_system_command(name, path)
9
+ end
10
+
11
+ def alias_command(name, *args)
12
+ Commander.alias_command(name, *args)
13
+ end
14
+ end
15
+
16
+ attr_reader :opts
17
+ def initialize(opts = {})
18
+ @commands = []
19
+ @opts = opts
20
+ end
21
+
22
+ def transact(&block)
23
+ instance_eval(&block)
24
+ @commands.last
25
+ end
26
+
27
+ def add_command(command)
28
+ @commands << command
29
+ command
30
+ end
31
+
32
+ def drop_command(command)
33
+ @commands -= [command]
34
+ end
35
+
36
+ def run(opts = {}, &block)
37
+ if block
38
+ transact(&block)
39
+ end
40
+ script = Tempfile.new("script.sh")
41
+ script.write(to_sh(opts))
42
+ script.close
43
+ output = `bash #{script.path}`
44
+ unless $?.exitstatus.zero?
45
+ ee = ShellB::ExecutionError.new(output)
46
+ ee.script = File.read(script)
47
+ raise ee
48
+ end
49
+ ensure
50
+ script.close!
51
+ end
52
+
53
+ def run!(opts = {}, &block)
54
+ run(opts.merge(exit_on_errors: true), &block)
55
+ end
56
+
57
+ def to_sh(opts = {})
58
+ str = make_preamble(opts)
59
+ str += @commands.map do |command|
60
+ decorate_command(command, opts)
61
+ end.join("\n\n")
62
+ str
63
+ end
64
+
65
+ def decorate_command(command, opts)
66
+ cmd_str = command.to_sh
67
+ return cmd_str unless opts[:exit_on_errors]
68
+ cmd_str = wrap_it(cmd_str, "(") unless command.name == "cd"
69
+ "#{cmd_str} || exit $?"
70
+ end
71
+
72
+ def method_missing(meth, *args)
73
+ return super unless commander.respond_to?(meth)
74
+ add_command(commander.public_send(meth, *args))
75
+ end
76
+
77
+ def make_preamble(opts)
78
+ preamble = []
79
+ if opts[:exit_on_errors]
80
+ preamble << %w[set -x]
81
+ preamble << %w[set -e]
82
+ preamble << []
83
+ end
84
+ preamble = preamble.map { |pream| Shellwords.join(pream) }
85
+ preamble.join("\n")
86
+ end
87
+
88
+ def respond_to?(meth)
89
+ super || commander.respond_to?(meth)
90
+ end
91
+
92
+ def commander
93
+ @commander ||= Commander.new(self)
94
+ end
95
+
96
+ def check_point
97
+ #no-op
98
+ end
99
+
100
+ def pretty_print(pp)
101
+ pp.object_group(self) do
102
+ pp.breakable
103
+ pp.text "@commands="
104
+ pp.pp @commands
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ def wrap_it(str, wrap_char)
111
+ return str if wrap_char.nil?
112
+
113
+ wrap_char = "(" if wrap_char == true
114
+ end_char = {
115
+ "(" => ")",
116
+ "{" => "}",
117
+ "[" => "]"
118
+ }[wrap_char] || raise("No matching character for #{wrap_char}")
119
+ "#{wrap_char} #{str} #{end_char}"
120
+ end
121
+ end
122
+ end
data/lib/shellb/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module ShellB
2
+ VERSION = "0.0.1"
3
+ end
data/shellb.gemspec ADDED
@@ -0,0 +1,43 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "shellb/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "shellb"
8
+ spec.version = ShellB::VERSION
9
+ spec.authors = ["Ryan Duryea"]
10
+ spec.email = ["aguynamedryan@gmail.com"]
11
+
12
+ spec.summary = %q{Light DSL to generate shell scripts}
13
+ spec.description = %q{Ruby's Shell class is awesome, but it is slow and memory intensive because all IO passes through Ruby. This gem is heavily inspired by the Shell class, but instead generates a script that executes in a shell without having Ruby in the mix, keeping things fast.}
14
+ spec.homepage = "https://github.com/aguynamedryan/shellb"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
21
+
22
+ spec.metadata["homepage_uri"] = spec.homepage
23
+ spec.metadata["source_code_uri"] = "https://github.com/aguynamedryan/shellb"
24
+ spec.metadata["changelog_uri"] = "https://github.com/aguynamedryan/shellb/CHANGELOG.md"
25
+ else
26
+ raise "RubyGems 2.0 or newer is required to protect against " \
27
+ "public gem pushes."
28
+ end
29
+
30
+ # Specify which files should be added to the gem when it is released.
31
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
32
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
33
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
34
+ end
35
+ spec.bindir = "exe"
36
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
+ spec.require_paths = ["lib"]
38
+
39
+ spec.add_development_dependency "bundler", "~> 2.0"
40
+ spec.add_development_dependency "rake", "~> 10.0"
41
+ spec.add_development_dependency "rspec", "~> 3.0"
42
+ spec.add_development_dependency "pry-byebug", "~> 3.0"
43
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shellb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Duryea
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-12-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description: Ruby's Shell class is awesome, but it is slow and memory intensive because
70
+ all IO passes through Ruby. This gem is heavily inspired by the Shell class, but
71
+ instead generates a script that executes in a shell without having Ruby in the mix,
72
+ keeping things fast.
73
+ email:
74
+ - aguynamedryan@gmail.com
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - ".gitignore"
80
+ - ".rspec"
81
+ - ".travis.yml"
82
+ - CHANGELOG.md
83
+ - Gemfile
84
+ - Gemfile.lock
85
+ - LICENSE.txt
86
+ - README.md
87
+ - Rakefile
88
+ - bin/console
89
+ - bin/setup
90
+ - lib/shellb.rb
91
+ - lib/shellb/command.rb
92
+ - lib/shellb/commander.rb
93
+ - lib/shellb/shell.rb
94
+ - lib/shellb/version.rb
95
+ - shellb.gemspec
96
+ homepage: https://github.com/aguynamedryan/shellb
97
+ licenses:
98
+ - MIT
99
+ metadata:
100
+ allowed_push_host: https://rubygems.org
101
+ homepage_uri: https://github.com/aguynamedryan/shellb
102
+ source_code_uri: https://github.com/aguynamedryan/shellb
103
+ changelog_uri: https://github.com/aguynamedryan/shellb/CHANGELOG.md
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubygems_version: 3.0.6
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: Light DSL to generate shell scripts
123
+ test_files: []