slop 1.5.3 → 1.5.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -2
- data/Rakefile +2 -5
- data/lib/slop.rb +29 -13
- data/lib/slop/option.rb +25 -20
- data/lib/slop/options.rb +7 -8
- data/slop.gemspec +2 -5
- data/test/commands_test.rb +1 -1
- data/test/helper.rb +12 -0
- data/test/option_test.rb +10 -2
- data/test/slop_test.rb +18 -3
- metadata +2 -2
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
task :test do
|
2
|
-
|
3
|
-
require
|
4
|
-
require 'minitest/autorun'
|
5
|
-
begin; require 'turn'; rescue LoadError; end
|
6
|
-
Dir.glob("test/**/*_test.rb").each { |test| require "./#{test}" }
|
2
|
+
$:.unshift './test'
|
3
|
+
Dir.glob("test/*_test.rb").each { |test| require "./#{test}" }
|
7
4
|
end
|
8
5
|
|
9
6
|
task :default => :test
|
data/lib/slop.rb
CHANGED
@@ -16,7 +16,7 @@ class Slop
|
|
16
16
|
class InvalidOptionError < RuntimeError; end
|
17
17
|
|
18
18
|
# @return [String] The current version string
|
19
|
-
VERSION = '1.5.
|
19
|
+
VERSION = '1.5.4'
|
20
20
|
|
21
21
|
# Parses the items from a CLI format into a friendly object.
|
22
22
|
#
|
@@ -72,7 +72,7 @@ class Slop
|
|
72
72
|
def initialize(*opts, &block)
|
73
73
|
sloptions = {}
|
74
74
|
sloptions.merge! opts.pop if opts.last.is_a? Hash
|
75
|
-
|
75
|
+
sloptions[:banner] = opts.shift if opts[0].respond_to?(:to_str)
|
76
76
|
opts.each { |o| sloptions[o] = true }
|
77
77
|
|
78
78
|
@options = Options.new
|
@@ -81,7 +81,7 @@ class Slop
|
|
81
81
|
@longest_flag = 0
|
82
82
|
@invalid_options = []
|
83
83
|
|
84
|
-
@banner
|
84
|
+
@banner = sloptions[:banner]
|
85
85
|
@strict = sloptions[:strict]
|
86
86
|
@multiple_switches = sloptions[:multiple_switches]
|
87
87
|
@on_empty = sloptions[:on_empty]
|
@@ -109,7 +109,7 @@ class Slop
|
|
109
109
|
# opts = Slop.parse do
|
110
110
|
# banner "Usage - ruby foo.rb [arguments]"
|
111
111
|
# end
|
112
|
-
# @return [String]
|
112
|
+
# @return [String] The current banner.
|
113
113
|
def banner(text=nil)
|
114
114
|
@banner = text if text
|
115
115
|
@banner
|
@@ -134,16 +134,17 @@ class Slop
|
|
134
134
|
@options.each(&block)
|
135
135
|
end
|
136
136
|
|
137
|
-
# Return the value of an option via the subscript operator.
|
138
|
-
#
|
139
137
|
# @param [Symbol] key Option symbol.
|
140
138
|
# @example
|
141
139
|
# opts[:name] #=> "Emily"
|
142
|
-
#
|
140
|
+
# opts.get(:name) #=> "Emily"
|
141
|
+
# @return [Object] Returns the value associated with that option. If an
|
142
|
+
# option doesn't exist, a command will instead be searched for
|
143
143
|
def [](key)
|
144
144
|
option = @options[key]
|
145
145
|
option ? option.argument_value : @commands[key]
|
146
146
|
end
|
147
|
+
alias :get :[]
|
147
148
|
|
148
149
|
# Specify an option with a short or long version, description and type.
|
149
150
|
#
|
@@ -245,7 +246,16 @@ class Slop
|
|
245
246
|
# @return [Boolean] Whether the desired option was specified.
|
246
247
|
def method_missing(meth, *args, &block)
|
247
248
|
super unless meth.to_s =~ /\?\z/
|
248
|
-
|
249
|
+
present? meth.to_s.chomp '?'
|
250
|
+
end
|
251
|
+
|
252
|
+
# Check if an option is specified in the parsed list. Does the same as
|
253
|
+
# Slop#option? but a convenience method for unacceptable method names.
|
254
|
+
#
|
255
|
+
# @param [Object] The object name to check
|
256
|
+
# @return [Boolean] true if this option is present
|
257
|
+
def present?(option_name)
|
258
|
+
!!get(option_name)
|
249
259
|
end
|
250
260
|
|
251
261
|
# Returns the banner followed by available options listed on the next line.
|
@@ -263,6 +273,11 @@ class Slop
|
|
263
273
|
end
|
264
274
|
alias :help :to_s
|
265
275
|
|
276
|
+
def inspect
|
277
|
+
"#<Slop config_options=#{@sloptions.inspect}\n " +
|
278
|
+
options.map(&:inspect).join("\n ") + "\n>"
|
279
|
+
end
|
280
|
+
|
266
281
|
private
|
267
282
|
|
268
283
|
class << self
|
@@ -315,14 +330,15 @@ class Slop
|
|
315
330
|
end
|
316
331
|
|
317
332
|
if option
|
318
|
-
|
319
|
-
|
333
|
+
option.count += 1
|
334
|
+
trash << index
|
335
|
+
next if option.forced
|
320
336
|
option.argument_value = true
|
321
337
|
|
322
338
|
if option.expects_argument? || option.accepts_optional_argument?
|
323
339
|
argument ||= items.at(index + 1)
|
324
340
|
check_valid_argument!(option, argument)
|
325
|
-
trash <<
|
341
|
+
trash << index + 1
|
326
342
|
|
327
343
|
if argument
|
328
344
|
check_matching_argument!(option, argument)
|
@@ -337,11 +353,11 @@ class Slop
|
|
337
353
|
end
|
338
354
|
else
|
339
355
|
check_invalid_option!(item, flag)
|
340
|
-
block.call(item) if block_given? && !trash.include?(
|
356
|
+
block.call(item) if block_given? && !trash.include?(index)
|
341
357
|
end
|
342
358
|
end
|
343
359
|
|
344
|
-
items.
|
360
|
+
items.reject!.with_index { |o, i| trash.include?(i) } if delete
|
345
361
|
raise_if_invalid_options!
|
346
362
|
items
|
347
363
|
end
|
data/lib/slop/option.rb
CHANGED
@@ -24,11 +24,17 @@ class Slop
|
|
24
24
|
# @return [Object] true/false, or an optional help string to append
|
25
25
|
attr_reader :help
|
26
26
|
|
27
|
+
# @return [Boolean] true if this options argument value has been forced
|
28
|
+
attr_reader :forced
|
29
|
+
|
27
30
|
# @overload argument_value=(value)
|
28
31
|
# Set this options argument value
|
29
32
|
# @param [Object] value The value you'd like applied to this option
|
30
33
|
attr_writer :argument_value
|
31
34
|
|
35
|
+
# @return [Integer] The amount of times this option has been invoked
|
36
|
+
attr_accessor :count
|
37
|
+
|
32
38
|
# @param [Slop] slop
|
33
39
|
# @param [String, #to_s] short
|
34
40
|
# @param [String, #to_s] long
|
@@ -56,26 +62,19 @@ class Slop
|
|
56
62
|
|
57
63
|
@tail = options[:tail]
|
58
64
|
@match = options[:match]
|
65
|
+
@delimiter = options[:delimiter] || ','
|
66
|
+
@limit = options[:limit] || 0
|
59
67
|
@help = options[:help]
|
60
68
|
@help = true if @help.nil?
|
61
69
|
|
62
70
|
@forced = false
|
63
71
|
@argument_value = nil
|
64
|
-
|
65
|
-
@delimiter = options[:delimiter] || ','
|
66
|
-
@limit = options[:limit] || 0
|
67
|
-
|
68
|
-
if @long_flag && @long_flag.size > @slop.longest_flag
|
69
|
-
if @help.respond_to? :to_str
|
70
|
-
size = @long_flag.size + @help.size
|
71
|
-
else
|
72
|
-
size = @long_flag.size
|
73
|
-
end
|
74
|
-
@slop.longest_flag = size
|
75
|
-
end
|
72
|
+
@count = 0
|
76
73
|
|
77
74
|
@callback = blk if block_given?
|
78
75
|
@callback ||= options[:callback]
|
76
|
+
|
77
|
+
build_longest_flag
|
79
78
|
end
|
80
79
|
|
81
80
|
# @return [Boolean] true if this option expects an argument
|
@@ -105,9 +104,9 @@ class Slop
|
|
105
104
|
value.split @delimiter, @limit
|
106
105
|
when 'range'
|
107
106
|
value_to_range value
|
108
|
-
when 'string'; value.to_s
|
109
|
-
when 'symbol'; value.to_s.to_sym
|
110
|
-
when 'integer'; value.to_s.to_i
|
107
|
+
when 'string', 'str'; value.to_s
|
108
|
+
when 'symbol', 'sym'; value.to_s.to_sym
|
109
|
+
when 'integer', 'int'; value.to_s.to_i
|
111
110
|
when 'float'; value.to_s.to_f
|
112
111
|
else
|
113
112
|
value
|
@@ -123,11 +122,6 @@ class Slop
|
|
123
122
|
@forced = true
|
124
123
|
end
|
125
124
|
|
126
|
-
# @return [Boolean] true if this argument value has been forced
|
127
|
-
def forced?
|
128
|
-
@forced
|
129
|
-
end
|
130
|
-
|
131
125
|
# This option in a nice pretty string, including a short flag, long
|
132
126
|
# flag, and description (if they exist).
|
133
127
|
# @see Slop#help
|
@@ -176,5 +170,16 @@ class Slop
|
|
176
170
|
value
|
177
171
|
end
|
178
172
|
end
|
173
|
+
|
174
|
+
def build_longest_flag
|
175
|
+
if @long_flag && @long_flag.size > @slop.longest_flag
|
176
|
+
if @help.respond_to? :to_str
|
177
|
+
size = @long_flag.size + @help.size
|
178
|
+
else
|
179
|
+
size = @long_flag.size
|
180
|
+
end
|
181
|
+
@slop.longest_flag = size
|
182
|
+
end
|
183
|
+
end
|
179
184
|
end
|
180
185
|
end
|
data/lib/slop/options.rb
CHANGED
@@ -4,22 +4,21 @@ class Slop
|
|
4
4
|
# @param [Boolean] symbols true to cast hash keys to symbols
|
5
5
|
# @return [Hash]
|
6
6
|
def to_hash(symbols)
|
7
|
-
|
8
|
-
each do |option|
|
7
|
+
reduce({}) do |hsh, option|
|
9
8
|
key = option.key
|
10
9
|
key = key.to_sym if symbols
|
11
|
-
|
10
|
+
hsh[key] = option.argument_value
|
11
|
+
hsh
|
12
12
|
end
|
13
|
-
out
|
14
13
|
end
|
15
14
|
|
16
15
|
# @param [Object] flag The short/long flag representing the option
|
17
16
|
# @return [Option] the option assoiated with this flag
|
18
17
|
def [](flag)
|
19
|
-
item = flag.to_s
|
20
18
|
if flag.is_a?(Integer)
|
21
19
|
slice flag
|
22
20
|
else
|
21
|
+
item = flag.to_s
|
23
22
|
find do |option|
|
24
23
|
option.short_flag == item || option.long_flag == item
|
25
24
|
end
|
@@ -29,9 +28,9 @@ class Slop
|
|
29
28
|
# @see Slop#help
|
30
29
|
# @return [String] All options in a pretty help string
|
31
30
|
def to_help
|
32
|
-
heads = reject
|
33
|
-
tails = select
|
34
|
-
all = (heads + tails).
|
31
|
+
heads = reject(&:tail)
|
32
|
+
tails = select(&:tail)
|
33
|
+
all = (heads + tails).select(&:help)
|
35
34
|
all.map(&:to_s).join("\n")
|
36
35
|
end
|
37
36
|
end
|
data/slop.gemspec
CHANGED
@@ -4,14 +4,11 @@ require 'slop'
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'slop'
|
6
6
|
s.version = Slop::VERSION
|
7
|
-
s.platform = Gem::Platform::RUBY
|
8
7
|
s.summary = 'Option gathering made easy'
|
9
8
|
s.description = 'A simple DSL for gathering options and parsing the command line'
|
10
9
|
s.author = 'Lee Jarvis'
|
11
10
|
s.email = 'lee@jarvis.co'
|
12
11
|
s.homepage = 'http://github.com/injekt/slop'
|
13
|
-
|
14
|
-
s.
|
15
|
-
s.test_files = `git ls-files -- test/*`.split("\n")
|
16
|
-
s.require_paths = ["lib"]
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
17
14
|
end
|
data/test/commands_test.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
unless Object.const_defined? 'Slop'
|
2
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
require 'slop'
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'minitest/autorun'
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'turn'
|
10
|
+
rescue LoadError
|
11
|
+
end
|
12
|
+
|
1
13
|
class TestCase < MiniTest::Unit::TestCase
|
2
14
|
def self.test(name, &block)
|
3
15
|
test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
|
data/test/option_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'helper'
|
2
2
|
|
3
3
|
class OptionTest < TestCase
|
4
4
|
def option(*args, &block)
|
@@ -63,6 +63,7 @@ class OptionTest < TestCase
|
|
63
63
|
test 'casting' do
|
64
64
|
assert_equal :foo, option_value(%w/--name foo/, :name, true, :as => Symbol)
|
65
65
|
assert_equal :foo, option_value(%w/--name foo/, :name, true, :as => :symbol)
|
66
|
+
assert_equal :foo, option_value(%w/--name foo/, :name, true, :as => :sym)
|
66
67
|
assert_equal 30, option_value(%w/--age 30/, :age, true, :as => Integer)
|
67
68
|
assert_equal "1.0", option_value(%w/--id 1/, :id, true, :as => Float).to_s
|
68
69
|
end
|
@@ -75,7 +76,7 @@ class OptionTest < TestCase
|
|
75
76
|
|
76
77
|
# default back to the string unless a regex is successful
|
77
78
|
# return value.to_i if the value is /\A\d+\z/
|
78
|
-
# maybe this should raise
|
79
|
+
# maybe this should raise if Slop#strict?
|
79
80
|
assert_equal "1abc10", option_value(%w/-r 1abc10/, :r, true, :as => Range)
|
80
81
|
assert_equal 1, option_value(%w/-r 1/, :r, true, :as => Range)
|
81
82
|
end
|
@@ -137,4 +138,11 @@ class OptionTest < TestCase
|
|
137
138
|
assert_equal nil, slop[:foo]
|
138
139
|
refute_equal "", slop[:foo]
|
139
140
|
end
|
141
|
+
|
142
|
+
test 'counting options' do
|
143
|
+
slop = Slop.new { on :v; on :x }
|
144
|
+
slop.parse %w/-v -v -v -x/
|
145
|
+
assert_equal 1, slop.options[:x].count
|
146
|
+
assert_equal 3, slop.options[:v].count
|
147
|
+
end
|
140
148
|
end
|
data/test/slop_test.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
1
3
|
class SlopTest < TestCase
|
2
4
|
def clean_options(*args)
|
3
5
|
Slop.new.send(:clean_options, args)
|
@@ -32,7 +34,7 @@ class SlopTest < TestCase
|
|
32
34
|
slop.opt(:f, :foo, 'foo')
|
33
35
|
slop.opt(:b, :bar, 'bar')
|
34
36
|
|
35
|
-
slop.each { |option|
|
37
|
+
slop.each { |option| assert_kind_of Slop::Option, option }
|
36
38
|
end
|
37
39
|
|
38
40
|
test 'defaulting to ARGV' do
|
@@ -42,13 +44,12 @@ class SlopTest < TestCase
|
|
42
44
|
end
|
43
45
|
|
44
46
|
test 'callback when option array is empty' do
|
45
|
-
item1 =
|
47
|
+
item1 = nil
|
46
48
|
temp_argv([]) do
|
47
49
|
Slop.new { on_empty { item1 = 'foo' } }.parse
|
48
50
|
end
|
49
51
|
|
50
52
|
assert_equal 'foo', item1
|
51
|
-
assert_nil item2
|
52
53
|
end
|
53
54
|
|
54
55
|
test 'multiple switches with the :multiple_switches flag' do
|
@@ -144,6 +145,12 @@ class SlopTest < TestCase
|
|
144
145
|
assert_empty items
|
145
146
|
end
|
146
147
|
|
148
|
+
test '#parse! does not remove unparsed items with same value as a parsed item' do
|
149
|
+
items = %w/bar --foo bar/
|
150
|
+
Slop.new { |opt| opt.on :foo, 'foo', true }.parse!(items)
|
151
|
+
assert_equal %w/bar/, items
|
152
|
+
end
|
153
|
+
|
147
154
|
test '#parse! removes parsed items prefixed with --no-' do
|
148
155
|
items = %w/--no-foo/
|
149
156
|
Slop.new { |opt| opt.on :foo }.parse!(items)
|
@@ -210,6 +217,14 @@ class SlopTest < TestCase
|
|
210
217
|
refute slop.debug?
|
211
218
|
end
|
212
219
|
|
220
|
+
test 'options are present' do
|
221
|
+
opts = Slop.new { on :f, 'foo-bar'; on :b, 'bar-baz' }
|
222
|
+
opts.parse %w/--foo-bar/
|
223
|
+
|
224
|
+
assert opts.present?('foo-bar')
|
225
|
+
refute opts.present?('bar-baz')
|
226
|
+
end
|
227
|
+
|
213
228
|
test 'raises if an option expects an argument and none is given' do
|
214
229
|
slop = Slop.new
|
215
230
|
slop.opt :name, true
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: slop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.5.
|
5
|
+
version: 1.5.4
|
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-
|
13
|
+
date: 2011-05-01 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|