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 CHANGED
@@ -1,3 +1,4 @@
1
+ .rvmrc
1
2
  .yardoc
2
3
  doc
3
4
  *.swp
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
- gem build slop.gemspec
17
- gem install slop-<version>.gem
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
- -v, --verbose Enable verbose mode
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
- Slop.parse do
106
- on :V, :version, 'Print the version' do
107
- puts 'Version 1.0.0'
108
- exit
109
- end
110
- end
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
- on :n, "Your name"
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
- on :n, nil, "Your name", true
188
+ on :n, nil, "Your name", true
150
189
 
151
190
  You can also try other variations:
152
191
 
153
- on :name, "Your name"
154
- on :n, :name
155
- on :name, true
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
- opt :people, true, :as => Array, :delimiter => ':', :limit => 2)
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 < ArgumentError; end
8
- class InvalidArgumentError < ArgumentError; end
9
- class InvalidOptionError < ArgumentError; end
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
- return if value.nil?
118
-
119
- case @options[:as].to_s
120
- when 'Array'
121
- value.split(@options[:delimiter] || ',', @options[:limit] || 0)
122
- when 'String'; value.to_s
123
- when 'Symbol'; value.to_s.to_sym
124
- when 'Integer'; value.to_s.to_i
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
@@ -1,3 +1,3 @@
1
1
  class Slop
2
- VERSION = '1.2.0'
2
+ VERSION = '1.2.1'
3
3
  end
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.0
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-21 00:00:00 +00:00
13
+ date: 2011-03-24 00:00:00 +00:00
14
14
  default_executable:
15
15
  dependencies: []
16
16