slop 3.0.4 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +12 -0
- data/CHANGES.md +9 -0
- data/Gemfile +3 -0
- data/README.md +4 -2
- data/lib/slop.rb +32 -20
- data/lib/slop/commands.rb +21 -0
- data/lib/slop/option.rb +38 -5
- data/slop.gemspec +11 -8
- data/test/option_test.rb +9 -1
- data/test/slop_test.rb +9 -1
- metadata +33 -3
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/CHANGES.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
3.1.0
|
2
|
+
-----
|
3
|
+
|
4
|
+
* Allow options to be fetched via underscores instead of dashes
|
5
|
+
(as a fallback) (Eric Anderson, #51)
|
6
|
+
* Added `Slop#strict?` method.
|
7
|
+
* Added strict checks for Integer/Float type casting. (Amon Sha)
|
8
|
+
* Ensure separators are not replacing existing separators (#61)
|
9
|
+
|
1
10
|
3.0.4 (2012-01-31)
|
2
11
|
------------------
|
3
12
|
|
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -5,6 +5,8 @@ Slop is a simple option parser with an easy to remember syntax and friendly API.
|
|
5
5
|
|
6
6
|
This README is targeted at Slop v3.
|
7
7
|
|
8
|
+
[![Build Status](https://secure.travis-ci.org/injekt/slop.png)](http://travis-ci.org/injekt/slop)
|
9
|
+
|
8
10
|
Installation
|
9
11
|
------------
|
10
12
|
|
@@ -27,7 +29,7 @@ opts = Slop.parse do
|
|
27
29
|
banner "ruby foo.rb [options]\n"
|
28
30
|
on :name=, 'Your name'
|
29
31
|
on :p, :password, 'Your password', :argument => :optional
|
30
|
-
on :v :verbose, 'Enable verbose mode'
|
32
|
+
on :v, :verbose, 'Enable verbose mode'
|
31
33
|
end
|
32
34
|
|
33
35
|
# if ARGV is `--name Lee -v`
|
@@ -130,4 +132,4 @@ opts = Slop.parse do
|
|
130
132
|
end
|
131
133
|
|
132
134
|
opts.to_hash #=> { :name => 'lee', :age => 105 }
|
133
|
-
```
|
135
|
+
```
|
data/lib/slop.rb
CHANGED
@@ -4,7 +4,7 @@ require 'slop/commands'
|
|
4
4
|
class Slop
|
5
5
|
include Enumerable
|
6
6
|
|
7
|
-
VERSION = '3.0
|
7
|
+
VERSION = '3.1.0'
|
8
8
|
|
9
9
|
# The main Error class, all Exception classes inherit from this class.
|
10
10
|
class Error < StandardError; end
|
@@ -89,7 +89,7 @@ class Slop
|
|
89
89
|
# Returns a new instance of Slop.
|
90
90
|
def optspec(string, config = {})
|
91
91
|
config[:banner], optspec = string.split(/^--+$/, 2) if string[/^--+$/]
|
92
|
-
lines =
|
92
|
+
lines = optspec.split("\n").reject(&:empty?)
|
93
93
|
opts = Slop.new(config)
|
94
94
|
|
95
95
|
lines.each do |line|
|
@@ -97,7 +97,7 @@ class Slop
|
|
97
97
|
short, long = opt.split(',').map { |s| s.sub(/\A--?/, '') }
|
98
98
|
opt = opts.on(short, long, description)
|
99
99
|
|
100
|
-
if long && long
|
100
|
+
if long && long.end_with?('=')
|
101
101
|
long.sub!(/\=$/, '')
|
102
102
|
opt.config[:argument] = true
|
103
103
|
end
|
@@ -154,6 +154,13 @@ class Slop
|
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
157
|
+
# Is strict mode enabled?
|
158
|
+
#
|
159
|
+
# Returns true if strict mode is enabled, false otherwise.
|
160
|
+
def strict?
|
161
|
+
config[:strict]
|
162
|
+
end
|
163
|
+
|
157
164
|
# Set the banner.
|
158
165
|
#
|
159
166
|
# banner - The String to set the banner.
|
@@ -260,7 +267,7 @@ class Slop
|
|
260
267
|
# with a ? character it will instead call super().
|
261
268
|
def method_missing(method, *args, &block)
|
262
269
|
meth = method.to_s
|
263
|
-
if meth
|
270
|
+
if meth.end_with?('?')
|
264
271
|
present?(meth.chop)
|
265
272
|
else
|
266
273
|
super
|
@@ -272,7 +279,7 @@ class Slop
|
|
272
279
|
# Returns true if this option key exists in our list of options.
|
273
280
|
def respond_to?(method)
|
274
281
|
method = method.to_s
|
275
|
-
if method
|
282
|
+
if method.end_with?('?') && options.any? { |o| o.key == method.chop }
|
276
283
|
true
|
277
284
|
else
|
278
285
|
super
|
@@ -325,7 +332,11 @@ class Slop
|
|
325
332
|
#
|
326
333
|
# text - The String text to print.
|
327
334
|
def separator(text)
|
328
|
-
@separators[options.size]
|
335
|
+
if @separators[options.size]
|
336
|
+
@separators[options.size] << "\n#{text}"
|
337
|
+
else
|
338
|
+
@separators[options.size] = text
|
339
|
+
end
|
329
340
|
end
|
330
341
|
|
331
342
|
# Print a handy Slop help string.
|
@@ -363,17 +374,17 @@ class Slop
|
|
363
374
|
return items
|
364
375
|
end
|
365
376
|
|
366
|
-
items.each_with_index
|
377
|
+
items.each_with_index do |item, index|
|
367
378
|
@trash << index && break if item == '--'
|
368
379
|
autocreate(items, index) if config[:autocreate]
|
369
380
|
process_item(items, index, &block) unless @trash.include?(index)
|
370
|
-
|
371
|
-
items.reject!.with_index { |item, index|
|
381
|
+
end
|
382
|
+
items.reject!.with_index { |item, index| @trash.include?(index) } if delete
|
372
383
|
|
373
|
-
|
374
|
-
if
|
384
|
+
missing_options = options.select { |opt| opt.required? && opt.count < 1 }
|
385
|
+
if missing_options.any?
|
375
386
|
raise MissingOptionError,
|
376
|
-
|
387
|
+
"Missing required option(s): #{missing_options.map(&:key).join(', ')}"
|
377
388
|
end
|
378
389
|
|
379
390
|
if @unknown_options.any?
|
@@ -397,10 +408,10 @@ class Slop
|
|
397
408
|
# Returns nothing.
|
398
409
|
def process_item(items, index, &block)
|
399
410
|
item = items[index]
|
400
|
-
option, argument = extract_option(item) if item
|
411
|
+
option, argument = extract_option(item) if item.start_with?('-')
|
401
412
|
|
402
413
|
if option
|
403
|
-
option.count += 1 unless item
|
414
|
+
option.count += 1 unless item.start_with?('--no-')
|
404
415
|
@trash << index
|
405
416
|
@triggered_options << option
|
406
417
|
|
@@ -426,7 +437,7 @@ class Slop
|
|
426
437
|
option.call(nil)
|
427
438
|
end
|
428
439
|
else
|
429
|
-
@unknown_options << item if
|
440
|
+
@unknown_options << item if strict? && item =~ /\A--?/
|
430
441
|
block.call(item) if block && !@trash.include?(index)
|
431
442
|
end
|
432
443
|
end
|
@@ -441,7 +452,7 @@ class Slop
|
|
441
452
|
# Returns nothing.
|
442
453
|
def execute_option(option, argument, index, item = nil)
|
443
454
|
if !option
|
444
|
-
if config[:multiple_switches] &&
|
455
|
+
if config[:multiple_switches] && strict?
|
445
456
|
raise InvalidOptionError, "Unknown option -#{item}"
|
446
457
|
end
|
447
458
|
return
|
@@ -482,6 +493,7 @@ class Slop
|
|
482
493
|
def extract_option(flag)
|
483
494
|
option = fetch_option(flag)
|
484
495
|
option ||= fetch_option(flag.downcase) if config[:ignore_case]
|
496
|
+
option ||= fetch_option(flag.gsub(/([^-])-/, '\1_'))
|
485
497
|
|
486
498
|
unless option
|
487
499
|
case flag
|
@@ -506,7 +518,7 @@ class Slop
|
|
506
518
|
argument = items[index + 1]
|
507
519
|
option.config[:argument] = (argument && argument !~ /\A--?/)
|
508
520
|
option.config[:autocreated] = true
|
509
|
-
|
521
|
+
options << option
|
510
522
|
end
|
511
523
|
end
|
512
524
|
|
@@ -538,7 +550,7 @@ class Slop
|
|
538
550
|
def extract_short_flag(objects, config)
|
539
551
|
flag = clean(objects.first)
|
540
552
|
|
541
|
-
if flag.size == 2 && flag
|
553
|
+
if flag.size == 2 && flag.end_with?('=')
|
542
554
|
config[:argument] ||= true
|
543
555
|
flag.chop!
|
544
556
|
end
|
@@ -556,8 +568,8 @@ class Slop
|
|
556
568
|
def extract_long_flag(objects, config)
|
557
569
|
flag = objects.first.to_s
|
558
570
|
if flag =~ /\A(?:--?)?[a-zA-Z][a-zA-Z0-9_-]+\=?\??\z/
|
559
|
-
config[:argument] ||= true if flag
|
560
|
-
config[:optional_argument] = true if flag
|
571
|
+
config[:argument] ||= true if flag.end_with?('=')
|
572
|
+
config[:optional_argument] = true if flag.end_with?('=?')
|
561
573
|
objects.shift
|
562
574
|
clean(flag).sub(/\=\??\z/, '')
|
563
575
|
end
|
data/lib/slop/commands.rb
CHANGED
@@ -12,6 +12,27 @@ class Slop
|
|
12
12
|
#
|
13
13
|
# config - An optional configuration Hash.
|
14
14
|
# block - Optional block used to define commands.
|
15
|
+
#
|
16
|
+
# Examples:
|
17
|
+
#
|
18
|
+
# commands = Slop::Commands.new do
|
19
|
+
# on :new do
|
20
|
+
# on '-o', '--outdir=', 'The output directory'
|
21
|
+
# on '-v', '--verbose', 'Enable verbose mode'
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# on :generate do
|
25
|
+
# on '--assets', 'Generate assets', :default => true
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# global do
|
29
|
+
# on '-D', '--debug', 'Enable debug mode', :default => false
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# commands[:new].class #=> Slop
|
34
|
+
# commands.parse
|
35
|
+
#
|
15
36
|
def initialize(config = {}, &block)
|
16
37
|
@config = config
|
17
38
|
@commands = {}
|
data/lib/slop/option.rb
CHANGED
@@ -39,13 +39,12 @@ class Slop
|
|
39
39
|
@config = DEFAULT_OPTIONS.merge(config)
|
40
40
|
@count = 0
|
41
41
|
@callback = block_given? ? block : config[:callback]
|
42
|
-
@value = nil
|
43
42
|
|
44
43
|
@types = {
|
45
44
|
:string => proc { |v| v.to_s },
|
46
45
|
:symbol => proc { |v| v.to_sym },
|
47
|
-
:integer => proc { |v| v
|
48
|
-
:float => proc { |v| v
|
46
|
+
:integer => proc { |v| value_to_integer(v) },
|
47
|
+
:float => proc { |v| value_to_float(v) },
|
49
48
|
:array => proc { |v| v.split(@config[:delimiter], @config[:limit]) },
|
50
49
|
:range => proc { |v| value_to_range(v) }
|
51
50
|
}
|
@@ -129,6 +128,40 @@ class Slop
|
|
129
128
|
|
130
129
|
private
|
131
130
|
|
131
|
+
# Convert an object to an Integer if possible.
|
132
|
+
#
|
133
|
+
# value - The Object we want to convert to an integer.
|
134
|
+
#
|
135
|
+
# Returns the Integer value if possible to convert, else a zero.
|
136
|
+
def value_to_integer(value)
|
137
|
+
if @slop.strict?
|
138
|
+
begin
|
139
|
+
Integer(value.to_s, 10)
|
140
|
+
rescue ArgumentError
|
141
|
+
raise InvalidArgumentError, "#{value} could not be coerced into Integer"
|
142
|
+
end
|
143
|
+
else
|
144
|
+
value.to_s.to_i
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Convert an object to a Float if possible.
|
149
|
+
#
|
150
|
+
# value - The Object we want to convert to a float.
|
151
|
+
#
|
152
|
+
# Returns the Float value if possible to convert, else a zero.
|
153
|
+
def value_to_float(value)
|
154
|
+
if @slop.strict?
|
155
|
+
begin
|
156
|
+
Float(value.to_s)
|
157
|
+
rescue ArgumentError
|
158
|
+
raise InvalidArgumentError, "#{value} could not be coerced into Float"
|
159
|
+
end
|
160
|
+
else
|
161
|
+
value.to_s.to_f
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
132
165
|
# Convert an object to a Range if possible.
|
133
166
|
#
|
134
167
|
# value - The Object we want to convert to a range.
|
@@ -141,7 +174,7 @@ class Slop
|
|
141
174
|
when /\A(-?\d+?)(\.\.\.?|-|,)(-?\d+)\z/
|
142
175
|
Range.new($1.to_i, $3.to_i, $2 == '...')
|
143
176
|
else
|
144
|
-
if @slop.
|
177
|
+
if @slop.strict?
|
145
178
|
raise InvalidArgumentError, "#{value} could not be coerced into Range"
|
146
179
|
else
|
147
180
|
value
|
@@ -150,4 +183,4 @@ class Slop
|
|
150
183
|
end
|
151
184
|
|
152
185
|
end
|
153
|
-
end
|
186
|
+
end
|
data/slop.gemspec
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
|
-
s.name
|
3
|
-
s.version
|
4
|
-
s.summary
|
2
|
+
s.name = 'slop'
|
3
|
+
s.version = '3.1.0'
|
4
|
+
s.summary = 'Option gathering made easy'
|
5
5
|
s.description = 'A simple DSL for gathering options and parsing the command line'
|
6
|
-
s.author
|
7
|
-
s.email
|
8
|
-
s.homepage
|
9
|
-
s.files
|
10
|
-
s.test_files
|
6
|
+
s.author = 'Lee Jarvis'
|
7
|
+
s.email = 'lee@jarvis.co'
|
8
|
+
s.homepage = 'http://github.com/injekt/slop'
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
11
|
+
|
12
|
+
s.add_development_dependency 'rake'
|
13
|
+
s.add_development_dependency 'minitest'
|
11
14
|
end
|
data/test/option_test.rb
CHANGED
@@ -56,6 +56,14 @@ class OptionTest < TestCase
|
|
56
56
|
opts.on :f=, :as => Integer
|
57
57
|
opts.parse %w'-f 1'
|
58
58
|
assert_equal 1, opts[:f]
|
59
|
+
|
60
|
+
opts = Slop.new(:strict => true) { on :r=, :as => Integer }
|
61
|
+
assert_raises(Slop::InvalidArgumentError) { opts.parse %w/-r abc/ }
|
62
|
+
end
|
63
|
+
|
64
|
+
test "float type cast" do
|
65
|
+
opts = Slop.new(:strict => true) { on :r=, :as => Float }
|
66
|
+
assert_raises(Slop::InvalidArgumentError) { opts.parse %w/-r abc/ }
|
59
67
|
end
|
60
68
|
|
61
69
|
test "symbol type cast" do
|
@@ -115,4 +123,4 @@ class OptionTest < TestCase
|
|
115
123
|
slop.on :foo, :help => ' -f, --foo SOMETHING FOOEY'
|
116
124
|
assert_equal ' -f, --foo SOMETHING FOOEY', slop.fetch_option(:foo).help
|
117
125
|
end
|
118
|
-
end
|
126
|
+
end
|
data/test/slop_test.rb
CHANGED
@@ -256,6 +256,13 @@ class SlopTest < TestCase
|
|
256
256
|
assert_equal 'bar', opts[:foo]
|
257
257
|
end
|
258
258
|
|
259
|
+
test "supporting dash" do
|
260
|
+
opts = Slop.new { on :foo_bar= }
|
261
|
+
opts.parse %w' --foo-bar baz '
|
262
|
+
assert_equal 'baz', opts[:foo_bar]
|
263
|
+
assert opts.foo_bar?
|
264
|
+
end
|
265
|
+
|
259
266
|
test "parsing an optspec and building options" do
|
260
267
|
optspec = <<-SPEC
|
261
268
|
ruby foo.rb [options]
|
@@ -284,9 +291,10 @@ class SlopTest < TestCase
|
|
284
291
|
opts = Slop.new do
|
285
292
|
on :foo
|
286
293
|
separator "hello"
|
294
|
+
separator "world"
|
287
295
|
on :bar
|
288
296
|
end
|
289
|
-
assert_equal " --foo \nhello\n --bar ", opts.help
|
297
|
+
assert_equal " --foo \nhello\nworld\n --bar ", opts.help
|
290
298
|
end
|
291
299
|
|
292
300
|
test "printing help with :help => true" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,30 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
13
|
-
dependencies:
|
12
|
+
date: 2012-04-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &70221805243820 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70221805243820
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: minitest
|
27
|
+
requirement: &70221805243060 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70221805243060
|
14
36
|
description: A simple DSL for gathering options and parsing the command line
|
15
37
|
email: lee@jarvis.co
|
16
38
|
executables: []
|
@@ -18,7 +40,9 @@ extensions: []
|
|
18
40
|
extra_rdoc_files: []
|
19
41
|
files:
|
20
42
|
- .gitignore
|
43
|
+
- .travis.yml
|
21
44
|
- CHANGES.md
|
45
|
+
- Gemfile
|
22
46
|
- LICENSE
|
23
47
|
- README.md
|
24
48
|
- Rakefile
|
@@ -42,12 +66,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
42
66
|
- - ! '>='
|
43
67
|
- !ruby/object:Gem::Version
|
44
68
|
version: '0'
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
hash: -2177478579712084864
|
45
72
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
73
|
none: false
|
47
74
|
requirements:
|
48
75
|
- - ! '>='
|
49
76
|
- !ruby/object:Gem::Version
|
50
77
|
version: '0'
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
hash: -2177478579712084864
|
51
81
|
requirements: []
|
52
82
|
rubyforge_project:
|
53
83
|
rubygems_version: 1.8.11
|