slop 1.2.0 → 1.2.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/.gitignore +1 -0
- data/README.md +111 -40
- data/lib/slop.rb +21 -6
- data/lib/slop/option.rb +22 -9
- data/lib/slop/version.rb +1 -1
- data/test/option_test.rb +1 -0
- data/test/slop_test.rb +20 -0
- metadata +2 -2
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -13,8 +13,8 @@ Installation
|
|
13
13
|
### GitHub
|
14
14
|
|
15
15
|
git clone git://github.com/injekt/slop.git
|
16
|
-
|
17
|
-
|
16
|
+
gem build slop.gemspec
|
17
|
+
gem install slop-<version>.gem
|
18
18
|
|
19
19
|
Usage
|
20
20
|
-----
|
@@ -40,23 +40,6 @@ You can also return your options as a Hash
|
|
40
40
|
# Symbols
|
41
41
|
opts.to_hash(true) #=> {:name => 'Lee Jarvis', :verbose => true, :age => nil, :sex => 'male'}
|
42
42
|
|
43
|
-
If you pass a block to `Slop#parse`, Slop will yield non-options as
|
44
|
-
they're found, just like
|
45
|
-
[OptionParser](http://rubydoc.info/stdlib/optparse/1.9.2/OptionParser:order)
|
46
|
-
does it.
|
47
|
-
|
48
|
-
opts = Slop.new do
|
49
|
-
on :n, :name, :optional => false
|
50
|
-
end
|
51
|
-
|
52
|
-
opts.parse do |arg|
|
53
|
-
puts arg
|
54
|
-
end
|
55
|
-
|
56
|
-
# if ARGV is `foo --name Lee bar`
|
57
|
-
foo
|
58
|
-
bar
|
59
|
-
|
60
43
|
If you don't like the method `on` (because it sounds like the option **expects**
|
61
44
|
a block), you can use the `opt` or `option` alternatives.
|
62
45
|
|
@@ -81,7 +64,7 @@ send the Slop object to `puts` or use the `help` method.
|
|
81
64
|
|
82
65
|
Will output something like
|
83
66
|
|
84
|
-
|
67
|
+
-v, --verbose Enable verbose mode
|
85
68
|
-n, --name Your name
|
86
69
|
-a, --age Your age
|
87
70
|
|
@@ -96,22 +79,78 @@ or
|
|
96
79
|
banner "Usage: foo.rb [options]"
|
97
80
|
end
|
98
81
|
|
82
|
+
Helpful Help
|
83
|
+
------------
|
84
|
+
|
85
|
+
Long form:
|
86
|
+
|
87
|
+
Slop.parse do
|
88
|
+
...
|
89
|
+
on :h, :help, 'Print this help message', :tail => true do
|
90
|
+
puts help
|
91
|
+
exit
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
Shortcut:
|
96
|
+
|
97
|
+
Slop.parse :help => true do
|
98
|
+
...
|
99
|
+
end
|
100
|
+
|
99
101
|
Callbacks
|
100
102
|
---------
|
101
103
|
|
102
104
|
If you'd like to trigger an event when an option is used, you can pass a
|
103
105
|
block to your option. Here's how:
|
104
106
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
107
|
+
Slop.parse do
|
108
|
+
on :V, :version, 'Print the version' do
|
109
|
+
puts 'Version 1.0.0'
|
110
|
+
exit
|
111
|
+
end
|
112
|
+
end
|
111
113
|
|
112
114
|
Now when using the `--version` option on the command line, the trigger will
|
113
115
|
be called and its contents executed.
|
114
116
|
|
117
|
+
Yielding Non Options
|
118
|
+
--------------------
|
119
|
+
|
120
|
+
If you pass a block to `Slop#parse`, Slop will yield non-options as
|
121
|
+
they're found, just like
|
122
|
+
[OptionParser](http://rubydoc.info/stdlib/optparse/1.9.2/OptionParser:order)
|
123
|
+
does it.
|
124
|
+
|
125
|
+
opts = Slop.new do
|
126
|
+
on :n, :name, :optional => false
|
127
|
+
end
|
128
|
+
|
129
|
+
opts.parse do |arg|
|
130
|
+
puts arg
|
131
|
+
end
|
132
|
+
|
133
|
+
# if ARGV is `foo --name Lee bar`
|
134
|
+
foo
|
135
|
+
bar
|
136
|
+
|
137
|
+
Negative Options
|
138
|
+
----------------
|
139
|
+
|
140
|
+
Slop also allows you to prefix `--no-` to an option which will force the option
|
141
|
+
to return a false value.
|
142
|
+
|
143
|
+
opts = Slop.parse do
|
144
|
+
on :v, :verbose, :default => true
|
145
|
+
end
|
146
|
+
|
147
|
+
# with no command line options
|
148
|
+
opts[:verbose] #=> true
|
149
|
+
|
150
|
+
# with `--no-verbose`
|
151
|
+
opts[:verbose] #=> false
|
152
|
+
opts.verbose? #=> false
|
153
|
+
|
115
154
|
Ugh, Symbols
|
116
155
|
------------
|
117
156
|
|
@@ -141,18 +180,18 @@ Slop is pretty smart when it comes to building your options, for example if you
|
|
141
180
|
want your option to have a flag attribute, but no `--option` attribute, you
|
142
181
|
can do this:
|
143
182
|
|
144
|
-
|
183
|
+
on :n, "Your name"
|
145
184
|
|
146
185
|
and Slop will detect a description in place of an option, so you don't have to
|
147
186
|
do this:
|
148
187
|
|
149
|
-
|
188
|
+
on :n, nil, "Your name", true
|
150
189
|
|
151
190
|
You can also try other variations:
|
152
191
|
|
153
|
-
|
154
|
-
|
155
|
-
|
192
|
+
on :name, "Your name"
|
193
|
+
on :n, :name
|
194
|
+
on :name, true
|
156
195
|
|
157
196
|
Lists
|
158
197
|
-----
|
@@ -169,12 +208,51 @@ You can of course also parse lists into options. Here's how:
|
|
169
208
|
You can also change both the split delimiter and limit
|
170
209
|
|
171
210
|
opts = Slop.parse do
|
172
|
-
|
211
|
+
opt :people, true, :as => Array, :delimiter => ':', :limit => 2)
|
173
212
|
end
|
174
213
|
|
175
214
|
# ARGV is `--people lee:injekt:bob`
|
176
215
|
opts[:people] #=> ["lee", "injekt:bob"]
|
177
216
|
|
217
|
+
Strict Mode
|
218
|
+
-----------
|
219
|
+
|
220
|
+
Passing `strict => true` to `Slop.parse` causes it to raise a `Slop::InvalidOptionError`
|
221
|
+
when an invalid option is found (`false` by default):
|
222
|
+
|
223
|
+
Slop.new(:strict => true).parse(%w/--foo/)
|
224
|
+
# => Slop::InvalidOptionError: Unknown option -- 'foo'
|
225
|
+
|
226
|
+
and it handles multiple invalid options with a sprinkling of pluralization:
|
227
|
+
|
228
|
+
Slop.new(:strict => true).parse(%w/--foo --bar -z/)
|
229
|
+
# => Slop::InvalidOptionError: Unknown options -- 'foo', 'bar', 'z'
|
230
|
+
|
231
|
+
Significantly, however, Slop will still parse the valid options:
|
232
|
+
|
233
|
+
begin
|
234
|
+
slop = Slop.new(:strict => true, :help => true) do
|
235
|
+
banner "Usage:\n\t./awesome_sauce [options]\n\nOptions:"
|
236
|
+
on :n, :name, 'Your name'
|
237
|
+
end
|
238
|
+
slop.parse(%w/--foo --bar -z/)
|
239
|
+
rescue Slop::InvalidOptionError => e
|
240
|
+
puts "\n#{e.message}\n\n"
|
241
|
+
puts slop
|
242
|
+
exit
|
243
|
+
end
|
244
|
+
|
245
|
+
yields:
|
246
|
+
|
247
|
+
Unknown options -- 'foo', 'bar', 'z'
|
248
|
+
|
249
|
+
Usage:
|
250
|
+
./awesome_sauce [options]
|
251
|
+
|
252
|
+
Options:
|
253
|
+
-n, --name Your name
|
254
|
+
-h, --help Print this help message
|
255
|
+
|
178
256
|
Woah woah, why you hating on OptionParser?
|
179
257
|
------------------------------------------
|
180
258
|
|
@@ -211,11 +289,4 @@ thing in Slop:
|
|
211
289
|
on :a, :age, 'Your age', true
|
212
290
|
end
|
213
291
|
|
214
|
-
things = opts.to_hash
|
215
|
-
|
216
|
-
Contributing
|
217
|
-
------------
|
218
|
-
|
219
|
-
If you'd like to contribute to Slop (it's **really** appreciated) please fork
|
220
|
-
the GitHub repository, create your feature/bugfix branch, add tests, and send
|
221
|
-
me a pull request. I'd be more than happy to look at it.
|
292
|
+
things = opts.to_hash
|
data/lib/slop.rb
CHANGED
@@ -4,9 +4,9 @@ require 'slop/version'
|
|
4
4
|
class Slop
|
5
5
|
include Enumerable
|
6
6
|
|
7
|
-
class MissingArgumentError <
|
8
|
-
class InvalidArgumentError <
|
9
|
-
class InvalidOptionError <
|
7
|
+
class MissingArgumentError < RuntimeError; end
|
8
|
+
class InvalidArgumentError < RuntimeError; end
|
9
|
+
class InvalidOptionError < RuntimeError; end
|
10
10
|
|
11
11
|
# Parses the items from a CLI format into a friendly object.
|
12
12
|
#
|
@@ -35,7 +35,9 @@ class Slop
|
|
35
35
|
initialize_and_parse(items, true, options, &block)
|
36
36
|
end
|
37
37
|
|
38
|
+
# @return [Options]
|
38
39
|
attr_reader :options
|
40
|
+
|
39
41
|
attr_writer :banner
|
40
42
|
attr_accessor :longest_flag
|
41
43
|
|
@@ -48,6 +50,7 @@ class Slop
|
|
48
50
|
@banner = nil
|
49
51
|
@longest_flag = 0
|
50
52
|
@strict = options[:strict]
|
53
|
+
@invalid_options = []
|
51
54
|
|
52
55
|
if block_given?
|
53
56
|
block.arity == 1 ? yield(self) : instance_eval(&block)
|
@@ -210,6 +213,11 @@ private
|
|
210
213
|
if !option && item =~ /^-[^-]/
|
211
214
|
flag, argument = flag.split('', 2)
|
212
215
|
option = @options[flag]
|
216
|
+
elsif !option && item =~ /--no-(.+)$/
|
217
|
+
if option = @options[$1]
|
218
|
+
option.force_argument_value false
|
219
|
+
next
|
220
|
+
end
|
213
221
|
end
|
214
222
|
|
215
223
|
if option
|
@@ -238,6 +246,7 @@ private
|
|
238
246
|
end
|
239
247
|
|
240
248
|
items.delete_if { |item| trash.include? item } if delete
|
249
|
+
raise_if_invalid_options
|
241
250
|
items
|
242
251
|
end
|
243
252
|
|
@@ -258,9 +267,7 @@ private
|
|
258
267
|
end
|
259
268
|
|
260
269
|
def check_invalid_option(item, flag)
|
261
|
-
if item[/^--?/] && @strict
|
262
|
-
raise InvalidOptionError, "Unknown option -- '#{flag}'"
|
263
|
-
end
|
270
|
+
@invalid_options << flag if item[/^--?/] && @strict
|
264
271
|
end
|
265
272
|
|
266
273
|
def clean_options(args)
|
@@ -288,4 +295,12 @@ private
|
|
288
295
|
options
|
289
296
|
end
|
290
297
|
|
298
|
+
def raise_if_invalid_options
|
299
|
+
return if !@strict || @invalid_options.empty?
|
300
|
+
message = "Unknown option"
|
301
|
+
message << 's' if @invalid_options.size > 1
|
302
|
+
message << ' -- ' << @invalid_options.map { |o| "'#{o}'" }.join(', ')
|
303
|
+
raise InvalidOptionError, message
|
304
|
+
end
|
305
|
+
|
291
306
|
end
|
data/lib/slop/option.rb
CHANGED
@@ -80,6 +80,10 @@ class Slop
|
|
80
80
|
@expects_argument = true if options[:optional] == false
|
81
81
|
@tail = options[:tail]
|
82
82
|
@match = options[:match]
|
83
|
+
@forced = false
|
84
|
+
|
85
|
+
@delimiter = options[:delimiter] || ','
|
86
|
+
@limit = options[:limit] || 0
|
83
87
|
|
84
88
|
if @long_flag && @long_flag.size > @slop.longest_flag
|
85
89
|
@slop.longest_flag = @long_flag.size
|
@@ -113,21 +117,30 @@ class Slop
|
|
113
117
|
# @return [Object] the argument value after it's been case
|
114
118
|
# according to the `:as` option
|
115
119
|
def argument_value
|
120
|
+
return @argument_value if @forced
|
116
121
|
value = @argument_value || default
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
when '
|
123
|
-
when '
|
124
|
-
when '
|
125
|
-
when 'Float'; value.to_s.to_f
|
122
|
+
|
123
|
+
case @options[:as].to_s.downcase
|
124
|
+
when 'array'
|
125
|
+
value.split @delimiter, @limit
|
126
|
+
when 'string'; value.to_s
|
127
|
+
when 'symbol'; value.to_s.to_sym
|
128
|
+
when 'integer'; value.to_s.to_i
|
129
|
+
when 'float'; value.to_s.to_f
|
126
130
|
else
|
127
131
|
value
|
128
132
|
end
|
129
133
|
end
|
130
134
|
|
135
|
+
# Force an argument value, used when the desired argument value
|
136
|
+
# is negative (false or nil)
|
137
|
+
#
|
138
|
+
# @param [Object] value
|
139
|
+
def force_argument_value(value)
|
140
|
+
@argument_value = value
|
141
|
+
@forced = true
|
142
|
+
end
|
143
|
+
|
131
144
|
def to_s
|
132
145
|
out = " "
|
133
146
|
out += @short_flag ? "-#{@short_flag}, " : ' ' * 4
|
data/lib/slop/version.rb
CHANGED
data/test/option_test.rb
CHANGED
@@ -62,6 +62,7 @@ class OptionTest < TestCase
|
|
62
62
|
|
63
63
|
test 'casting' do
|
64
64
|
assert_equal :foo, option_value(%w/--name foo/, :name, true, :as => Symbol)
|
65
|
+
assert_equal :foo, option_value(%w/--name foo/, :name, true, :as => :symbol)
|
65
66
|
assert_equal 30, option_value(%w/--age 30/, :age, true, :as => Integer)
|
66
67
|
assert_equal "1.0", option_value(%w/--id 1/, :id, true, :as => Float).to_s
|
67
68
|
end
|
data/test/slop_test.rb
CHANGED
@@ -216,6 +216,14 @@ class SlopTest < TestCase
|
|
216
216
|
assert totallynotstrict.parse %w/--foo/
|
217
217
|
end
|
218
218
|
|
219
|
+
test 'strict mode parses options before raising Slop::InvalidOptionError' do
|
220
|
+
strict = Slop.new :strict => true
|
221
|
+
strict.opt :n, :name, true
|
222
|
+
|
223
|
+
assert_raises(Slop::InvalidOptionError, /--foo/) { strict.parse %w/--foo --name nelson/ }
|
224
|
+
assert_equal 'nelson', strict[:name]
|
225
|
+
end
|
226
|
+
|
219
227
|
test 'short option flag with no space between flag and argument' do
|
220
228
|
slop = Slop.new
|
221
229
|
slop.opt :p, :password, true
|
@@ -225,4 +233,16 @@ class SlopTest < TestCase
|
|
225
233
|
assert_equal 'foo', slop[:password]
|
226
234
|
assert_equal 'bar', slop[:shortpass]
|
227
235
|
end
|
236
|
+
|
237
|
+
test 'prefixing --no- onto options for a negative result' do
|
238
|
+
slop = Slop.new
|
239
|
+
slop.opt :d, :debug
|
240
|
+
slop.opt :v, :verbose, :default => true
|
241
|
+
slop.parse %w/--no-debug --no-verbose --no-nothing/
|
242
|
+
|
243
|
+
refute slop.verbose?
|
244
|
+
refute slop.debug?
|
245
|
+
refute slop[:verbose]
|
246
|
+
refute slop[:debug]
|
247
|
+
end
|
228
248
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: slop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.2.
|
5
|
+
version: 1.2.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-03-
|
13
|
+
date: 2011-03-24 00:00:00 +00:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|