ejt_command_line 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +4 -0
- data/ejt_command_line.gemspec +24 -0
- data/lib/ejt_command_line/version.rb +3 -0
- data/lib/ejt_command_line.rb +268 -0
- data/spec/command_line_spec.rb +358 -0
- data/spec/command_line_spec.rb~ +359 -0
- data/spec/spec_helper.rb +8 -0
- metadata +101 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MDQzM2QzNDU0NGE4MzhiOWZhMDc1ZGE0YjA3MDQzZTNkMDQ3Y2MzZA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NmIxZDE2MTE0ZjZiNzQ5OWI4MjFhZTU0MGQwZTU2M2IyMDYxZTBlNA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NDQ2MDc2ZmEzZjY2ODZjNTAyNTQwNzNlMjM3YThjYWFiM2IwNjc0ZmQwNGQ4
|
10
|
+
MDdhODFjYjM4YTk5N2M1ZWM3ODRjNGEzZGM2YmRiMzU1MTNiYjRlNjEwN2U2
|
11
|
+
YTQ2MGRmOGMyM2FhMDI4ZTU4NjkyMjBmZGM0NTJiYjQ4OTkwMzg=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NTdlNzU2NTYwMmNiY2RmZDIxM2I5ZjNiYmZiOWJkZDY3ODc2ZTA0OGZhYTJh
|
14
|
+
MWY5MDllZDNkNWVlZjVjYzZlNjE5Y2NjN2UzMDU4YTM2NDBkNGI0ODZkNzAz
|
15
|
+
YWU2OTJlYWI4ZGYzMTViMjIxNzcwYWQzMWQ3MjU1YTdmMzc2NTU=
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Joe Thornber
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# EjtCommandLine
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ejt_command_line'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ejt_command_line
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ejt_command_line/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ejt_command_line"
|
8
|
+
spec.version = EjtCommandLine::VERSION
|
9
|
+
spec.authors = ["Joe Thornber"]
|
10
|
+
spec.email = ["ejt@redhat.com"]
|
11
|
+
spec.description = %q{Yet another command line parser. Allows you define argument types}
|
12
|
+
spec.summary = %q{Command line parser}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "GPL"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
@@ -0,0 +1,268 @@
|
|
1
|
+
require "ejt_command_line/version"
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
#----------------------------------------------------------------
|
5
|
+
|
6
|
+
module CommandLine
|
7
|
+
# from prelude
|
8
|
+
def bracket_(release)
|
9
|
+
r = nil
|
10
|
+
begin
|
11
|
+
r = yield
|
12
|
+
ensure
|
13
|
+
release.call
|
14
|
+
end
|
15
|
+
r
|
16
|
+
end
|
17
|
+
|
18
|
+
#----------------------------------------------------------------
|
19
|
+
|
20
|
+
class CommandLineError < StandardError
|
21
|
+
end
|
22
|
+
|
23
|
+
class ParseError < CommandLineError
|
24
|
+
end
|
25
|
+
|
26
|
+
class ConfigureError < CommandLineError
|
27
|
+
end
|
28
|
+
|
29
|
+
#----------------------------------------------------------------
|
30
|
+
|
31
|
+
def simple_switch_parser(*aliases)
|
32
|
+
ArrayParser::choice(*aliases)
|
33
|
+
end
|
34
|
+
|
35
|
+
def value_switch_parser(*aliases, &block)
|
36
|
+
p = sequence(choice(*aliases), value(&block))
|
37
|
+
end
|
38
|
+
|
39
|
+
#----------------------------------------------------------------
|
40
|
+
|
41
|
+
class Switch
|
42
|
+
attr_reader :flags, :parser
|
43
|
+
|
44
|
+
def initialize(flags, parser = nil)
|
45
|
+
@flags = flags
|
46
|
+
@parser = parser
|
47
|
+
end
|
48
|
+
|
49
|
+
def has_flag?(flag)
|
50
|
+
@flags.member?(flag)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Command
|
55
|
+
attr_reader :switches
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
@switches = []
|
59
|
+
@mutually_exclusive_sets = [] # list of lists of syms
|
60
|
+
@mandatory = []
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_switches(syms)
|
64
|
+
@switches += syms
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_mutually_exclusive_set(syms)
|
68
|
+
@mutually_exclusive_sets << syms.to_set
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_mandatory_switch(sym)
|
72
|
+
@mandatory << sym
|
73
|
+
end
|
74
|
+
|
75
|
+
def check_mutual_exclusion(syms)
|
76
|
+
nr_sets = @mutually_exclusive_sets.size
|
77
|
+
set_counts = Array.new(nr_sets, [])
|
78
|
+
|
79
|
+
syms.each do |s|
|
80
|
+
# is it in an exclusive set?
|
81
|
+
0.upto(nr_sets - 1) do |n|
|
82
|
+
if @mutually_exclusive_sets[n].member?(s)
|
83
|
+
set_counts[n] << s
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
0.upto(nr_sets - 1) do |n|
|
89
|
+
if set_counts[n].size > 1
|
90
|
+
msg = "mutually exclusive options used:\n"
|
91
|
+
set_counts[n].each {|sym| msg += " #{sym}\n"}
|
92
|
+
raise ParseError, msg
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def check_mandatory(syms)
|
98
|
+
missing = []
|
99
|
+
|
100
|
+
@mandatory.each do |m|
|
101
|
+
unless syms.member?(m)
|
102
|
+
missing << m
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
if missing.size > 0
|
107
|
+
msg = "missing mandatory switches:\n"
|
108
|
+
missing.each do |m|
|
109
|
+
msg += " #{m}\n"
|
110
|
+
end
|
111
|
+
|
112
|
+
raise ParseError, msg
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class Parser
|
118
|
+
GLOBAL_SYM = :global__
|
119
|
+
|
120
|
+
def initialize(&block)
|
121
|
+
@switches = {}
|
122
|
+
@global_switches = []
|
123
|
+
@value_types = {}
|
124
|
+
@commands = Hash.new {|hash, key| Command.new}
|
125
|
+
@current_command = @commands[GLOBAL_SYM]
|
126
|
+
|
127
|
+
configure(&block) if block
|
128
|
+
end
|
129
|
+
|
130
|
+
def configure(&block)
|
131
|
+
self.instance_eval(&block)
|
132
|
+
end
|
133
|
+
|
134
|
+
def value_type(sym, &parser)
|
135
|
+
if @value_types.member?(sym)
|
136
|
+
raise ConfigureError, "duplicate value type '#{sym}'"
|
137
|
+
end
|
138
|
+
|
139
|
+
@value_types[sym] = parser
|
140
|
+
end
|
141
|
+
|
142
|
+
def simple_switch(sym, *flags)
|
143
|
+
@switches[sym] = Switch.new(flags)
|
144
|
+
end
|
145
|
+
|
146
|
+
def value_switch(sym, value_sym, *flags)
|
147
|
+
@switches[sym] = Switch.new(flags, get_value_parser(value_sym))
|
148
|
+
end
|
149
|
+
|
150
|
+
def global(&block)
|
151
|
+
command(GLOBAL_SYM, &block)
|
152
|
+
end
|
153
|
+
|
154
|
+
def command(sym, &block)
|
155
|
+
old = @current_command
|
156
|
+
@current_command = @commands[sym] = Command.new
|
157
|
+
|
158
|
+
if block
|
159
|
+
release = lambda {@current_command = old}
|
160
|
+
bracket_(release) do
|
161
|
+
self.instance_eval(&block)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def switches(*syms)
|
167
|
+
check_switches_are_defined(syms)
|
168
|
+
@current_command.add_switches(syms)
|
169
|
+
end
|
170
|
+
|
171
|
+
def one_of(*syms)
|
172
|
+
check_switches_are_defined(syms)
|
173
|
+
@current_command.add_switches(syms)
|
174
|
+
@current_command.add_mutually_exclusive_set(syms)
|
175
|
+
end
|
176
|
+
|
177
|
+
def mandatory(sym)
|
178
|
+
syms = [sym]
|
179
|
+
check_switches_are_defined(syms)
|
180
|
+
@current_command.add_switches(syms)
|
181
|
+
@current_command.add_mandatory_switch(sym)
|
182
|
+
end
|
183
|
+
|
184
|
+
def parse(handler, *args)
|
185
|
+
command, opts, plain_args = parse_(args)
|
186
|
+
handler.send(command, opts, plain_args)
|
187
|
+
end
|
188
|
+
|
189
|
+
private
|
190
|
+
def parse_value(arg, s, args)
|
191
|
+
if s.parser
|
192
|
+
if args.size == 0
|
193
|
+
raise ParseError, "no value specified for switch '#{arg}'"
|
194
|
+
end
|
195
|
+
|
196
|
+
value = args.shift
|
197
|
+
begin
|
198
|
+
s.parser.call(value)
|
199
|
+
rescue => e
|
200
|
+
raise ParseError, "couldn't parse value '#{arg}=#{value}'\n#{e}"
|
201
|
+
end
|
202
|
+
else
|
203
|
+
true
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def parse_(args)
|
208
|
+
in_command = false
|
209
|
+
opts = {}
|
210
|
+
plain_args = []
|
211
|
+
valid_switches = @commands[GLOBAL_SYM].switches
|
212
|
+
command = :global_command
|
213
|
+
|
214
|
+
while args.size > 0 do
|
215
|
+
arg = args.shift
|
216
|
+
|
217
|
+
if arg =~ /^-/
|
218
|
+
sym, s = find_switch(valid_switches, arg)
|
219
|
+
opts[sym] = parse_value(arg, s, args)
|
220
|
+
|
221
|
+
else
|
222
|
+
cmd = arg.intern
|
223
|
+
|
224
|
+
if !in_command && @commands.member?(cmd)
|
225
|
+
command = cmd
|
226
|
+
valid_switches = @commands[cmd].switches
|
227
|
+
in_command = true
|
228
|
+
else
|
229
|
+
plain_args << arg
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
@commands[command].check_mutual_exclusion(opts.keys)
|
235
|
+
@commands[command].check_mandatory(opts.keys)
|
236
|
+
[command, opts, plain_args]
|
237
|
+
end
|
238
|
+
|
239
|
+
def check_switches_are_defined(syms)
|
240
|
+
syms.each do |sym|
|
241
|
+
raise ConfigureError, "unknown switch '#{sym}'" unless @switches.member?(sym)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def find_switch(valid_switches, switch)
|
246
|
+
catch :found do
|
247
|
+
valid_switches.each do |sym|
|
248
|
+
s = @switches[sym]
|
249
|
+
if s.has_flag?(switch)
|
250
|
+
throw :found, [sym, s]
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
raise ParseError, "unexpected switch '#{switch}'"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def get_value_parser(sym)
|
259
|
+
if @value_types.member?(sym)
|
260
|
+
@value_types[sym]
|
261
|
+
else
|
262
|
+
raise ConfigureError, "unknown value type '#{sym}'"
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
#----------------------------------------------------------------
|
@@ -0,0 +1,358 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include CommandLine
|
4
|
+
|
5
|
+
#----------------------------------------------------------------
|
6
|
+
|
7
|
+
describe "Parser" do
|
8
|
+
before :each do
|
9
|
+
@clh = Parser.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def help_switch
|
13
|
+
@clh.simple_switch :help, '--help', '-h'
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "creation" do
|
17
|
+
it "should take a config block" do
|
18
|
+
block_watcher = mock()
|
19
|
+
block_watcher.should_receive(:executed)
|
20
|
+
|
21
|
+
clh = Parser.new do
|
22
|
+
value_type :string do |str|
|
23
|
+
str
|
24
|
+
end
|
25
|
+
|
26
|
+
block_watcher.executed
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "value types" do
|
32
|
+
it "should allow you to register new value types" do
|
33
|
+
@clh.configure do
|
34
|
+
value_type :string do |str|
|
35
|
+
str
|
36
|
+
end
|
37
|
+
|
38
|
+
value_type :int do |str|
|
39
|
+
str.to_i
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should fail it you try and define a duplicate value type" do
|
45
|
+
@clh.value_type :string do |str|
|
46
|
+
str
|
47
|
+
end
|
48
|
+
|
49
|
+
expect do
|
50
|
+
@clh.value_type :string do |str|
|
51
|
+
str
|
52
|
+
end
|
53
|
+
end.to raise_error(ConfigureError, /string/)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "switches are defined separately from commands" do
|
58
|
+
it "should let you define binary switch" do
|
59
|
+
help_switch
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should fail if you try and define a switch that takes an unknown value type" do
|
63
|
+
expect {@clh.value_switch :resize_to, :volume_size, '--resize-to'}.to raise_error(ConfigureError, /volume_size/)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should let you define an option that takes a single value" do
|
67
|
+
@clh.configure do
|
68
|
+
value_type :volume_size do |str|
|
69
|
+
str.to_i
|
70
|
+
end
|
71
|
+
|
72
|
+
value_switch :resize_to, :volume_size, '--resize-to'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "global switches" do
|
78
|
+
it "should let you bind global switch" do
|
79
|
+
help_switch
|
80
|
+
@clh.configure do
|
81
|
+
global do
|
82
|
+
switches :help
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should raise an error if the switch hasn't been previously defined" do
|
88
|
+
expect do
|
89
|
+
@clh.global do
|
90
|
+
switches :become_sentient
|
91
|
+
end
|
92
|
+
end.to raise_error(ConfigureError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "sub commands" do
|
97
|
+
it "should let you register a command" do
|
98
|
+
@clh.configure do
|
99
|
+
command(:create) {}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should let you omit the block for a command" do
|
104
|
+
@clh.configure do
|
105
|
+
command :create
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should let you bind switches" do
|
110
|
+
@clh.configure do
|
111
|
+
simple_switch :grow_to, '--grow-to'
|
112
|
+
simple_switch :grow_by, '--grow-by'
|
113
|
+
simple_switch :shrink_to, '--shrink-to'
|
114
|
+
simple_switch :shrink_by, '--shrink-by'
|
115
|
+
|
116
|
+
command :resize do
|
117
|
+
switches :grow_to, :grow_by, :shrink_to, :shrink_by
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "parsing" do
|
124
|
+
describe "global command" do
|
125
|
+
it "should handle no switches" do
|
126
|
+
handler = mock()
|
127
|
+
handler.should_receive(:global_command).with({}, [])
|
128
|
+
@clh.parse(handler)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should raise a ParseError if an unrecognised switch is used" do
|
132
|
+
handler = mock()
|
133
|
+
expect {@clh.parse(handler, '--go-back-in-time')}.to raise_error(ParseError, /--go-back-in-time/)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should handle binary switches" do
|
137
|
+
handler = mock()
|
138
|
+
handler.should_receive(:global_command).with({:help => true}, [])
|
139
|
+
|
140
|
+
@clh.configure do
|
141
|
+
simple_switch :help, '--help', '-h'
|
142
|
+
global do
|
143
|
+
switches :help
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
@clh.parse(handler, '-h')
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should handle multiple binary switches" do
|
151
|
+
handler = mock()
|
152
|
+
handler.should_receive(:global_command).with({:help => true, :ro => true}, [])
|
153
|
+
|
154
|
+
@clh.configure do
|
155
|
+
simple_switch :help, '--help', '-h'
|
156
|
+
simple_switch :ro, '--read-only', '-r'
|
157
|
+
|
158
|
+
global do
|
159
|
+
switches :help, :ro
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
@clh.parse(handler, '-h', '--read-only')
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should handle valued switches" do
|
167
|
+
handler = mock()
|
168
|
+
|
169
|
+
@clh.configure do
|
170
|
+
value_type :int do |str|
|
171
|
+
str.to_i
|
172
|
+
end
|
173
|
+
|
174
|
+
value_switch :count, :int, '--count', '-c'
|
175
|
+
|
176
|
+
global do
|
177
|
+
switches :count
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
handler.should_receive(:global_command).
|
182
|
+
with({:count => 17}, [])
|
183
|
+
@clh.parse(handler, '--count', '17')
|
184
|
+
|
185
|
+
handler.should_receive(:global_command).
|
186
|
+
with({:count => 17}, ['one', 'two'])
|
187
|
+
@clh.parse(handler, 'one', '-c', '17', 'two')
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should raise an ArgumentError if no value is given for a valued switch" do
|
191
|
+
handler = mock()
|
192
|
+
|
193
|
+
@clh.configure do
|
194
|
+
value_type :int do |str|
|
195
|
+
str.to_i
|
196
|
+
end
|
197
|
+
|
198
|
+
value_switch :count, :int, '--count', '-c'
|
199
|
+
|
200
|
+
global do
|
201
|
+
switches :count
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
expect do
|
206
|
+
@clh.parse(handler, '--count')
|
207
|
+
end.to raise_error(ParseError, /count/)
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should filter non-switches out" do
|
211
|
+
handler = mock()
|
212
|
+
handler.should_receive(:global_command).
|
213
|
+
with({:help => true, :ro => true}, ['my_file', 'my_other_file'])
|
214
|
+
|
215
|
+
@clh.configure do
|
216
|
+
simple_switch :help, '--help', '-h'
|
217
|
+
simple_switch :ro, '--read-only', '-r'
|
218
|
+
|
219
|
+
global do
|
220
|
+
switches :help, :ro
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
@clh.parse(handler, '-h', 'my_file', '--read-only', 'my_other_file')
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "simple commands" do
|
229
|
+
it "should handle commands that take no switches" do
|
230
|
+
@clh.configure do
|
231
|
+
command :create do
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
handler = mock()
|
236
|
+
handler.should_receive(:create).with({}, ['fred'])
|
237
|
+
@clh.parse(handler, 'create', 'fred')
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "commands" do
|
242
|
+
before :each do
|
243
|
+
@clh.configure do
|
244
|
+
value_type :int do |str|
|
245
|
+
str.to_i
|
246
|
+
end
|
247
|
+
|
248
|
+
value_switch :grow_to, :int, '--grow-to'
|
249
|
+
value_switch :grow_by, :int, '--grow-by'
|
250
|
+
value_switch :shrink_to, :int, '--shrink-to'
|
251
|
+
value_switch :shrink_by, :int, '--shrink-by'
|
252
|
+
|
253
|
+
command :resize do
|
254
|
+
switches :grow_to, :grow_by, :shrink_to, :shrink_by
|
255
|
+
end
|
256
|
+
|
257
|
+
command :shrink do
|
258
|
+
switches :grow_to, :grow_by, :shrink_to, :shrink_by
|
259
|
+
end
|
260
|
+
|
261
|
+
command :grow do
|
262
|
+
switches :grow_to, :grow_by, :shrink_to, :shrink_by
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should allow you to define a sub command" do
|
268
|
+
handler = mock()
|
269
|
+
handler.should_receive(:resize).with({:grow_to => 12345}, ['fred'])
|
270
|
+
@clh.parse(handler, 'resize', '--grow-to', '12345', 'fred')
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should prevent you calling two sub commands on the same line" do
|
274
|
+
handler = mock()
|
275
|
+
handler.should_receive(:resize).
|
276
|
+
with({:grow_to => 1234, :shrink_to => 2345}, ['shrink', 'fred'])
|
277
|
+
@clh.parse(handler, 'resize', '--grow-to', '1234', 'shrink', '--shrink-to', '2345', 'fred')
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
describe "exclusive switches" do
|
282
|
+
before :each do
|
283
|
+
@clh.configure do
|
284
|
+
value_type :int do |str|
|
285
|
+
str.to_i
|
286
|
+
end
|
287
|
+
|
288
|
+
value_switch :grow_to, :int, '--grow-to'
|
289
|
+
value_switch :grow_by, :int, '--grow-by'
|
290
|
+
value_switch :shrink_to, :int, '--shrink-to'
|
291
|
+
value_switch :shrink_by, :int, '--shrink-by'
|
292
|
+
|
293
|
+
command :resize do
|
294
|
+
one_of :grow_to, :grow_by, :shrink_to, :shrink_by
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
it "should parse one exclusive switch" do
|
300
|
+
handler = mock()
|
301
|
+
handler.should_receive(:resize).
|
302
|
+
with({:grow_to => 1234}, ['fred'])
|
303
|
+
@clh.parse(handler, 'resize', '--grow-to', '1234', 'fred')
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should raise a ParseError if more than one switch from an exclusive set is defined" do
|
307
|
+
handler = mock()
|
308
|
+
expect do
|
309
|
+
@clh.parse(handler, 'resize', '--grow-to', '1234', '--shrink-by', '2345', 'fred')
|
310
|
+
end.to raise_error(ParseError, /mutually exclusive/)
|
311
|
+
# FIXME: would be nice to see the actual flags in the exception
|
312
|
+
end
|
313
|
+
|
314
|
+
it "should let you define more than one exclusive set" do
|
315
|
+
pending
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
it "should handle --foo=<value>" do
|
320
|
+
pending "todo"
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
describe "mandatory switches" do
|
325
|
+
before :each do
|
326
|
+
@clh.configure do
|
327
|
+
value_type :int do |str|
|
328
|
+
str.to_i
|
329
|
+
end
|
330
|
+
|
331
|
+
value_switch :grow_to, :int, '--grow-to'
|
332
|
+
value_switch :grow_by, :int, '--grow-by'
|
333
|
+
value_switch :shrink_to, :int, '--shrink-to'
|
334
|
+
value_switch :shrink_by, :int, '--shrink-by'
|
335
|
+
|
336
|
+
command :resize do
|
337
|
+
mandatory :grow_to
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
it "should parse ok if mandatory switch is given" do
|
343
|
+
handler = mock()
|
344
|
+
handler.should_receive(:resize).
|
345
|
+
with({:grow_to => 3}, ['fred'])
|
346
|
+
@clh.parse(handler, 'resize', '--grow-to', '3', 'fred')
|
347
|
+
end
|
348
|
+
|
349
|
+
it "should raise a ParseError if a mandatory switch is omitted" do
|
350
|
+
handler = mock()
|
351
|
+
expect do
|
352
|
+
@clh.parse(handler, 'resize', 'fred')
|
353
|
+
end.to raise_error(ParseError, /grow_to/)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
#----------------------------------------------------------------
|
@@ -0,0 +1,359 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lib/command_line'
|
3
|
+
|
4
|
+
include CommandLine
|
5
|
+
|
6
|
+
#----------------------------------------------------------------
|
7
|
+
|
8
|
+
describe "Parser" do
|
9
|
+
before :each do
|
10
|
+
@clh = Parser.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def help_switch
|
14
|
+
@clh.simple_switch :help, '--help', '-h'
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "creation" do
|
18
|
+
it "should take a config block" do
|
19
|
+
block_watcher = mock()
|
20
|
+
block_watcher.should_receive(:executed)
|
21
|
+
|
22
|
+
clh = Parser.new do
|
23
|
+
value_type :string do |str|
|
24
|
+
str
|
25
|
+
end
|
26
|
+
|
27
|
+
block_watcher.executed
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "value types" do
|
33
|
+
it "should allow you to register new value types" do
|
34
|
+
@clh.configure do
|
35
|
+
value_type :string do |str|
|
36
|
+
str
|
37
|
+
end
|
38
|
+
|
39
|
+
value_type :int do |str|
|
40
|
+
str.to_i
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should fail it you try and define a duplicate value type" do
|
46
|
+
@clh.value_type :string do |str|
|
47
|
+
str
|
48
|
+
end
|
49
|
+
|
50
|
+
expect do
|
51
|
+
@clh.value_type :string do |str|
|
52
|
+
str
|
53
|
+
end
|
54
|
+
end.to raise_error(ConfigureError, /string/)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "switches are defined separately from commands" do
|
59
|
+
it "should let you define binary switch" do
|
60
|
+
help_switch
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should fail if you try and define a switch that takes an unknown value type" do
|
64
|
+
expect {@clh.value_switch :resize_to, :volume_size, '--resize-to'}.to raise_error(ConfigureError, /volume_size/)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should let you define an option that takes a single value" do
|
68
|
+
@clh.configure do
|
69
|
+
value_type :volume_size do |str|
|
70
|
+
str.to_i
|
71
|
+
end
|
72
|
+
|
73
|
+
value_switch :resize_to, :volume_size, '--resize-to'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "global switches" do
|
79
|
+
it "should let you bind global switch" do
|
80
|
+
help_switch
|
81
|
+
@clh.configure do
|
82
|
+
global do
|
83
|
+
switches :help
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should raise an error if the switch hasn't been previously defined" do
|
89
|
+
expect do
|
90
|
+
@clh.global do
|
91
|
+
switches :become_sentient
|
92
|
+
end
|
93
|
+
end.to raise_error(ConfigureError)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "sub commands" do
|
98
|
+
it "should let you register a command" do
|
99
|
+
@clh.configure do
|
100
|
+
command(:create) {}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should let you omit the block for a command" do
|
105
|
+
@clh.configure do
|
106
|
+
command :create
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should let you bind switches" do
|
111
|
+
@clh.configure do
|
112
|
+
simple_switch :grow_to, '--grow-to'
|
113
|
+
simple_switch :grow_by, '--grow-by'
|
114
|
+
simple_switch :shrink_to, '--shrink-to'
|
115
|
+
simple_switch :shrink_by, '--shrink-by'
|
116
|
+
|
117
|
+
command :resize do
|
118
|
+
switches :grow_to, :grow_by, :shrink_to, :shrink_by
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "parsing" do
|
125
|
+
describe "global command" do
|
126
|
+
it "should handle no switches" do
|
127
|
+
handler = mock()
|
128
|
+
handler.should_receive(:global_command).with({}, [])
|
129
|
+
@clh.parse(handler)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should raise a ParseError if an unrecognised switch is used" do
|
133
|
+
handler = mock()
|
134
|
+
expect {@clh.parse(handler, '--go-back-in-time')}.to raise_error(ParseError, /--go-back-in-time/)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should handle binary switches" do
|
138
|
+
handler = mock()
|
139
|
+
handler.should_receive(:global_command).with({:help => true}, [])
|
140
|
+
|
141
|
+
@clh.configure do
|
142
|
+
simple_switch :help, '--help', '-h'
|
143
|
+
global do
|
144
|
+
switches :help
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
@clh.parse(handler, '-h')
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should handle multiple binary switches" do
|
152
|
+
handler = mock()
|
153
|
+
handler.should_receive(:global_command).with({:help => true, :ro => true}, [])
|
154
|
+
|
155
|
+
@clh.configure do
|
156
|
+
simple_switch :help, '--help', '-h'
|
157
|
+
simple_switch :ro, '--read-only', '-r'
|
158
|
+
|
159
|
+
global do
|
160
|
+
switches :help, :ro
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
@clh.parse(handler, '-h', '--read-only')
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should handle valued switches" do
|
168
|
+
handler = mock()
|
169
|
+
|
170
|
+
@clh.configure do
|
171
|
+
value_type :int do |str|
|
172
|
+
str.to_i
|
173
|
+
end
|
174
|
+
|
175
|
+
value_switch :count, :int, '--count', '-c'
|
176
|
+
|
177
|
+
global do
|
178
|
+
switches :count
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
handler.should_receive(:global_command).
|
183
|
+
with({:count => 17}, [])
|
184
|
+
@clh.parse(handler, '--count', '17')
|
185
|
+
|
186
|
+
handler.should_receive(:global_command).
|
187
|
+
with({:count => 17}, ['one', 'two'])
|
188
|
+
@clh.parse(handler, 'one', '-c', '17', 'two')
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should raise an ArgumentError if no value is given for a valued switch" do
|
192
|
+
handler = mock()
|
193
|
+
|
194
|
+
@clh.configure do
|
195
|
+
value_type :int do |str|
|
196
|
+
str.to_i
|
197
|
+
end
|
198
|
+
|
199
|
+
value_switch :count, :int, '--count', '-c'
|
200
|
+
|
201
|
+
global do
|
202
|
+
switches :count
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
expect do
|
207
|
+
@clh.parse(handler, '--count')
|
208
|
+
end.to raise_error(ParseError, /count/)
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should filter non-switches out" do
|
212
|
+
handler = mock()
|
213
|
+
handler.should_receive(:global_command).
|
214
|
+
with({:help => true, :ro => true}, ['my_file', 'my_other_file'])
|
215
|
+
|
216
|
+
@clh.configure do
|
217
|
+
simple_switch :help, '--help', '-h'
|
218
|
+
simple_switch :ro, '--read-only', '-r'
|
219
|
+
|
220
|
+
global do
|
221
|
+
switches :help, :ro
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
@clh.parse(handler, '-h', 'my_file', '--read-only', 'my_other_file')
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "simple commands" do
|
230
|
+
it "should handle commands that take no switches" do
|
231
|
+
@clh.configure do
|
232
|
+
command :create do
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
handler = mock()
|
237
|
+
handler.should_receive(:create).with({}, ['fred'])
|
238
|
+
@clh.parse(handler, 'create', 'fred')
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe "commands" do
|
243
|
+
before :each do
|
244
|
+
@clh.configure do
|
245
|
+
value_type :int do |str|
|
246
|
+
str.to_i
|
247
|
+
end
|
248
|
+
|
249
|
+
value_switch :grow_to, :int, '--grow-to'
|
250
|
+
value_switch :grow_by, :int, '--grow-by'
|
251
|
+
value_switch :shrink_to, :int, '--shrink-to'
|
252
|
+
value_switch :shrink_by, :int, '--shrink-by'
|
253
|
+
|
254
|
+
command :resize do
|
255
|
+
switches :grow_to, :grow_by, :shrink_to, :shrink_by
|
256
|
+
end
|
257
|
+
|
258
|
+
command :shrink do
|
259
|
+
switches :grow_to, :grow_by, :shrink_to, :shrink_by
|
260
|
+
end
|
261
|
+
|
262
|
+
command :grow do
|
263
|
+
switches :grow_to, :grow_by, :shrink_to, :shrink_by
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
it "should allow you to define a sub command" do
|
269
|
+
handler = mock()
|
270
|
+
handler.should_receive(:resize).with({:grow_to => 12345}, ['fred'])
|
271
|
+
@clh.parse(handler, 'resize', '--grow-to', '12345', 'fred')
|
272
|
+
end
|
273
|
+
|
274
|
+
it "should prevent you calling two sub commands on the same line" do
|
275
|
+
handler = mock()
|
276
|
+
handler.should_receive(:resize).
|
277
|
+
with({:grow_to => 1234, :shrink_to => 2345}, ['shrink', 'fred'])
|
278
|
+
@clh.parse(handler, 'resize', '--grow-to', '1234', 'shrink', '--shrink-to', '2345', 'fred')
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "exclusive switches" do
|
283
|
+
before :each do
|
284
|
+
@clh.configure do
|
285
|
+
value_type :int do |str|
|
286
|
+
str.to_i
|
287
|
+
end
|
288
|
+
|
289
|
+
value_switch :grow_to, :int, '--grow-to'
|
290
|
+
value_switch :grow_by, :int, '--grow-by'
|
291
|
+
value_switch :shrink_to, :int, '--shrink-to'
|
292
|
+
value_switch :shrink_by, :int, '--shrink-by'
|
293
|
+
|
294
|
+
command :resize do
|
295
|
+
one_of :grow_to, :grow_by, :shrink_to, :shrink_by
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should parse one exclusive switch" do
|
301
|
+
handler = mock()
|
302
|
+
handler.should_receive(:resize).
|
303
|
+
with({:grow_to => 1234}, ['fred'])
|
304
|
+
@clh.parse(handler, 'resize', '--grow-to', '1234', 'fred')
|
305
|
+
end
|
306
|
+
|
307
|
+
it "should raise a ParseError if more than one switch from an exclusive set is defined" do
|
308
|
+
handler = mock()
|
309
|
+
expect do
|
310
|
+
@clh.parse(handler, 'resize', '--grow-to', '1234', '--shrink-by', '2345', 'fred')
|
311
|
+
end.to raise_error(ParseError, /mutually exclusive/)
|
312
|
+
# FIXME: would be nice to see the actual flags in the exception
|
313
|
+
end
|
314
|
+
|
315
|
+
it "should let you define more than one exclusive set" do
|
316
|
+
pending
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should handle --foo=<value>" do
|
321
|
+
pending "todo"
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
describe "mandatory switches" do
|
326
|
+
before :each do
|
327
|
+
@clh.configure do
|
328
|
+
value_type :int do |str|
|
329
|
+
str.to_i
|
330
|
+
end
|
331
|
+
|
332
|
+
value_switch :grow_to, :int, '--grow-to'
|
333
|
+
value_switch :grow_by, :int, '--grow-by'
|
334
|
+
value_switch :shrink_to, :int, '--shrink-to'
|
335
|
+
value_switch :shrink_by, :int, '--shrink-by'
|
336
|
+
|
337
|
+
command :resize do
|
338
|
+
mandatory :grow_to
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
it "should parse ok if mandatory switch is given" do
|
344
|
+
handler = mock()
|
345
|
+
handler.should_receive(:resize).
|
346
|
+
with({:grow_to => 3}, ['fred'])
|
347
|
+
@clh.parse(handler, 'resize', '--grow-to', '3', 'fred')
|
348
|
+
end
|
349
|
+
|
350
|
+
it "should raise a ParseError if a mandatory switch is omitted" do
|
351
|
+
handler = mock()
|
352
|
+
expect do
|
353
|
+
@clh.parse(handler, 'resize', 'fred')
|
354
|
+
end.to raise_error(ParseError, /grow_to/)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
#----------------------------------------------------------------
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ejt_command_line
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joe Thornber
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-05-30 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: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '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: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Yet another command line parser. Allows you define argument types
|
56
|
+
email:
|
57
|
+
- ejt@redhat.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- .rspec
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE.txt
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- ejt_command_line.gemspec
|
69
|
+
- lib/ejt_command_line.rb
|
70
|
+
- lib/ejt_command_line/version.rb
|
71
|
+
- spec/command_line_spec.rb
|
72
|
+
- spec/command_line_spec.rb~
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
homepage: ''
|
75
|
+
licenses:
|
76
|
+
- GPL
|
77
|
+
metadata: {}
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 2.0.3
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: Command line parser
|
98
|
+
test_files:
|
99
|
+
- spec/command_line_spec.rb
|
100
|
+
- spec/command_line_spec.rb~
|
101
|
+
- spec/spec_helper.rb
|