slop 1.4.0 → 1.4.1
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/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
|
|