slop 1.4.0 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +124 -108
- data/lib/slop.rb +6 -8
- data/lib/slop/option.rb +15 -0
- data/test/option_test.rb +11 -0
- data/test/slop_test.rb +17 -0
- metadata +2 -2
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Slop
|
2
2
|
====
|
3
3
|
|
4
|
-
Slop is a simple option
|
4
|
+
Slop is a simple option parser with an easy to remember syntax and friendly API.
|
5
5
|
|
6
6
|
Installation
|
7
7
|
------------
|
@@ -18,49 +18,49 @@ Installation
|
|
18
18
|
|
19
19
|
Usage
|
20
20
|
-----
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
21
|
+
# parse assumes ARGV, otherwise you can pass it your own Array
|
22
|
+
opts = Slop.parse do
|
23
|
+
on :v, :verbose, 'Enable verbose mode' # boolean value
|
24
|
+
on :n, :name, 'Your name', true # compulsory argument
|
25
|
+
on :s, :sex, 'Your sex', :optional => false # the same thing
|
26
|
+
on :a, :age, 'Your age', :optional => true # optional argument
|
27
|
+
end
|
28
|
+
|
29
|
+
# if ARGV is `-v --name 'lee jarvis' -s male`
|
30
|
+
opts.verbose? #=> true
|
31
|
+
opts.name? #=> true
|
32
|
+
opts[:name] #=> 'lee jarvis'
|
33
|
+
opts.age? #=> false
|
34
|
+
opts[:age] #=> nil
|
35
35
|
|
36
36
|
You can also return your options as a Hash
|
37
37
|
|
38
|
-
|
38
|
+
opts.to_hash #=> {'name' => 'Lee Jarvis', 'verbose' => true, 'age' => nil, 'sex' => 'male'}
|
39
39
|
|
40
|
-
|
41
|
-
|
40
|
+
# Symbols
|
41
|
+
opts.to_hash(true) #=> {:name => 'Lee Jarvis', :verbose => true, :age => nil, :sex => 'male'}
|
42
42
|
|
43
43
|
If you don't like the method `on` (because it sounds like the option **expects**
|
44
44
|
a block), you can use the `opt` or `option` alternatives.
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
on :v, :verbose
|
47
|
+
opt :v, :verbose
|
48
|
+
option :v, :verbose
|
49
49
|
|
50
50
|
If you don't like that Slop evaluates your block, or you want slop access
|
51
51
|
inside of your block without referring to `self`, you can pass a block argument to
|
52
52
|
`parse`.
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
Slop.parse do |opts|
|
55
|
+
opts.on :v, :verbose
|
56
|
+
opts.on :n, :name, 'Your name', true
|
57
|
+
end
|
58
58
|
|
59
59
|
If you want some pretty output for the user to see your options, you can just
|
60
60
|
send the Slop object to `puts` or use the `help` method.
|
61
61
|
|
62
|
-
|
63
|
-
|
62
|
+
puts opts
|
63
|
+
puts opts.help
|
64
64
|
|
65
65
|
Will output something like
|
66
66
|
|
@@ -70,14 +70,18 @@ Will output something like
|
|
70
70
|
|
71
71
|
You can also add a banner using the `banner` method
|
72
72
|
|
73
|
-
|
74
|
-
|
73
|
+
opts = Slop.parse
|
74
|
+
opts.banner = "Usage: foo.rb [options]"
|
75
|
+
|
76
|
+
or
|
77
|
+
|
78
|
+
opts = Slop.parse do
|
79
|
+
banner "Usage: foo.rb [options]"
|
80
|
+
end
|
75
81
|
|
76
82
|
or
|
77
83
|
|
78
|
-
|
79
|
-
banner "Usage: foo.rb [options]"
|
80
|
-
end
|
84
|
+
opts = Slop.new "Usage: foo.rb [options]"
|
81
85
|
|
82
86
|
Helpful Help
|
83
87
|
------------
|
@@ -116,12 +120,12 @@ Now throw some options at it:
|
|
116
120
|
|
117
121
|
Here's what we'll get back
|
118
122
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
123
|
+
{
|
124
|
+
:server=>"ftp://foobar.com",
|
125
|
+
:port=>1234,
|
126
|
+
:username=>"FooBar",
|
127
|
+
:password=>"hello there"
|
128
|
+
}
|
125
129
|
|
126
130
|
Callbacks
|
127
131
|
---------
|
@@ -147,17 +151,17 @@ they're found, just like
|
|
147
151
|
[OptionParser](http://rubydoc.info/stdlib/optparse/1.9.2/OptionParser:order)
|
148
152
|
does it.
|
149
153
|
|
150
|
-
|
151
|
-
|
152
|
-
|
154
|
+
opts = Slop.new do
|
155
|
+
on :n, :name, :optional => false
|
156
|
+
end
|
153
157
|
|
154
|
-
|
155
|
-
|
156
|
-
|
158
|
+
opts.parse do |arg|
|
159
|
+
puts arg
|
160
|
+
end
|
157
161
|
|
158
|
-
|
159
|
-
|
160
|
-
|
162
|
+
# if ARGV is `foo --name Lee bar`
|
163
|
+
foo
|
164
|
+
bar
|
161
165
|
|
162
166
|
Negative Options
|
163
167
|
----------------
|
@@ -165,16 +169,16 @@ Negative Options
|
|
165
169
|
Slop also allows you to prefix `--no-` to an option which will force the option
|
166
170
|
to return a false value.
|
167
171
|
|
168
|
-
|
169
|
-
|
170
|
-
|
172
|
+
opts = Slop.parse do
|
173
|
+
on :v, :verbose, :default => true
|
174
|
+
end
|
171
175
|
|
172
|
-
|
173
|
-
|
176
|
+
# with no command line options
|
177
|
+
opts[:verbose] #=> true
|
174
178
|
|
175
|
-
|
176
|
-
|
177
|
-
|
179
|
+
# with `--no-verbose`
|
180
|
+
opts[:verbose] #=> false
|
181
|
+
opts.verbose? #=> false
|
178
182
|
|
179
183
|
Short Switches
|
180
184
|
--------------
|
@@ -196,16 +200,49 @@ by passing the `:multiple_switches` option to a new Slop object.
|
|
196
200
|
opts[:b] #=> false
|
197
201
|
opts[:c] #=> true
|
198
202
|
|
203
|
+
Lists
|
204
|
+
-----
|
205
|
+
|
206
|
+
You can of course also parse lists into options. Here's how:
|
207
|
+
|
208
|
+
opts = Slop.parse do
|
209
|
+
opt :people, true, :as => Array
|
210
|
+
end
|
211
|
+
|
212
|
+
# ARGV is `--people lee,john,bill`
|
213
|
+
opts[:people] #=> ['lee', 'john', 'bill']
|
214
|
+
|
215
|
+
You can also change both the split delimiter and limit
|
216
|
+
|
217
|
+
opts = Slop.parse do
|
218
|
+
opt :people, true, :as => Array, :delimiter => ':', :limit => 2)
|
219
|
+
end
|
220
|
+
|
221
|
+
# ARGV is `--people lee:injekt:bob`
|
222
|
+
opts[:people] #=> ["lee", "injekt:bob"]
|
223
|
+
|
224
|
+
Ranges
|
225
|
+
------
|
226
|
+
|
227
|
+
What would Slop be if it didn't know what ranges were?
|
228
|
+
|
229
|
+
opts = Slop.parse do
|
230
|
+
opt :r, :range, true, :as => Range
|
231
|
+
end
|
232
|
+
|
233
|
+
# ARGV is `--range 1..10` or 1-10, or 1,10 (yes Slop supports them all)
|
234
|
+
opts[:range].to_a #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
235
|
+
|
199
236
|
Ugh, Symbols
|
200
237
|
------------
|
201
238
|
|
202
239
|
Fine, don't use them
|
203
240
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
241
|
+
Slop.parse do
|
242
|
+
on :n, :name, 'Your name'
|
243
|
+
on 'n', 'name', 'Your name'
|
244
|
+
on '-n', '--name', 'Your name'
|
245
|
+
end
|
209
246
|
|
210
247
|
All of these options will do the same thing
|
211
248
|
|
@@ -214,9 +251,9 @@ Ugh, Blocks
|
|
214
251
|
|
215
252
|
C'mon man, this is Ruby, GTFO if you don't like blocks.
|
216
253
|
|
217
|
-
|
218
|
-
|
219
|
-
|
254
|
+
opts = Slop.new
|
255
|
+
opts.on :v, :verbose
|
256
|
+
opts.parse
|
220
257
|
|
221
258
|
Smart
|
222
259
|
-----
|
@@ -225,39 +262,18 @@ Slop is pretty smart when it comes to building your options, for example if you
|
|
225
262
|
want your option to have a flag attribute, but no `--option` attribute, you
|
226
263
|
can do this:
|
227
264
|
|
228
|
-
|
265
|
+
on :n, "Your name"
|
229
266
|
|
230
267
|
and Slop will detect a description in place of an option, so you don't have to
|
231
268
|
do this:
|
232
269
|
|
233
|
-
|
270
|
+
on :n, nil, "Your name", true
|
234
271
|
|
235
272
|
You can also try other variations:
|
236
273
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
Lists
|
242
|
-
-----
|
243
|
-
|
244
|
-
You can of course also parse lists into options. Here's how:
|
245
|
-
|
246
|
-
opts = Slop.parse do
|
247
|
-
opt :people, true, :as => Array
|
248
|
-
end
|
249
|
-
|
250
|
-
# ARGV is `--people lee,john,bill`
|
251
|
-
opts[:people] #=> ['lee', 'john', 'bill']
|
252
|
-
|
253
|
-
You can also change both the split delimiter and limit
|
254
|
-
|
255
|
-
opts = Slop.parse do
|
256
|
-
opt :people, true, :as => Array, :delimiter => ':', :limit => 2)
|
257
|
-
end
|
258
|
-
|
259
|
-
# ARGV is `--people lee:injekt:bob`
|
260
|
-
opts[:people] #=> ["lee", "injekt:bob"]
|
274
|
+
on :name, "Your name"
|
275
|
+
on :n, :name
|
276
|
+
on :name, true
|
261
277
|
|
262
278
|
Strict Mode
|
263
279
|
-----------
|
@@ -306,33 +322,33 @@ I'm not, honestly! I love OptionParser. I really do, it's a fantastic library.
|
|
306
322
|
So why did I build Slop? Well, I find myself using OptionParser to simply
|
307
323
|
gather a bunch of key/value options, usually you would do something like this:
|
308
324
|
|
309
|
-
|
325
|
+
require 'optparse'
|
310
326
|
|
311
|
-
|
327
|
+
things = {}
|
312
328
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
329
|
+
opt = OptionParser.new do |opt|
|
330
|
+
opt.on('-n', '--name NAME', 'Your name') do |name|
|
331
|
+
things[:name] = name
|
332
|
+
end
|
317
333
|
|
318
|
-
|
319
|
-
|
320
|
-
|
334
|
+
opt.on('-a', '--age AGE', 'Your age') do |age|
|
335
|
+
things[:age] = age
|
336
|
+
end
|
321
337
|
|
322
|
-
|
323
|
-
|
338
|
+
# you get the point
|
339
|
+
end
|
324
340
|
|
325
|
-
|
326
|
-
|
341
|
+
opt.parse
|
342
|
+
things #=> { :name => 'lee', :age => 105 }
|
327
343
|
|
328
344
|
Which is all great and stuff, but it can lead to some repetition, the same
|
329
345
|
thing in Slop:
|
330
346
|
|
331
|
-
|
347
|
+
require 'slop'
|
332
348
|
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
349
|
+
opts = Slop.parse do
|
350
|
+
on :n, :name, 'Your name', true
|
351
|
+
on :a, :age, 'Your age', true
|
352
|
+
end
|
337
353
|
|
338
|
-
|
354
|
+
opts.to_hash(true) #=> { :name => 'lee', :age => 105 }
|
data/lib/slop.rb
CHANGED
@@ -16,7 +16,7 @@ class Slop
|
|
16
16
|
class InvalidOptionError < RuntimeError; end
|
17
17
|
|
18
18
|
# @return [String] The current version string
|
19
|
-
VERSION = '1.4.
|
19
|
+
VERSION = '1.4.1'
|
20
20
|
|
21
21
|
# Parses the items from a CLI format into a friendly object.
|
22
22
|
#
|
@@ -57,10 +57,10 @@ class Slop
|
|
57
57
|
def initialize(*opts, &block)
|
58
58
|
sloptions = {}
|
59
59
|
sloptions.merge! opts.pop if opts.last.is_a? Hash
|
60
|
+
@banner = opts.shift if opts[0].respond_to?(:to_str)
|
60
61
|
opts.each { |o| sloptions[o] = true }
|
61
62
|
|
62
63
|
@options = Options.new
|
63
|
-
@banner = nil
|
64
64
|
@longest_flag = 0
|
65
65
|
@strict = sloptions[:strict]
|
66
66
|
@invalid_options = []
|
@@ -163,7 +163,7 @@ class Slop
|
|
163
163
|
# # symbols!
|
164
164
|
# opts.to_hash(true) #=> { :name => 'Emily' }
|
165
165
|
# @return [Hash]
|
166
|
-
def to_hash(symbols=
|
166
|
+
def to_hash(symbols=false)
|
167
167
|
@options.to_hash(symbols)
|
168
168
|
end
|
169
169
|
alias :to_h :to_hash
|
@@ -195,7 +195,7 @@ class Slop
|
|
195
195
|
end
|
196
196
|
alias :help :to_s
|
197
197
|
|
198
|
-
private
|
198
|
+
private
|
199
199
|
|
200
200
|
def self.initialize_and_parse(items, delete, options, &block)
|
201
201
|
if items.is_a?(Hash) && options.empty?
|
@@ -322,8 +322,8 @@ private
|
|
322
322
|
end
|
323
323
|
|
324
324
|
long = args.first
|
325
|
-
boolean =
|
326
|
-
if !boolean && long.to_s =~ /\A(
|
325
|
+
boolean = [true, false].include?(long)
|
326
|
+
if !boolean && long.to_s =~ /\A(?:--?)?[a-zA-Z0-9_-]+\z/
|
327
327
|
options.push args.shift.to_s.sub(/\A--?/, '')
|
328
328
|
else
|
329
329
|
options.push nil
|
@@ -331,8 +331,6 @@ private
|
|
331
331
|
|
332
332
|
options.push args.first.respond_to?(:to_sym) ? args.shift : nil
|
333
333
|
options.push args.shift ? true : false # force true/false
|
334
|
-
|
335
|
-
options
|
336
334
|
end
|
337
335
|
|
338
336
|
def raise_if_invalid_options
|
data/lib/slop/option.rb
CHANGED
@@ -91,6 +91,8 @@ class Slop
|
|
91
91
|
case @options[:as].to_s.downcase
|
92
92
|
when 'array'
|
93
93
|
value.split @delimiter, @limit
|
94
|
+
when 'range'
|
95
|
+
value_to_range value
|
94
96
|
when 'string'; value.to_s
|
95
97
|
when 'symbol'; value.to_s.to_sym
|
96
98
|
when 'integer'; value.to_s.to_i
|
@@ -141,5 +143,18 @@ class Slop
|
|
141
143
|
"long_flag=#{@long_flag.inspect} " +
|
142
144
|
"description=#{@description.inspect}>"
|
143
145
|
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def value_to_range(value)
|
150
|
+
case value.to_s
|
151
|
+
when /\A(\d+?)(?:\.\.|-|,)(\d+)\z/
|
152
|
+
Integer($1) .. Integer($2)
|
153
|
+
when /\A(\d+?)\.\.\.(\d+)\z/
|
154
|
+
Integer($1) ... Integer($2)
|
155
|
+
else
|
156
|
+
value
|
157
|
+
end
|
158
|
+
end
|
144
159
|
end
|
145
160
|
end
|
data/test/option_test.rb
CHANGED
@@ -67,6 +67,17 @@ class OptionTest < TestCase
|
|
67
67
|
assert_equal "1.0", option_value(%w/--id 1/, :id, true, :as => Float).to_s
|
68
68
|
end
|
69
69
|
|
70
|
+
test 'ranges' do
|
71
|
+
assert_equal (1..10), option_value(%w/-r 1..10/, :r, true, :as => Range)
|
72
|
+
assert_equal (1..10), option_value(%w/-r 1-10/, :r, true, :as => Range)
|
73
|
+
assert_equal (1..10), option_value(%w/-r 1,10/, :r, true, :as => Range)
|
74
|
+
assert_equal (1...10), option_value(%w/-r 1...10/, :r, true, :as => Range)
|
75
|
+
|
76
|
+
# default back to the string unless a regex is successful
|
77
|
+
# maybe this should raise is Slop#strict?
|
78
|
+
assert_equal "1abc10", option_value(%w/-r 1abc10/, :r, true, :as => Range)
|
79
|
+
end
|
80
|
+
|
70
81
|
test 'printing options' do
|
71
82
|
slop = Slop.new
|
72
83
|
slop.opt :n, :name, 'Your name', true
|
data/test/slop_test.rb
CHANGED
@@ -5,6 +5,14 @@ class SlopTest < TestCase
|
|
5
5
|
Slop.new.send(:clean_options, args)
|
6
6
|
end
|
7
7
|
|
8
|
+
def temp_argv(items)
|
9
|
+
old_argv = ARGV.clone
|
10
|
+
ARGV.replace items
|
11
|
+
yield
|
12
|
+
ensure
|
13
|
+
ARGV.replace old_argv
|
14
|
+
end
|
15
|
+
|
8
16
|
test 'includes Enumerable' do
|
9
17
|
assert Slop.included_modules.include?(Enumerable)
|
10
18
|
end
|
@@ -30,6 +38,12 @@ class SlopTest < TestCase
|
|
30
38
|
slop.each { |option| assert option }
|
31
39
|
end
|
32
40
|
|
41
|
+
test 'defaulting to ARGV' do
|
42
|
+
temp_argv(%w/--name lee/) do
|
43
|
+
assert_equal('lee', Slop.parse { on :name, true }[:name])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
33
47
|
test 'multiple switches with the :multiple_switches flag' do
|
34
48
|
slop = Slop.new :multiple_switches => true, :strict => true
|
35
49
|
%w/a b c/.each { |f| slop.on f }
|
@@ -88,6 +102,9 @@ class SlopTest < TestCase
|
|
88
102
|
|
89
103
|
slop.banner = nil
|
90
104
|
assert_equal "", slop.to_s
|
105
|
+
|
106
|
+
slop = Slop.new "foo bar"
|
107
|
+
assert_equal "foo bar", slop.banner
|
91
108
|
end
|
92
109
|
|
93
110
|
test 'storing long option lengths' do
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: slop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.4.
|
5
|
+
version: 1.4.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Lee Jarvis
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-04-
|
13
|
+
date: 2011-04-14 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|