1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
|
Slop
====
Slop is a simple option parser with an easy to remember syntax and friendly API.
Installation
------------
### Rubygems
gem install slop
### GitHub
git clone git://github.com/injekt/slop.git
gem build slop.gemspec
gem install slop-<version>.gem
Usage
-----
# parse assumes ARGV, otherwise you can pass it your own Array
opts = Slop.parse do
on :v, :verbose, 'Enable verbose mode' # boolean value
on :n, :name, 'Your name', true # compulsory argument
on :s, :sex, 'Your sex', :optional => false # the same thing
on :a, :age, 'Your age', :optional => true # optional argument
end
# if ARGV is `-v --name 'lee jarvis' -s male`
opts.verbose? #=> true
opts.name? #=> true
opts[:name] #=> 'lee jarvis'
opts.age? #=> false
opts[:age] #=> nil
You can also return your options as a Hash
opts.to_hash #=> {'name' => 'Lee Jarvis', 'verbose' => true, 'age' => nil, 'sex' => 'male'}
# Symbols
opts.to_hash(true) #=> {:name => 'Lee Jarvis', :verbose => true, :age => nil, :sex => 'male'}
If you don't like the method `on` (because it sounds like the option **expects**
a block), you can use the `opt` or `option` alternatives.
on :v, :verbose
opt :v, :verbose
option :v, :verbose
If you don't like that Slop evaluates your block, or you want slop access
inside of your block without referring to `self`, you can pass a block argument to
`parse`.
Slop.parse do |opts|
opts.on :v, :verbose
opts.on :n, :name, 'Your name', true
end
If you want some pretty output for the user to see your options, you can just
send the Slop object to `puts` or use the `help` method.
puts opts
puts opts.help
Will output something like
-v, --verbose Enable verbose mode
-n, --name Your name
-a, --age Your age
You can also add a banner using the `banner` method
opts = Slop.parse
opts.banner = "Usage: foo.rb [options]"
or
opts = Slop.parse do
banner "Usage: foo.rb [options]"
end
or
opts = Slop.new "Usage: foo.rb [options]"
Helpful Help
------------
Long form:
Slop.parse do
...
on :h, :help, 'Print this help message', :tail => true do
puts help
exit
end
end
Shortcut:
Slop.parse :help => true do
...
end
Parsing
-------
Slop's pretty good at parsing, let's take a look at what it'll extract for you
Slop.parse do
on 's', 'server', true
on 'p', 'port', true, :as => :integer
on 'username', true, :matches => /[^a-zA-Z]+$/
on 'password', true
end
Now throw some options at it:
-s ftp://foobar.com -p1234 --username=FooBar --password 'hello there'
Here's what we'll get back
{
:server=>"ftp://foobar.com",
:port=>1234,
:username=>"FooBar",
:password=>"hello there"
}
Callbacks
---------
If you'd like to trigger an event when an option is used, you can pass a
block to your option. Here's how:
Slop.parse do
on :V, :version, 'Print the version' do
puts 'Version 1.0.0'
exit
end
end
Now when using the `--version` option on the command line, the trigger will
be called and its contents executed.
Yielding Non Options
--------------------
If you pass a block to `Slop#parse`, Slop will yield non-options as
they're found, just like
[OptionParser](http://rubydoc.info/stdlib/optparse/1.9.2/OptionParser:order)
does it.
opts = Slop.new do
on :n, :name, :optional => false
end
opts.parse do |arg|
puts arg
end
# if ARGV is `foo --name Lee bar`
foo
bar
Negative Options
----------------
Slop also allows you to prefix `--no-` to an option which will force the option
to return a false value.
opts = Slop.parse do
on :v, :verbose, :default => true
end
# with no command line options
opts[:verbose] #=> true
# with `--no-verbose`
opts[:verbose] #=> false
opts.verbose? #=> false
Short Switches
--------------
Want to enable multiple switches at once like rsync does? By default Slop will
parse `-abcd` as the option `a` with the argument `bcd`, this can be disabled
by passing the `:multiple_switches` option to a new Slop object.
opts = Slop.new(:strict, :multiple_switches) do
on :a, 'First switch'
on :b, 'Second switch'
on :c, 'Third switch'
end
opts.parse
# Using `-ac`
opts[:a] #=> true
opts[:b] #=> false
opts[:c] #=> true
Lists
-----
You can of course also parse lists into options. Here's how:
opts = Slop.parse do
opt :people, true, :as => Array
end
# ARGV is `--people lee,john,bill`
opts[:people] #=> ['lee', 'john', 'bill']
You can also change both the split delimiter and limit
opts = Slop.parse do
opt :people, true, :as => Array, :delimiter => ':', :limit => 2)
end
# ARGV is `--people lee:injekt:bob`
opts[:people] #=> ["lee", "injekt:bob"]
Ranges
------
What would Slop be if it didn't know what ranges were?
opts = Slop.parse do
opt :r, :range, true, :as => Range
end
# ARGV is `--range 1..10` or 1-10, or 1,10 (yes Slop supports them all)
opts[:range].to_a #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Ugh, Symbols
------------
Fine, don't use them
Slop.parse do
on :n, :name, 'Your name'
on 'n', 'name', 'Your name'
on '-n', '--name', 'Your name'
end
All of these options will do the same thing
Ugh, Blocks
-----------
C'mon man, this is Ruby, GTFO if you don't like blocks.
opts = Slop.new
opts.on :v, :verbose
opts.parse
Smart
-----
Slop is pretty smart when it comes to building your options, for example if you
want your option to have a flag attribute, but no `--option` attribute, you
can do this:
on :n, "Your name"
and Slop will detect a description in place of an option, so you don't have to
do this:
on :n, nil, "Your name", true
You can also try other variations:
on :name, "Your name"
on :n, :name
on :name, true
Strict Mode
-----------
Passing `strict => true` to `Slop.parse` causes it to raise a `Slop::InvalidOptionError`
when an invalid option is found (`false` by default):
Slop.new(:strict => true).parse(%w/--foo/)
# => Slop::InvalidOptionError: Unknown option -- 'foo'
and it handles multiple invalid options with a sprinkling of pluralization:
Slop.new(:strict => true).parse(%w/--foo --bar -z/)
# => Slop::InvalidOptionError: Unknown options -- 'foo', 'bar', 'z'
Significantly, however, Slop will still parse the valid options:
slop = Slop.new(:strict => true, :help => true) do
banner "Usage:\n\t./awesome_sauce [options]\n\nOptions:"
on :n, :name, 'Your name'
end
begin
slop.parse(%w/--foo --bar -z/)
rescue Slop::InvalidOptionError => e
puts "\n#{e.message}\n\n"
puts slop
exit
end
yields:
Unknown options -- 'foo', 'bar', 'z'
Usage:
./awesome_sauce [options]
Options:
-n, --name Your name
-h, --help Print this help message
Commands
--------
Slop allows you to nest more instances of Slop inside of `commands`. These
instances will then be used to parse arguments if they're called upon.
Slop will use the first argument in the list of items passed to `parse` to
check if it is a `command`.
Slop.parse ['foo', '--bar', 'baz']
Slop will look to see if the `foo` command exists, and if it does, it'll pass
the options `['--bar', 'baz']` to the instance of Slop that belongs to `foo`.
Here's how commands might look:
opts = Slop.new do
command :foo do
on :b, :bar, 'something', true
end
command :clean do
on :v, :verbose, do
puts 'Enabled verbose mode for clean'
end
end
# non-command specific options
on :v, :version do
puts 'version 1'
end
end
* Run with `run.rb -v`
* Output: `version 1`
* Run with: `run.rb clean -v`
* Output: `Enabled verbose mode for clean`
Woah woah, why you hating on OptionParser?
------------------------------------------
I'm not, honestly! I love OptionParser. I really do, it's a fantastic library.
So why did I build Slop? Well, I find myself using OptionParser to simply
gather a bunch of key/value options, usually you would do something like this:
require 'optparse'
things = {}
opt = OptionParser.new do |opt|
opt.on('-n', '--name NAME', 'Your name') do |name|
things[:name] = name
end
opt.on('-a', '--age AGE', 'Your age') do |age|
things[:age] = age
end
# you get the point
end
opt.parse
things #=> { :name => 'lee', :age => 105 }
Which is all great and stuff, but it can lead to some repetition, the same
thing in Slop:
require 'slop'
opts = Slop.parse do
on :n, :name, 'Your name', true
on :a, :age, 'Your age', true
end
opts.to_hash(true) #=> { :name => 'lee', :age => 105 }
|