slop 3.0.4 → 3.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.
- 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
|
+
[](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
|