slop 1.9.1 → 2.0.0
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/CHANGES.md +20 -1
- data/README.md +19 -12
- data/Rakefile +1 -5
- data/lib/slop.rb +260 -19
- data/slop.gemspec +1 -1
- data/test/option_test.rb +9 -0
- data/test/slop_test.rb +4 -4
- metadata +18 -39
- data/lib/slop/option.rb +0 -205
- data/lib/slop/options.rb +0 -49
data/CHANGES.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
2.0.0 (2011-07-07)
|
2
|
+
-----------
|
3
|
+
|
4
|
+
* Deprecations:
|
5
|
+
* Removed `Slop::Options#to_hash` continue using `Slop#to_hash` directly.
|
6
|
+
This method also now returns symbols by default instead of strings. If
|
7
|
+
you want strings use `opts.to_hash(false)`
|
8
|
+
* `:multiple_switches` is now enabled by default, to parse `fbar` as the
|
9
|
+
option `f` with value `bar` you must disable `:multiple_switches`
|
10
|
+
* Removed `Slop::Options#to_help` and merged its contents into `Slop#help`
|
11
|
+
* Removed `lib/slop/options.rb` and merged `Slop::Options` into slop.rb
|
12
|
+
* Removed `lib/slop/option.rb` and merged `Slop::Option` into slop.rb
|
13
|
+
* These changes make Slop much easier to vendor in libraries
|
14
|
+
* `Slop::Option` now inherits from `Struct.new`
|
15
|
+
* Added Slop::Error subclassing from StandardError which all exception
|
16
|
+
classes should inherit from
|
17
|
+
* Added Slop::MissingOptionError and `:required` option to Slop::Option.
|
18
|
+
This exception is raised when a mandatory option is not used
|
19
|
+
|
1
20
|
1.9.1 (2011-06-16)
|
2
21
|
------------------
|
3
22
|
|
@@ -84,4 +103,4 @@
|
|
84
103
|
* Add `Slop#present?` as alias for `Slop#<option>?`
|
85
104
|
* Add `Option#count` for monitoring how many times an option is called
|
86
105
|
* Add `:io` for using a custom IO object when using the `:help` option
|
87
|
-
* Numerous performance tweaks
|
106
|
+
* Numerous performance tweaks
|
data/README.md
CHANGED
@@ -39,7 +39,7 @@ wiki page.
|
|
39
39
|
|
40
40
|
You can also return your options as a Hash
|
41
41
|
|
42
|
-
opts.to_hash #=> {
|
42
|
+
opts.to_hash #=> {:name => 'Lee Jarvis', :verbose => true, :age => nil, :sex => 'male'}
|
43
43
|
|
44
44
|
If you want some pretty output for the user to see your options, you can just
|
45
45
|
send the Slop object to `puts` or use the `help` method.
|
@@ -83,7 +83,7 @@ Parsing
|
|
83
83
|
|
84
84
|
Slop's pretty good at parsing, let's take a look at what it'll extract for you
|
85
85
|
|
86
|
-
Slop.parse do
|
86
|
+
Slop.parse(:multiple_switches => false) do
|
87
87
|
on 's', 'server', true
|
88
88
|
on 'p', 'port', true, :as => :integer
|
89
89
|
on 'username', true, :matches => /[^a-zA-Z]+$/
|
@@ -97,10 +97,10 @@ Now throw some options at it:
|
|
97
97
|
Here's what we'll get back
|
98
98
|
|
99
99
|
{
|
100
|
-
:server=>"ftp://foobar.com",
|
101
|
-
:port=>1234,
|
102
|
-
:username=>"FooBar",
|
103
|
-
:password=>"hello there"
|
100
|
+
:server => "ftp://foobar.com",
|
101
|
+
:port => 1234,
|
102
|
+
:username => "FooBar",
|
103
|
+
:password => "hello there"
|
104
104
|
}
|
105
105
|
|
106
106
|
Events
|
@@ -160,22 +160,29 @@ Short Switches
|
|
160
160
|
--------------
|
161
161
|
|
162
162
|
Want to enable multiple switches at once like rsync does? By default Slop will
|
163
|
-
parse `-
|
164
|
-
|
163
|
+
parse `-abc` as the options `a` `b` and `c` and set their values to true. If
|
164
|
+
you would like to disable this, you can pass `multiple_switches => false` to
|
165
|
+
a new Slop object. In which case Slop will then parse `-fbar` as the option
|
166
|
+
`f` with the argument value `bar`.
|
165
167
|
|
166
|
-
|
168
|
+
Slop.parse do
|
167
169
|
on :a, 'First switch'
|
168
170
|
on :b, 'Second switch'
|
169
171
|
on :c, 'Third switch'
|
170
172
|
end
|
171
173
|
|
172
|
-
opts.parse
|
173
|
-
|
174
174
|
# Using `-ac`
|
175
175
|
opts[:a] #=> true
|
176
176
|
opts[:b] #=> false
|
177
177
|
opts[:c] #=> true
|
178
178
|
|
179
|
+
Slop.parse(:multiple_switches => false) do
|
180
|
+
on :a, 'Some switch', true
|
181
|
+
end
|
182
|
+
|
183
|
+
# Using `ahello`
|
184
|
+
opts[:a] #=> 'hello'
|
185
|
+
|
179
186
|
Lists
|
180
187
|
-----
|
181
188
|
|
@@ -245,4 +252,4 @@ thing in Slop:
|
|
245
252
|
on :a, :age, 'Your age', true, :as => :int
|
246
253
|
end
|
247
254
|
|
248
|
-
opts.to_hash
|
255
|
+
opts.to_hash #=> { :name => 'lee', :age => 105 }
|
data/Rakefile
CHANGED
data/lib/slop.rb
CHANGED
@@ -1,22 +1,240 @@
|
|
1
|
-
require 'slop/options'
|
2
|
-
require 'slop/option'
|
3
|
-
|
4
1
|
class Slop
|
5
2
|
include Enumerable
|
6
3
|
|
4
|
+
# Slops standard Error class. All exception classes should
|
5
|
+
# inherit from this class
|
6
|
+
class Error < StandardError; end
|
7
|
+
|
7
8
|
# Raised when an option expects an argument and none is given
|
8
|
-
class MissingArgumentError <
|
9
|
+
class MissingArgumentError < Error; end
|
10
|
+
|
11
|
+
# Raised when an option is required but not given
|
12
|
+
class MissingOptionError < Error; end
|
9
13
|
|
10
14
|
# Raised when an option specifies the `:match` attribute and this
|
11
15
|
# options argument does not match this regexp
|
12
|
-
class InvalidArgumentError <
|
16
|
+
class InvalidArgumentError < Error; end
|
13
17
|
|
14
18
|
# Raised when the `:strict` option is enabled and an unknown
|
15
19
|
# or unspecified option is used
|
16
|
-
class InvalidOptionError <
|
20
|
+
class InvalidOptionError < Error; end
|
21
|
+
|
22
|
+
# Each option specified in `Slop#opt` creates an instance of this class
|
23
|
+
class Option < Struct.new(:short_flag, :long_flag, :description,
|
24
|
+
:tail, :match, :help, :required, :forced, :count)
|
25
|
+
|
26
|
+
# @param [Slop] slop
|
27
|
+
# @param [String, #to_s] short
|
28
|
+
# @param [String, #to_s] long
|
29
|
+
# @param [String] description
|
30
|
+
# @param [Boolean] argument
|
31
|
+
# @param [Hash] options
|
32
|
+
# @option options [Boolean] :optional
|
33
|
+
# @option options [Boolean] :argument
|
34
|
+
# @option options [Object] :default
|
35
|
+
# @option options [Proc, #call] :callback
|
36
|
+
# @option options [String, #to_s] :delimiter (',')
|
37
|
+
# @option options [Integer] :limit (0)
|
38
|
+
# @option options [Boolean] :tail (false)
|
39
|
+
# @option options [Regexp] :match
|
40
|
+
# @option options [String, #to_s] :unless
|
41
|
+
# @option options [Boolean, String] :help (true)
|
42
|
+
# @option options [Boolean] :required (false)
|
43
|
+
def initialize(slop, short, long, description, argument, options, &blk)
|
44
|
+
@slop = slop
|
45
|
+
|
46
|
+
self.short_flag = short
|
47
|
+
self.long_flag = long
|
48
|
+
self.description = description
|
49
|
+
|
50
|
+
@argument = argument
|
51
|
+
@options = options
|
52
|
+
|
53
|
+
self.tail = @options[:tail]
|
54
|
+
self.match = @options[:match]
|
55
|
+
self.help = @options.fetch(:help, true)
|
56
|
+
self.required = @options[:required]
|
57
|
+
|
58
|
+
@delimiter = @options.fetch(:delimiter, ',')
|
59
|
+
@limit = @options.fetch(:limit, 0)
|
60
|
+
@argument_type = @options[:as].to_s.downcase
|
61
|
+
@argument_value = nil
|
62
|
+
|
63
|
+
self.forced = false
|
64
|
+
self.count = 0
|
65
|
+
|
66
|
+
@callback = blk if block_given?
|
67
|
+
@callback ||= @options[:callback]
|
68
|
+
|
69
|
+
build_longest_flag
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [Boolean] true if this option expects an argument
|
73
|
+
def expects_argument?
|
74
|
+
@argument || @options[:argument] || @options[:optional] == false
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [Boolean] true if this option accepts an optional argument
|
78
|
+
def accepts_optional_argument?
|
79
|
+
@options[:optional]
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [String] either the long or short flag for this option
|
83
|
+
def key
|
84
|
+
long_flag || short_flag
|
85
|
+
end
|
86
|
+
|
87
|
+
# Set this options argument value.
|
88
|
+
#
|
89
|
+
# If this options argument type is expected to be an Array, this
|
90
|
+
# method will split the value and concat elements into the original
|
91
|
+
# argument value
|
92
|
+
#
|
93
|
+
# @param [Object] value The value to set this options argument to
|
94
|
+
def argument_value=(value)
|
95
|
+
if @argument_type == 'array'
|
96
|
+
@argument_value ||= []
|
97
|
+
|
98
|
+
if value.respond_to?(:to_str)
|
99
|
+
@argument_value.concat value.split(@delimiter, @limit)
|
100
|
+
end
|
101
|
+
else
|
102
|
+
@argument_value = value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# @return [Object] the argument value after it's been cast
|
107
|
+
# according to the `:as` option
|
108
|
+
def argument_value
|
109
|
+
return @argument_value if forced
|
110
|
+
value = @argument_value || @options[:default]
|
111
|
+
return if value.nil?
|
112
|
+
|
113
|
+
case @argument_type
|
114
|
+
when 'array'; @argument_value
|
115
|
+
when 'range'; value_to_range value
|
116
|
+
when 'float'; value.to_s.to_f
|
117
|
+
when 'string', 'str'; value.to_s
|
118
|
+
when 'symbol', 'sym'; value.to_s.to_sym
|
119
|
+
when 'integer', 'int'; value.to_s.to_i
|
120
|
+
else
|
121
|
+
value
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Force an argument value, used when the desired argument value
|
126
|
+
# is negative (false or nil)
|
127
|
+
#
|
128
|
+
# @param [Object] value
|
129
|
+
def force_argument_value(value)
|
130
|
+
@argument_value = value
|
131
|
+
self.forced = true
|
132
|
+
end
|
133
|
+
|
134
|
+
# Execute the block or callback object associated with this Option
|
135
|
+
#
|
136
|
+
# @param [Object] The object to be sent to `:call`
|
137
|
+
def call(obj=nil)
|
138
|
+
@callback.call(obj) if @callback.respond_to?(:call)
|
139
|
+
end
|
140
|
+
|
141
|
+
# @param [Array] items The original array of objects passed to `Slop.new`
|
142
|
+
# @return [Boolean] true if this options `:unless` argument exists
|
143
|
+
# inside *items*
|
144
|
+
def omit_exec?(items)
|
145
|
+
string = @options[:unless].to_s.sub(/\A--?/, '')
|
146
|
+
items.any? { |i| i.to_s.sub(/\A--?/, '') == string }
|
147
|
+
end
|
148
|
+
|
149
|
+
# This option in a nice pretty string, including a short flag, long
|
150
|
+
# flag, and description (if they exist).
|
151
|
+
#
|
152
|
+
# @see Slop#help
|
153
|
+
# @return [String]
|
154
|
+
def to_s
|
155
|
+
out = " "
|
156
|
+
out += short_flag ? "-#{short_flag}, " : ' ' * 4
|
157
|
+
|
158
|
+
if long_flag
|
159
|
+
out += "--#{long_flag}"
|
160
|
+
if help.respond_to? :to_str
|
161
|
+
out += " #{help}"
|
162
|
+
size = long_flag.size + help.size + 1
|
163
|
+
else
|
164
|
+
size = long_flag.size
|
165
|
+
end
|
166
|
+
diff = @slop.longest_flag - size
|
167
|
+
out += " " * (diff + 6)
|
168
|
+
else
|
169
|
+
out += " " * (@slop.longest_flag + 8)
|
170
|
+
end
|
171
|
+
|
172
|
+
"#{out}#{description}"
|
173
|
+
end
|
174
|
+
|
175
|
+
# @return [String]
|
176
|
+
def inspect
|
177
|
+
"#<Slop::Option short_flag=#{short_flag.inspect} " +
|
178
|
+
"long_flag=#{long_flag.inspect} argument=#{@argument.inspect} " +
|
179
|
+
"description=#{description.inspect}>"
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def value_to_range(value)
|
185
|
+
case value.to_s
|
186
|
+
when /\A(-?\d+?)(?:\.\.|-|,)(-?\d+)\z/
|
187
|
+
$1.to_i .. $2.to_i
|
188
|
+
when /\A(-?\d+?)\.\.\.(-?\d+)\z/
|
189
|
+
$1.to_i ... $2.to_i
|
190
|
+
when /\A-?\d+\z/
|
191
|
+
value.to_i
|
192
|
+
else
|
193
|
+
value
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def build_longest_flag
|
198
|
+
if long_flag && long_flag.size > @slop.longest_flag
|
199
|
+
@slop.longest_flag = long_flag.size
|
200
|
+
@slop.longest_flag += help.size if help.respond_to? :to_str
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
# Used to hold a list of Option objects. This class inherits from Array
|
207
|
+
# and overwrites `Array#[]` so we can fetch Option objects via their
|
208
|
+
# short or long flags
|
209
|
+
class Options < Array
|
210
|
+
|
211
|
+
# Fetch an Option object. This method overrides Array#[] to provide
|
212
|
+
# a nicer interface for fetching options via their short or long flag.
|
213
|
+
# The reason we don't use a Hash here is because an option cannot be
|
214
|
+
# identified by a single label. Instead this method tests against
|
215
|
+
# a short flag first, followed by a long flag. When passing this
|
216
|
+
# method an Integer, it will work as an Array usually would, fetching
|
217
|
+
# the Slop::Option at this index.
|
218
|
+
#
|
219
|
+
# @param [Object] flag The short/long flag representing the option
|
220
|
+
# @example
|
221
|
+
# opts = Slop.parse { on :v, "Verbose mode" }
|
222
|
+
# opts.options[:v] #=> Option
|
223
|
+
# opts.options[:v].description #=> "Verbose mode"
|
224
|
+
# @return [Option] the option assoiated with this flag
|
225
|
+
def [](flag)
|
226
|
+
if flag.is_a? Integer
|
227
|
+
super
|
228
|
+
else
|
229
|
+
find do |option|
|
230
|
+
[option.short_flag, option.long_flag].include? flag.to_s
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
17
235
|
|
18
236
|
# @return [String] The current version string
|
19
|
-
VERSION = '
|
237
|
+
VERSION = '2.0.0'
|
20
238
|
|
21
239
|
# Parses the items from a CLI format into a friendly object
|
22
240
|
#
|
@@ -107,7 +325,7 @@ class Slop
|
|
107
325
|
#
|
108
326
|
# @option opts [Array] :aliases ([])
|
109
327
|
# * Primary uses by commands to implement command aliases
|
110
|
-
|
328
|
+
#
|
111
329
|
# @option opts [Boolean] :completion (true)
|
112
330
|
# * When true, commands will be auto completed. Ie `foobar` will be
|
113
331
|
# executed simply when `foo` `fo` or `foob` are used
|
@@ -126,7 +344,7 @@ class Slop
|
|
126
344
|
@banner = sloptions[:banner]
|
127
345
|
@strict = sloptions[:strict]
|
128
346
|
@ignore_case = sloptions[:ignore_case]
|
129
|
-
@multiple_switches = sloptions
|
347
|
+
@multiple_switches = sloptions.fetch(:multiple_switches, true)
|
130
348
|
@autocreate = sloptions[:autocreate]
|
131
349
|
@completion = sloptions.fetch(:completion, true)
|
132
350
|
@arguments = sloptions[:arguments]
|
@@ -340,13 +558,18 @@ class Slop
|
|
340
558
|
# Returns the parsed list into a option/value hash
|
341
559
|
#
|
342
560
|
# @example
|
343
|
-
# opts.to_hash #=> {
|
561
|
+
# opts.to_hash #=> { :name => 'Emily' }
|
344
562
|
#
|
345
|
-
# #
|
346
|
-
# opts.to_hash(
|
563
|
+
# # strings!
|
564
|
+
# opts.to_hash(false) #=> { 'name' => 'Emily' }
|
347
565
|
# @return [Hash]
|
348
|
-
def to_hash(symbols=
|
349
|
-
@options.
|
566
|
+
def to_hash(symbols=true)
|
567
|
+
@options.reduce({}) do |hsh, option|
|
568
|
+
key = option.key
|
569
|
+
key = key.to_sym if symbols
|
570
|
+
hsh[key] = option.argument_value
|
571
|
+
hsh
|
572
|
+
end
|
350
573
|
end
|
351
574
|
alias :to_h :to_hash
|
352
575
|
|
@@ -398,8 +621,16 @@ class Slop
|
|
398
621
|
parts << banner if banner
|
399
622
|
parts << summary if summary
|
400
623
|
parts << wrap_and_indent(description, 80, 4) if description
|
401
|
-
|
402
|
-
|
624
|
+
|
625
|
+
if options.size > 0
|
626
|
+
parts << "options:"
|
627
|
+
|
628
|
+
heads = @options.reject(&:tail)
|
629
|
+
tails = @options.select(&:tail)
|
630
|
+
all = (heads + tails).select(&:help)
|
631
|
+
|
632
|
+
parts << all.map(&:to_s).join("\n")
|
633
|
+
end
|
403
634
|
|
404
635
|
parts.join("\n\n")
|
405
636
|
end
|
@@ -463,8 +694,9 @@ class Slop
|
|
463
694
|
next if ignore_all
|
464
695
|
autocreate(flag, index, items) if @autocreate
|
465
696
|
option, argument = extract_option(item, flag)
|
466
|
-
|
467
|
-
|
697
|
+
|
698
|
+
if @multiple_switches && item[/\A-[^-]/] && !option
|
699
|
+
trash << index
|
468
700
|
next
|
469
701
|
end
|
470
702
|
|
@@ -504,6 +736,7 @@ class Slop
|
|
504
736
|
|
505
737
|
items.reject!.with_index { |o, i| trash.include?(i) } if delete
|
506
738
|
raise_if_invalid_options!
|
739
|
+
raise_if_missing_required_options!(items)
|
507
740
|
items
|
508
741
|
end
|
509
742
|
|
@@ -522,6 +755,14 @@ class Slop
|
|
522
755
|
raise InvalidOptionError, message
|
523
756
|
end
|
524
757
|
|
758
|
+
def raise_if_missing_required_options!(items)
|
759
|
+
@options.select(&:required).each do |o|
|
760
|
+
unless items.select {|i| i[/\A--?/] }.any? {|i| i.to_s.sub(/\A--?/, '') == o.key }
|
761
|
+
raise MissingOptionError, "Expected option `#{o.key}` is required"
|
762
|
+
end
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
525
766
|
# if multiple_switches is enabled, this method filters through an items
|
526
767
|
# characters and attempts to find an Option object for each flag.
|
527
768
|
#
|
@@ -669,4 +910,4 @@ class Slop
|
|
669
910
|
options.push @arguments ? true : (args.shift ? true : false)
|
670
911
|
options.push extras
|
671
912
|
end
|
672
|
-
end
|
913
|
+
end
|
data/slop.gemspec
CHANGED
data/test/option_test.rb
CHANGED
@@ -168,4 +168,13 @@ class OptionTest < TestCase
|
|
168
168
|
assert_equal "1", opts[:bar]
|
169
169
|
refute item
|
170
170
|
end
|
171
|
+
|
172
|
+
test 'raises MissingOptionError when an option is :required' do
|
173
|
+
opts = Slop.new do
|
174
|
+
on :foo, :required => true
|
175
|
+
end
|
176
|
+
|
177
|
+
assert_raises(Slop::MissingOptionError, /foo is required/) { opts.parse %w[ --bar ] }
|
178
|
+
assert_raises(Slop::MissingOptionError, /foo is required/) { opts.parse %w[ foo ] }
|
179
|
+
end
|
171
180
|
end
|
data/test/slop_test.rb
CHANGED
@@ -319,7 +319,7 @@ class SlopTest < TestCase
|
|
319
319
|
slop.opt :V, :verbose, :default => false
|
320
320
|
slop.parse %w/--name lee --version/
|
321
321
|
|
322
|
-
assert_equal({'name' => 'lee', 'version' => true, 'verbose' => false}, slop.to_hash)
|
322
|
+
assert_equal({'name' => 'lee', 'version' => true, 'verbose' => false}, slop.to_hash(false))
|
323
323
|
assert_equal({:name => 'lee', :version => true, :verbose => false}, slop.to_hash(true))
|
324
324
|
end
|
325
325
|
|
@@ -375,11 +375,11 @@ class SlopTest < TestCase
|
|
375
375
|
assert_equal 'nelson', strict[:name]
|
376
376
|
end
|
377
377
|
|
378
|
-
test 'short option flag with no space between flag and argument' do
|
379
|
-
slop = Slop.new
|
378
|
+
test 'short option flag with no space between flag and argument, with :multiple_switches => false' do
|
379
|
+
slop = Slop.new :multiple_switches => false
|
380
380
|
slop.opt :p, :password, true
|
381
381
|
slop.opt :s, :shortpass, true
|
382
|
-
slop.parse %w/-
|
382
|
+
slop.parse %w/-pfoo -sbar/
|
383
383
|
|
384
384
|
assert_equal 'foo', slop[:password]
|
385
385
|
assert_equal 'bar', slop[:shortpass]
|
metadata
CHANGED
@@ -1,33 +1,23 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: slop
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 9
|
9
|
-
- 1
|
10
|
-
version: 1.9.1
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Lee Jarvis
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2011-06-16 00:00:00 +01:00
|
12
|
+
date: 2011-07-07 00:00:00.000000000 +01:00
|
19
13
|
default_executable:
|
20
14
|
dependencies: []
|
21
|
-
|
22
15
|
description: A simple DSL for gathering options and parsing the command line
|
23
16
|
email: lee@jarvis.co
|
24
17
|
executables: []
|
25
|
-
|
26
18
|
extensions: []
|
27
|
-
|
28
19
|
extra_rdoc_files: []
|
29
|
-
|
30
|
-
files:
|
20
|
+
files:
|
31
21
|
- .gemtest
|
32
22
|
- .gitignore
|
33
23
|
- .yardopts
|
@@ -36,8 +26,6 @@ files:
|
|
36
26
|
- README.md
|
37
27
|
- Rakefile
|
38
28
|
- lib/slop.rb
|
39
|
-
- lib/slop/option.rb
|
40
|
-
- lib/slop/options.rb
|
41
29
|
- slop.gemspec
|
42
30
|
- test/commands_test.rb
|
43
31
|
- test/helper.rb
|
@@ -46,38 +34,29 @@ files:
|
|
46
34
|
has_rdoc: true
|
47
35
|
homepage: http://github.com/injekt/slop
|
48
36
|
licenses: []
|
49
|
-
|
50
37
|
post_install_message:
|
51
38
|
rdoc_options: []
|
52
|
-
|
53
|
-
require_paths:
|
39
|
+
require_paths:
|
54
40
|
- lib
|
55
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
42
|
none: false
|
57
|
-
requirements:
|
58
|
-
- -
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
|
61
|
-
|
62
|
-
- 0
|
63
|
-
version: "0"
|
64
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
48
|
none: false
|
66
|
-
requirements:
|
67
|
-
- -
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
|
70
|
-
segments:
|
71
|
-
- 0
|
72
|
-
version: "0"
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
73
53
|
requirements: []
|
74
|
-
|
75
54
|
rubyforge_project:
|
76
55
|
rubygems_version: 1.6.2
|
77
56
|
signing_key:
|
78
57
|
specification_version: 3
|
79
58
|
summary: Option gathering made easy
|
80
|
-
test_files:
|
59
|
+
test_files:
|
81
60
|
- test/commands_test.rb
|
82
61
|
- test/helper.rb
|
83
62
|
- test/option_test.rb
|
data/lib/slop/option.rb
DELETED
@@ -1,205 +0,0 @@
|
|
1
|
-
class Slop
|
2
|
-
class Option
|
3
|
-
|
4
|
-
# @return [String, #to_s] The short flag used for this option
|
5
|
-
attr_reader :short_flag
|
6
|
-
|
7
|
-
# @return [String, #to_s] The long flag used for this option
|
8
|
-
attr_reader :long_flag
|
9
|
-
|
10
|
-
# @return [String] This options description
|
11
|
-
attr_reader :description
|
12
|
-
|
13
|
-
# @return [Boolean] True if the option should be grouped at the
|
14
|
-
# tail of the help list
|
15
|
-
attr_reader :tail
|
16
|
-
|
17
|
-
# @return [Regexp] If provided, an options argument **must** match this
|
18
|
-
# regexp, otherwise Slop will raise an InvalidArgumentError
|
19
|
-
attr_reader :match
|
20
|
-
|
21
|
-
# @return [Object] true/false, or an optional help string to append
|
22
|
-
attr_reader :help
|
23
|
-
|
24
|
-
# @return [Boolean] true if this options argument value has been forced
|
25
|
-
attr_accessor :forced
|
26
|
-
|
27
|
-
# @return [Integer] The amount of times this option has been invoked
|
28
|
-
attr_accessor :count
|
29
|
-
|
30
|
-
# @param [Slop] slop
|
31
|
-
# @param [String, #to_s] short
|
32
|
-
# @param [String, #to_s] long
|
33
|
-
# @param [String] description
|
34
|
-
# @param [Boolean] argument
|
35
|
-
# @param [Hash] options
|
36
|
-
# @option options [Boolean] :optional
|
37
|
-
# @option options [Boolean] :argument
|
38
|
-
# @option options [Object] :default
|
39
|
-
# @option options [Proc, #call] :callback
|
40
|
-
# @option options [String, #to_s] :delimiter (',')
|
41
|
-
# @option options [Integer] :limit (0)
|
42
|
-
# @option options [Boolean] :tail (false)
|
43
|
-
# @option options [Regexp] :match
|
44
|
-
# @option options [String, #to_s] :unless
|
45
|
-
# @option options [Boolean, String] :help (true)
|
46
|
-
def initialize(slop, short, long, description, argument, options, &blk)
|
47
|
-
@slop = slop
|
48
|
-
@short_flag = short
|
49
|
-
@long_flag = long
|
50
|
-
@description = description
|
51
|
-
@argument = argument
|
52
|
-
@options = options
|
53
|
-
|
54
|
-
@tail = options[:tail]
|
55
|
-
@match = options[:match]
|
56
|
-
@delimiter = options.fetch(:delimiter, ',')
|
57
|
-
@limit = options.fetch(:limit, 0)
|
58
|
-
@help = options.fetch(:help, true)
|
59
|
-
@argument_type = options[:as].to_s.downcase
|
60
|
-
|
61
|
-
@forced = false
|
62
|
-
@argument_value = nil
|
63
|
-
@count = 0
|
64
|
-
|
65
|
-
@callback = blk if block_given?
|
66
|
-
@callback ||= options[:callback]
|
67
|
-
|
68
|
-
build_longest_flag
|
69
|
-
end
|
70
|
-
|
71
|
-
# @return [Boolean] true if this option expects an argument
|
72
|
-
def expects_argument?
|
73
|
-
@argument || @options[:argument] || @options[:optional] == false
|
74
|
-
end
|
75
|
-
|
76
|
-
# @return [Boolean] true if this option accepts an optional argument
|
77
|
-
def accepts_optional_argument?
|
78
|
-
@options[:optional]
|
79
|
-
end
|
80
|
-
|
81
|
-
# @return [String] either the long or short flag for this option
|
82
|
-
def key
|
83
|
-
@long_flag || @short_flag
|
84
|
-
end
|
85
|
-
|
86
|
-
# Set this options argument value.
|
87
|
-
#
|
88
|
-
# If this options argument type is expected to be an Array, this
|
89
|
-
# method will split the value and concat elements into the original
|
90
|
-
# argument value
|
91
|
-
#
|
92
|
-
# @param [Object] value The value to set this options argument to
|
93
|
-
def argument_value=(value)
|
94
|
-
if @argument_type == 'array'
|
95
|
-
@argument_value ||= []
|
96
|
-
if value.respond_to?(:to_str)
|
97
|
-
@argument_value.concat value.split(@delimiter, @limit)
|
98
|
-
end
|
99
|
-
else
|
100
|
-
@argument_value = value
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# @return [Object] the argument value after it's been cast
|
105
|
-
# according to the `:as` option
|
106
|
-
def argument_value
|
107
|
-
return @argument_value if @forced
|
108
|
-
value = @argument_value || @options[:default]
|
109
|
-
return if value.nil?
|
110
|
-
|
111
|
-
case @argument_type
|
112
|
-
when 'array'; @argument_value
|
113
|
-
when 'range'; value_to_range value
|
114
|
-
when 'float'; value.to_s.to_f
|
115
|
-
when 'string', 'str'; value.to_s
|
116
|
-
when 'symbol', 'sym'; value.to_s.to_sym
|
117
|
-
when 'integer', 'int'; value.to_s.to_i
|
118
|
-
else
|
119
|
-
value
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# Force an argument value, used when the desired argument value
|
124
|
-
# is negative (false or nil)
|
125
|
-
#
|
126
|
-
# @param [Object] value
|
127
|
-
def force_argument_value(value)
|
128
|
-
@argument_value = value
|
129
|
-
@forced = true
|
130
|
-
end
|
131
|
-
|
132
|
-
# Execute the block or callback object associated with this Option
|
133
|
-
#
|
134
|
-
# @param [Object] The object to be sent to `:call`
|
135
|
-
def call(obj=nil)
|
136
|
-
@callback.call(obj) if @callback.respond_to?(:call)
|
137
|
-
end
|
138
|
-
|
139
|
-
# @param [Array] items The original array of objects passed to `Slop.new`
|
140
|
-
# @return [Boolean] true if this options `:unless` argument exists
|
141
|
-
# inside *items*
|
142
|
-
def omit_exec?(items)
|
143
|
-
string = @options[:unless].to_s.sub(/\A--?/, '')
|
144
|
-
items.any? { |i| i.to_s.sub(/\A--?/, '') == string }
|
145
|
-
end
|
146
|
-
|
147
|
-
# This option in a nice pretty string, including a short flag, long
|
148
|
-
# flag, and description (if they exist).
|
149
|
-
#
|
150
|
-
# @see Slop#help
|
151
|
-
# @return [String]
|
152
|
-
def to_s
|
153
|
-
out = " "
|
154
|
-
out += @short_flag ? "-#{@short_flag}, " : ' ' * 4
|
155
|
-
|
156
|
-
if @long_flag
|
157
|
-
out += "--#{@long_flag}"
|
158
|
-
if @help.respond_to? :to_str
|
159
|
-
out += " #{@help}"
|
160
|
-
size = @long_flag.size + @help.size + 1
|
161
|
-
else
|
162
|
-
size = @long_flag.size
|
163
|
-
end
|
164
|
-
diff = @slop.longest_flag - size
|
165
|
-
out += " " * (diff + 6)
|
166
|
-
else
|
167
|
-
out += " " * (@slop.longest_flag + 8)
|
168
|
-
end
|
169
|
-
|
170
|
-
"#{out}#{@description}"
|
171
|
-
end
|
172
|
-
|
173
|
-
# @return [String]
|
174
|
-
def inspect
|
175
|
-
"#<Slop::Option short_flag=#{@short_flag.inspect} " +
|
176
|
-
"long_flag=#{@long_flag.inspect} argument=#{@argument.inspect} " +
|
177
|
-
"description=#{@description.inspect}>"
|
178
|
-
end
|
179
|
-
|
180
|
-
private
|
181
|
-
|
182
|
-
def value_to_range(value)
|
183
|
-
case value.to_s
|
184
|
-
when /\A(-?\d+?)(?:\.\.|-|,)(-?\d+)\z/
|
185
|
-
$1.to_i .. $2.to_i
|
186
|
-
when /\A(-?\d+?)\.\.\.(-?\d+)\z/
|
187
|
-
$1.to_i ... $2.to_i
|
188
|
-
when /\A-?\d+\z/
|
189
|
-
value.to_i
|
190
|
-
else
|
191
|
-
value
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def build_longest_flag
|
196
|
-
if @long_flag && @long_flag.size > @slop.longest_flag
|
197
|
-
if @help.respond_to? :to_str
|
198
|
-
@slop.longest_flag = @long_flag.size + @help.size
|
199
|
-
else
|
200
|
-
@slop.longest_flag = @long_flag.size
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
data/lib/slop/options.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
class Slop
|
2
|
-
class Options < Array
|
3
|
-
|
4
|
-
# @param [Boolean] symbols true to cast hash keys to symbols
|
5
|
-
# @see Slop#to_hash
|
6
|
-
# @return [Hash]
|
7
|
-
def to_hash(symbols)
|
8
|
-
reduce({}) do |hsh, option|
|
9
|
-
key = option.key
|
10
|
-
key = key.to_sym if symbols
|
11
|
-
hsh[key] = option.argument_value
|
12
|
-
hsh
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# Fetch an Option object. This method overrides Array#[] to provide
|
17
|
-
# a nicer interface for fetching options via their short or long flag.
|
18
|
-
# The reason we don't use a Hash here is because an option cannot be
|
19
|
-
# identified by a single label. Instead this method tests against
|
20
|
-
# a short flag first, followed by a long flag. When passing this
|
21
|
-
# method an Integer, it will work as an Array usually would, fetching
|
22
|
-
# the Slop::Option at this index.
|
23
|
-
#
|
24
|
-
# @param [Object] flag The short/long flag representing the option
|
25
|
-
# @example
|
26
|
-
# opts = Slop.parse { on :v, "Verbose mode" }
|
27
|
-
# opts.options[:v] #=> Option
|
28
|
-
# opts.options[:v].description #=> "Verbose mode"
|
29
|
-
# @return [Option] the option assoiated with this flag
|
30
|
-
def [](flag)
|
31
|
-
if flag.is_a? Integer
|
32
|
-
super
|
33
|
-
else
|
34
|
-
find do |option|
|
35
|
-
[option.short_flag, option.long_flag].include? flag.to_s
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# @see Slop#help
|
41
|
-
# @return [String] All options in a pretty help string
|
42
|
-
def to_help
|
43
|
-
heads = reject(&:tail)
|
44
|
-
tails = select(&:tail)
|
45
|
-
all = (heads + tails).select(&:help)
|
46
|
-
all.map(&:to_s).join("\n")
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|