slop 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.yardopts CHANGED
@@ -3,3 +3,4 @@
3
3
  --title "Slop - Option gathering made easy"
4
4
  lib/**/*.rb
5
5
  --no-private
6
+ --main README.md
data/README.md CHANGED
@@ -103,12 +103,12 @@ Parsing
103
103
 
104
104
  Slop's pretty good at parsing, let's take a look at what it'll extract for you
105
105
 
106
- Slop.parse do
107
- on 's', 'server', true
108
- on 'p', 'port', true, :as => :integer
109
- on 'username', true, :matches => /[^a-zA-Z]+$/
110
- on 'password', true
111
- end
106
+ Slop.parse do
107
+ on 's', 'server', true
108
+ on 'p', 'port', true, :as => :integer
109
+ on 'username', true, :matches => /[^a-zA-Z]+$/
110
+ on 'password', true
111
+ end
112
112
 
113
113
  Now throw some options at it:
114
114
 
@@ -129,12 +129,12 @@ Callbacks
129
129
  If you'd like to trigger an event when an option is used, you can pass a
130
130
  block to your option. Here's how:
131
131
 
132
- Slop.parse do
133
- on :V, :version, 'Print the version' do
134
- puts 'Version 1.0.0'
135
- exit
136
- end
137
- end
132
+ Slop.parse do
133
+ on :V, :version, 'Print the version' do
134
+ puts 'Version 1.0.0'
135
+ exit
136
+ end
137
+ end
138
138
 
139
139
  Now when using the `--version` option on the command line, the trigger will
140
140
  be called and its contents executed.
@@ -176,6 +176,26 @@ to return a false value.
176
176
  opts[:verbose] #=> false
177
177
  opts.verbose? #=> false
178
178
 
179
+ Short Switches
180
+ --------------
181
+
182
+ Want to enable multiple switches at once like rsync does? By default Slop will
183
+ parse `-abcd` as the option `a` with the argument `bcd`, this can be disabled
184
+ by passing the `:multiple_switches` option to a new Slop object.
185
+
186
+ opts = Slop.new(:strict, :multiple_switches) do
187
+ on :a, 'First switch'
188
+ on :b, 'Second switch'
189
+ on :c, 'Third switch'
190
+ end
191
+
192
+ opts.parse
193
+
194
+ # Using `-ac`
195
+ opts[:a] #=> true
196
+ opts[:b] #=> false
197
+ opts[:c] #=> true
198
+
179
199
  Ugh, Symbols
180
200
  ------------
181
201
 
@@ -233,7 +253,7 @@ You can of course also parse lists into options. Here's how:
233
253
  You can also change both the split delimiter and limit
234
254
 
235
255
  opts = Slop.parse do
236
- opt :people, true, :as => Array, :delimiter => ':', :limit => 2)
256
+ opt :people, true, :as => Array, :delimiter => ':', :limit => 2)
237
257
  end
238
258
 
239
259
  # ARGV is `--people lee:injekt:bob`
@@ -260,8 +280,8 @@ Significantly, however, Slop will still parse the valid options:
260
280
  on :n, :name, 'Your name'
261
281
  end
262
282
 
263
- begin
264
- slop.parse(%w/--foo --bar -z/)
283
+ begin
284
+ slop.parse(%w/--foo --bar -z/)
265
285
  rescue Slop::InvalidOptionError => e
266
286
  puts "\n#{e.message}\n\n"
267
287
  puts slop
data/lib/slop/option.rb CHANGED
@@ -1,59 +1,28 @@
1
1
  class Slop
2
- class Options < Array
3
-
4
- # @param [Boolean] symbols true to cast hash keys to symbols
5
- # @return [Hash]
6
- def to_hash(symbols)
7
- out = {}
8
- each do |option|
9
- key = option.key
10
- key = key.to_sym if symbols
11
- out[key] = option.argument_value
12
- end
13
- out
14
- end
15
-
16
- # @param [Object] flag
17
- # @return [Option] the option assoiated with this flag
18
- def [](flag)
19
- item = flag.to_s
20
- if item =~ /\A\d+\z/
21
- slice item.to_i
22
- else
23
- find do |option|
24
- option.short_flag == item || option.long_flag == item
25
- end
26
- end
27
- end
28
-
29
- # @return [String]
30
- def to_help
31
- heads = reject {|x| x.tail }
32
- tails = select {|x| x.tail }
33
- (heads + tails).map(&:to_s).join("\n")
34
- end
35
- end
36
-
37
2
  class Option
38
3
 
39
- # @return [String, #to_s]
4
+ # @return [String, #to_s] The short flag used for this option
40
5
  attr_reader :short_flag
41
6
 
42
- # @return [String, #to_s]
7
+ # @return [String, #to_s] The long flag used for this option
43
8
  attr_reader :long_flag
44
9
 
45
- # @return [String]
10
+ # @return [String] This options description
46
11
  attr_reader :description
47
12
 
48
- # @return [Proc, #call]
13
+ # @return [Proc, #call] The object to execute when this option is used
49
14
  attr_reader :callback
50
15
 
51
- # @return [Boolean]
16
+ # @return [Boolean] True if the option should be grouped at the
17
+ # tail of the help list
52
18
  attr_reader :tail
53
19
 
54
- # @return [Regex]
20
+ # @return [Regexp] If provided, an options argument **must** match this
21
+ # regexp, otherwise Slop will raise an InvalidArgumentError
55
22
  attr_reader :match
56
23
 
24
+ # @overload argument_value=(value)
25
+ # Set this options argument value
57
26
  attr_writer :argument_value
58
27
 
59
28
  # @param [Slop] slop
@@ -66,9 +35,9 @@ class Slop
66
35
  # @option options [Boolean] :argument
67
36
  # @option options [Object] :default
68
37
  # @option options [Proc, #call] :callback
69
- # @option options [String, #to_s] :delimiter
70
- # @option options [Integer] :limit
71
- # @option options [Boolean] :tail
38
+ # @option options [String, #to_s] :delimiter (',')
39
+ # @option options [Integer] :limit (0)
40
+ # @option options [Boolean] :tail (false)
72
41
  # @option options [Regexp] :match
73
42
  def initialize(slop, short, long, description, argument, options={}, &blk)
74
43
  @slop = slop
@@ -102,7 +71,7 @@ class Slop
102
71
  @expects_argument || @options[:argument]
103
72
  end
104
73
 
105
- # @return [Boolean] true if this option expects an optional argument
74
+ # @return [Boolean] true if this option accepts an optional argument
106
75
  def accepts_optional_argument?
107
76
  @options[:optional]
108
77
  end
@@ -140,10 +109,15 @@ class Slop
140
109
  @forced = true
141
110
  end
142
111
 
112
+ # @return [Boolean] true if this argument value has been forced
143
113
  def forced?
144
114
  @forced
145
115
  end
146
116
 
117
+ # This option in a nice pretty string, including a short flag, long
118
+ # flag, and description (if they exist).
119
+ # @see Slop#help
120
+ # @return [String]
147
121
  def to_s
148
122
  out = " "
149
123
  out += @short_flag ? "-#{@short_flag}, " : ' ' * 4
@@ -161,6 +135,7 @@ class Slop
161
135
  "#{out}#{@description}"
162
136
  end
163
137
 
138
+ # @return [String]
164
139
  def inspect
165
140
  "#<Slop::Option short_flag=#{@short_flag.inspect} " +
166
141
  "long_flag=#{@long_flag.inspect} " +
@@ -0,0 +1,37 @@
1
+ class Slop
2
+ class Options < Array
3
+
4
+ # @param [Boolean] symbols true to cast hash keys to symbols
5
+ # @return [Hash]
6
+ def to_hash(symbols)
7
+ out = {}
8
+ each do |option|
9
+ key = option.key
10
+ key = key.to_sym if symbols
11
+ out[key] = option.argument_value
12
+ end
13
+ out
14
+ end
15
+
16
+ # @param [Object] flag The short/long flag representing the option
17
+ # @return [Option] the option assoiated with this flag
18
+ def [](flag)
19
+ item = flag.to_s
20
+ if item =~ /\A\d+\z/
21
+ slice item.to_i
22
+ else
23
+ find do |option|
24
+ option.short_flag == item || option.long_flag == item
25
+ end
26
+ end
27
+ end
28
+
29
+ # @see Slop#help
30
+ # @return [String] All options in a pretty help string
31
+ def to_help
32
+ heads = reject {|x| x.tail }
33
+ tails = select {|x| x.tail }
34
+ (heads + tails).map(&:to_s).join("\n")
35
+ end
36
+ end
37
+ end
data/lib/slop.rb CHANGED
@@ -1,13 +1,23 @@
1
+ require 'slop/options'
1
2
  require 'slop/option'
2
- require 'slop/version'
3
3
 
4
4
  class Slop
5
5
  include Enumerable
6
6
 
7
+ # Raised when an option expects an argument and none is given
7
8
  class MissingArgumentError < RuntimeError; end
9
+
10
+ # Raised when an option specifies the `:match` attribute and this
11
+ # options argument does not match this regexp
8
12
  class InvalidArgumentError < RuntimeError; end
13
+
14
+ # Raised when the `:strict` option is enabled and an unknown
15
+ # or unspecified option is used
9
16
  class InvalidOptionError < RuntimeError; end
10
17
 
18
+ # @return [String] The current version string
19
+ VERSION = '1.4.0'
20
+
11
21
  # Parses the items from a CLI format into a friendly object.
12
22
  #
13
23
  # @param [Array] items Items to parse into options.
@@ -38,21 +48,29 @@ class Slop
38
48
  attr_accessor :longest_flag
39
49
 
40
50
  # @param [Hash] options
41
- # @option options [Boolean] :help Automatically add the `help` option
42
- # @option options [Boolean] :strict Strict mode raises when a non listed
51
+ # @option opts [Boolean] :help Automatically add the `help` option
52
+ # @option opts [Boolean] :strict Strict mode raises when a non listed
43
53
  # option is found, false by default
44
- def initialize(options={}, &block)
54
+ # @option opts [Boolean] :multiple_switches Allows `-abc` to be processed
55
+ # as the options 'a', 'b', 'c' and will force their argument values to
56
+ # true. By default Slop with parse this as 'a' with the argument 'bc'
57
+ def initialize(*opts, &block)
58
+ sloptions = {}
59
+ sloptions.merge! opts.pop if opts.last.is_a? Hash
60
+ opts.each { |o| sloptions[o] = true }
61
+
45
62
  @options = Options.new
46
63
  @banner = nil
47
64
  @longest_flag = 0
48
- @strict = options[:strict]
65
+ @strict = sloptions[:strict]
49
66
  @invalid_options = []
67
+ @multiple_switches = sloptions[:multiple_switches]
50
68
 
51
69
  if block_given?
52
70
  block.arity == 1 ? yield(self) : instance_eval(&block)
53
71
  end
54
72
 
55
- if options[:help]
73
+ if sloptions[:help]
56
74
  on :h, :help, 'Print this help message', :tail => true do
57
75
  puts help
58
76
  exit
@@ -201,8 +219,13 @@ private
201
219
  unless option
202
220
  case item
203
221
  when /\A-[^-]/
204
- flag, argument = flag.split('', 2)
205
- option = @options[flag]
222
+ if @multiple_switches
223
+ enable_multiple_switches(item)
224
+ next
225
+ else
226
+ flag, argument = flag.split('', 2)
227
+ option = @options[flag]
228
+ end
206
229
  when /\A--([^=]+)=(.+)\z/
207
230
  option = @options[$1]
208
231
  argument = $2
@@ -270,6 +293,23 @@ private
270
293
  @invalid_options << flag if item[/\A--?/] && @strict
271
294
  end
272
295
 
296
+ def enable_multiple_switches(item)
297
+ item[1..-1].split('').each do |switch|
298
+ if option = @options[switch]
299
+ if option.expects_argument?
300
+ raise MissingArgumentError,
301
+ "'-#{switch}' expects an argument, used in multiple_switch context"
302
+ else
303
+ option.argument_value = true
304
+ end
305
+ else
306
+ if @strict
307
+ raise InvalidOptionError, "Unknown option '-#{switch}'"
308
+ end
309
+ end
310
+ end
311
+ end
312
+
273
313
  def clean_options(args)
274
314
  options = []
275
315
 
data/slop.gemspec CHANGED
@@ -1,5 +1,5 @@
1
1
  $:.push File.expand_path('../lib', __FILE__)
2
- require 'slop/version'
2
+ require 'slop'
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'slop'
data/test/slop_test.rb CHANGED
@@ -5,14 +5,18 @@ class SlopTest < TestCase
5
5
  Slop.new.send(:clean_options, args)
6
6
  end
7
7
 
8
- def parse(items, &block)
9
- Slop.parse(items, &block)
10
- end
11
-
12
8
  test 'includes Enumerable' do
13
9
  assert Slop.included_modules.include?(Enumerable)
14
10
  end
15
11
 
12
+ test 'new accepts a hash or array of symbols' do
13
+ slop = Slop.new :strict, :multiple_switches => true
14
+
15
+ [ :@multiple_switches, :@strict ].each do |var|
16
+ assert slop.instance_variable_get var
17
+ end
18
+ end
19
+
16
20
  test 'parse returns a Slop object' do
17
21
  slop = Slop.parse([])
18
22
  assert_kind_of Slop, slop
@@ -26,6 +30,21 @@ class SlopTest < TestCase
26
30
  slop.each { |option| assert option }
27
31
  end
28
32
 
33
+ test 'multiple switches with the :multiple_switches flag' do
34
+ slop = Slop.new :multiple_switches => true, :strict => true
35
+ %w/a b c/.each { |f| slop.on f }
36
+ slop.on :z, true
37
+ slop.parse %w/-abc/
38
+
39
+ %w/a b c/.each do |flag|
40
+ assert slop[flag]
41
+ assert slop.send(flag + '?')
42
+ end
43
+
44
+ assert_raises(Slop::InvalidOptionError, /d/) { slop.parse %w/-abcd/ }
45
+ assert_raises(Slop::MissingArgumentError, /z/) { slop.parse %w/-abcz/ }
46
+ end
47
+
29
48
  test 'passing a block' do
30
49
  assert Slop.new {}
31
50
  slop = nil
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: slop
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.3.1
5
+ version: 1.4.0
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-30 00:00:00 +01:00
13
+ date: 2011-04-03 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -31,7 +31,7 @@ files:
31
31
  - Rakefile
32
32
  - lib/slop.rb
33
33
  - lib/slop/option.rb
34
- - lib/slop/version.rb
34
+ - lib/slop/options.rb
35
35
  - slop.gemspec
36
36
  - test/helper.rb
37
37
  - test/option_test.rb
data/lib/slop/version.rb DELETED
@@ -1,3 +0,0 @@
1
- class Slop
2
- VERSION = '1.3.1'
3
- end