slop 1.0.0.rc1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.yardopts CHANGED
@@ -1 +1,5 @@
1
- --hide-void-return -m markdown
1
+ --hide-void-return
2
+ -m markdown
3
+ --title "slop"
4
+ lib/**/*.rb
5
+ --no-private
data/README.md CHANGED
@@ -3,16 +3,12 @@ Slop
3
3
 
4
4
  Slop is a simple option collector with an easy to remember syntax and friendly API.
5
5
 
6
- **NOTE** This branch refers to the prerelease 1.0.0.rc1 version, this version has
7
- incompatible changes from version 0.0.3 (the latest stable version). You **should**
8
- upgrade.
9
-
10
6
  Installation
11
7
  ------------
12
8
 
13
9
  ### Rubygems
14
10
 
15
- gem install slop --pre
11
+ gem install slop
16
12
 
17
13
  ### GitHub
18
14
 
@@ -26,10 +22,11 @@ Usage
26
22
  opts = Slop.parse do
27
23
  on :v, :verbose, 'Enable verbose mode' # boolean value
28
24
  on :n, :name, 'Your name', true # compulsory argument
25
+ on :s, :sex, 'Your sex', :optional => false # the same thing
29
26
  on :a, :age, 'Your age', :optional => true # optional argument
30
27
  end
31
28
 
32
- # if ARGV is `-v --name 'lee jarvis'`
29
+ # if ARGV is `-v --name 'lee jarvis' -s male`
33
30
  opts.verbose? #=> true
34
31
  opts.name? #=> true
35
32
  opts[:name] #=> 'lee jarvis'
@@ -38,7 +35,7 @@ Usage
38
35
 
39
36
  You can also return your options as a Hash
40
37
 
41
- opts.to_hash #=> {:name => 'Lee Jarvis', :verbose => true, :age => nil}
38
+ opts.to_hash #=> {'name' => 'Lee Jarvis', 'verbose' => true, 'age' => nil, 'sex' => 'male'}
42
39
 
43
40
  If you don't like the method `on` (because it sounds like the option **expects**
44
41
  a callback), you can use the `opt` or `option` alternatives.
@@ -134,7 +131,7 @@ do this:
134
131
  You can also try other variations:
135
132
 
136
133
  on :name, "Your name"
137
- on :n, :name)
134
+ on :n, :name
138
135
  on :name, true
139
136
 
140
137
  Lists
@@ -156,6 +153,44 @@ You can also change both the split delimiter and limit
156
153
  end
157
154
  opts[:people] #=> ["lee", "injekt:bob"]
158
155
 
156
+ Woah woah, why you hating on OptionParser?
157
+ ------------------------------------------
158
+
159
+ I'm not, honestly! I love OptionParser. I really do, it's a fantastic library.
160
+ So why did I build Slop? Well, I find myself using OptionParser to simple
161
+ gather a bunch of key/value options, usually you would do something like this:
162
+
163
+ require 'optparse'
164
+
165
+ things = {}
166
+
167
+ opt = OptionParser.new do |opt|
168
+ opt.on('-n', '--name NAME', 'Your name') do |name|
169
+ things[:name] = name
170
+ end
171
+
172
+ opt.on('-a', '--age AGE', 'Your age') do |age|
173
+ things[:age] = age
174
+ end
175
+
176
+ # you get the point
177
+ end
178
+
179
+ opt.parse
180
+ # do something with things
181
+
182
+ Which is all great and stuff, but it can lead to some repetition, the same
183
+ thing in Slop:
184
+
185
+ require 'slop'
186
+
187
+ opts = Slop.parse do
188
+ on :n, :name, 'Your name', true
189
+ on :a, :age, 'Your age', true
190
+ end
191
+
192
+ things = opts.to_hash
193
+
159
194
  Contributing
160
195
  ------------
161
196
 
data/Rakefile CHANGED
@@ -4,4 +4,6 @@ task :test do
4
4
  require 'minitest/autorun'
5
5
  begin; require 'turn'; rescue LoadError; end
6
6
  Dir.glob("test/**/*_test.rb").each { |test| require_relative test }
7
- end
7
+ end
8
+
9
+ task :default => :test
@@ -6,6 +6,21 @@ class Slop
6
6
 
7
7
  class MissingArgumentError < ArgumentError; end
8
8
 
9
+ # Parses the items from a CLI format into a friendly object.
10
+ #
11
+ # @param [Array] items Items to parse into options.
12
+ # @yield Specify available CLI arguments using Slop# methods such as Slop#banner and Slop#option
13
+ # @return [Slop] Returns an instance of Slop.
14
+ # @example Specifying three options to parse:
15
+ # opts = Slops.parse do
16
+ # on :v, :verbose, 'Enable verbose mode'
17
+ # on :n, :name, 'Your name'
18
+ # on :a, :age, 'Your age'
19
+ # end
20
+ # -------
21
+ # program.rb --verbose -n 'Emily' -a 25
22
+ # @see Slop#banner
23
+ # @see Slop#option
9
24
  def self.parse(items=ARGV, &block)
10
25
  slop = new(&block)
11
26
  slop.parse(items)
@@ -14,24 +29,42 @@ class Slop
14
29
 
15
30
  attr_reader :options
16
31
  attr_writer :banner
32
+ attr_accessor :longest_flag
17
33
 
18
34
  def initialize(&block)
19
35
  @options = Options.new
20
36
  @banner = nil
37
+ @longest_flag = 0
38
+
21
39
  if block_given?
22
40
  block.arity == 1 ? yield(self) : instance_eval(&block)
23
41
  end
24
42
  end
25
43
 
44
+ # Set or return banner text.
45
+ #
46
+ # @param [String] text Displayed banner text.
47
+ # @return [String] Returns current banner.
48
+ # @example
49
+ # opts = Slop.parse do
50
+ # banner "Usage - ruby foo.rb [arguments]"
51
+ # end
52
+ # @see Slop#to_s
26
53
  def banner(text=nil)
27
54
  @banner = text if text
28
55
  @banner
29
56
  end
30
57
 
58
+ # Parse a list of options, leaving the original Array unchanged.
59
+ #
60
+ # @param items
31
61
  def parse(items=ARGV)
32
62
  parse_items(items)
33
63
  end
34
64
 
65
+ # Parse a list of options, removing parsed options from the original Array.
66
+ #
67
+ # @parse items
35
68
  def parse!(items=ARGV)
36
69
  parse_items(items, true)
37
70
  end
@@ -42,20 +75,43 @@ class Slop
42
75
  @options.each { |option| yield option }
43
76
  end
44
77
 
78
+ # Return the value of an option via the subscript operator.
79
+ #
80
+ # @param [Symbol] key Option symbol.
81
+ # @return [Object] Returns the object associated with that option.
82
+ # @example
83
+ # opts[:name]
84
+ # #=> "Emily"
85
+ # @see Slop#method_missing
45
86
  def [](key)
46
87
  option = @options[key]
47
88
  option ? option.argument_value : nil
48
89
  end
49
90
 
50
- # :short_flag
51
- # :long_flag
52
- # :description
53
- # :argument
91
+ # Specify an option with a short or long version, description and type.
92
+ #
93
+ # @param [*] args Option configuration.
94
+ # @option args [Symbol, String] :short_flag Short option name.
95
+ # @option args [Symbol, String] :long_flag Full option name.
96
+ # @option args [String] :description Option description for use in Slop#help
97
+ # @option args [Boolean] :argument Specifies whether a required option or not.
98
+ # @option args [Hash] :options Optional option configurations.
99
+ # @example
100
+ # opts = Slop.parse do
101
+ # on :n, :name, 'Your username', true # Required argument
102
+ # on :a, :age, 'Your age (optional)', :optional => true # Optional argument
103
+ # on :g, :gender, 'Your gender', :optional => false # Required argument
104
+ # on :V, :verbose, 'Run in verbose mode', :default => true # Runs verbose mode by default
105
+ # on :P, :people, 'Your friends', true, :as => Array # Required, list of people.
106
+ # on :h, :help, 'Print this help screen' do
107
+ # puts help
108
+ # end # Runs a block
109
+ # end
54
110
  def option(*args, &block)
55
111
  options = args.pop if args.last.is_a?(Hash)
56
112
  options ||= {}
57
113
 
58
- option = Option.new(*clean_options(args), options, &block)
114
+ option = Option.new(self, *clean_options(args), options, &block)
59
115
  @options << option
60
116
 
61
117
  option
@@ -63,10 +119,26 @@ class Slop
63
119
  alias :opt :option
64
120
  alias :on :option
65
121
 
122
+ # Returns the parsed list into a option/value hash.
123
+ #
124
+ # @return [Hash] Returns a hash with each specified option as a symbolic key with an associated value.
125
+ # @example
126
+ # opts.to_hash
127
+ # #=> { :name => 'Emily' }
66
128
  def to_hash
67
129
  @options.to_hash
68
130
  end
69
131
 
132
+ # Allows you to check whether an option was specified in the parsed list.
133
+ #
134
+ # @return [Boolean] Whether the desired option was specified.
135
+ # @example
136
+ # #== ruby foo.rb -v
137
+ # opts.verbose?
138
+ # #=> true
139
+ # opts.name?
140
+ # #=> false
141
+ # @see Slop#[]
70
142
  def method_missing(meth, *args, &block)
71
143
  if meth.to_s =~ /\?$/
72
144
  !!self[meth.to_s.chomp('?')]
@@ -75,6 +147,17 @@ class Slop
75
147
  end
76
148
  end
77
149
 
150
+ # Returns the banner followed by available options listed on the next line.
151
+ #
152
+ # @return [String] Help text.
153
+ # @example
154
+ # opts = Slop.parse do
155
+ # banner "Usage - ruby foo.rb [arguments]"
156
+ # on :v, :verbose, "Enable verbose mode"
157
+ # end
158
+ # opts.to_s
159
+ # #=> "Usage - ruby foo.rb [options]\n -v, --verbose Enable verbose mode"
160
+ # @see Slop#banner
78
161
  def to_s
79
162
  banner = "#{@banner}\n" if @banner
80
163
  (banner || '') + options.map(&:to_s).join("\n")
@@ -87,38 +170,34 @@ private
87
170
  trash = []
88
171
 
89
172
  items.each do |item|
90
-
91
173
  flag = item.to_s.sub(/^--?/, '')
92
- if flag.length == 1
93
- option = find { |option| option.short_flag == flag }
94
- else
95
- option = find { |option| option.long_flag == flag }
96
- end
97
174
 
98
- if option
175
+ if option = @options[flag]
176
+ trash << item if delete
99
177
  option.argument_value = true
100
178
 
101
179
  if option.expects_argument? || option.accepts_optional_argument?
102
180
  argument = items.at(items.index(item) + 1)
103
- trash << argument if delete && argument !~ /^--?/
181
+ trash << argument if delete
104
182
 
105
183
  if argument
106
184
  option.argument_value = argument
107
- option.callback.call(option.argument_value) if option.has_callback?
185
+ option.callback.call(option.argument_value) if option.callback
108
186
  else
187
+ option.argument_value = nil
109
188
  if option.accepts_optional_argument?
110
- option.callback.call(nil) if option.has_callback?
189
+ option.callback.call(nil) if option.callback
111
190
  else
112
191
  raise MissingArgumentError,
113
192
  "'#{flag}' expects an argument, none given"
114
193
  end
115
194
  end
116
- elsif option.has_callback?
195
+ elsif option.callback
117
196
  option.callback.call(nil)
118
197
  end
119
- trash << item if delete
120
198
  end
121
199
  end
200
+
122
201
  items.delete_if { |item| trash.include? item }
123
202
  end
124
203
 
@@ -8,8 +8,8 @@ class Slop
8
8
 
9
9
  def [](item)
10
10
  item = item.to_s
11
- if item =~ /^\d+/
12
- super
11
+ if item =~ /^\d+$/
12
+ slice(item.to_i)
13
13
  else
14
14
  find do |option|
15
15
  option.short_flag == item || option.long_flag == item
@@ -26,18 +26,20 @@ class Slop
26
26
  attr_reader :callback
27
27
  attr_writer :argument_value
28
28
 
29
- @@longest_flag = 0
30
-
31
- def initialize(short, long, description, argument, options={}, &block)
32
- @short_flag, @long_flag = short, long
33
- @description, @expects_argument = description, argument
29
+ def initialize(slop, short, long, description, argument, options={}, &blk)
30
+ @slop = slop
31
+ @short_flag = short
32
+ @long_flag = long
33
+ @description = description
34
34
  @options = options
35
+ @expects_argument = argument
36
+ @expects_argument = true if options[:optional] == false
35
37
 
36
- if @long_flag && @long_flag.size > @@longest_flag
37
- @@longest_flag = @long_flag.size
38
+ if @long_flag && @long_flag.size > @slop.longest_flag
39
+ @slop.longest_flag = @long_flag.size
38
40
  end
39
41
 
40
- @callback = block if block_given?
42
+ @callback = blk if block_given?
41
43
  @callback ||= options[:callback]
42
44
  @argument_value = nil
43
45
  end
@@ -50,10 +52,6 @@ class Slop
50
52
  @options[:optional]
51
53
  end
52
54
 
53
- def has_callback?
54
- !!@callback && @callback.respond_to?(:call)
55
- end
56
-
57
55
  def key
58
56
  @long_flag || @short_flag
59
57
  end
@@ -64,15 +62,15 @@ class Slop
64
62
 
65
63
  def argument_value
66
64
  value = @argument_value || default
67
- return unless value
65
+ return if value.nil?
68
66
 
69
67
  case @options[:as].to_s
70
68
  when 'Array'
71
69
  value.split(@options[:delimiter] || ',', @options[:limit] || 0)
72
70
  when 'String'; value.to_s
73
71
  when 'Symbol'; value.to_s.to_sym
74
- when 'Integer'; value.to_i
75
- when 'Float'; value.to_f
72
+ when 'Integer'; value.to_s.to_i
73
+ when 'Float'; value.to_s.to_f
76
74
  else
77
75
  value
78
76
  end
@@ -80,28 +78,25 @@ class Slop
80
78
 
81
79
  def to_s
82
80
  out = " "
83
- out += @short_flag ? "-#{@short_flag}, " : ' ' * 4
84
-
85
- out += "--#{@long_flag}" if @long_flag
81
+ out += @short_flag ? "-#{@short_flag}, " : ' ' * 4
86
82
 
87
83
  if @long_flag
88
- diff = @@longest_flag - @long_flag.size
84
+ out += "--#{@long_flag}"
85
+ diff = @slop.longest_flag - @long_flag.size
89
86
  spaces = " " * (diff + 6)
90
87
  out += spaces
91
88
  else
92
- spaces = " " * (@@longest_flag + 8)
89
+ spaces = " " * (@slop.longest_flag + 8)
93
90
  out += spaces
94
91
  end
95
92
 
96
- out += @description if @description
97
-
98
- out
93
+ "#{out}#{@description}"
99
94
  end
100
95
 
101
96
  def inspect
102
97
  "#<Slop::Option short_flag=#{@short_flag.inspect} " +
103
98
  "long_flag=#{@long_flag.inspect} " +
104
- "description=#{@description.inspect} "
99
+ "description=#{@description.inspect}>"
105
100
  end
106
101
  end
107
102
 
@@ -1,3 +1,3 @@
1
1
  class Slop
2
- VERSION = '1.0.0.rc1'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -17,9 +17,10 @@ class OptionTest < TestCase
17
17
  option_with_argument(*args, &block).argument_value
18
18
  end
19
19
 
20
- test 'expects an argument if argument is true' do
20
+ test 'expects an argument if argument is true or optional is false' do
21
21
  assert option(:f, :foo, 'foo', true).expects_argument?
22
22
  assert option(:f, :argument => true).expects_argument?
23
+ assert option(:f, :optional => false).expects_argument?
23
24
 
24
25
  refute option(:f, :foo).expects_argument?
25
26
  end
@@ -32,10 +33,10 @@ class OptionTest < TestCase
32
33
  end
33
34
 
34
35
  test 'has a callback when passed a block or callback option' do
35
- assert option(:f){}.has_callback?
36
- assert option(:callback => proc {}).has_callback?
36
+ assert option(:f){}.callback
37
+ assert option(:callback => proc {}).callback
37
38
 
38
- refute option(:f).has_callback?
39
+ refute option(:f).callback
39
40
  end
40
41
 
41
42
  test 'splits argument_value with :as => array' do
@@ -77,4 +78,16 @@ class OptionTest < TestCase
77
78
  assert_equal " --age Your age", slop.options[:age].to_s
78
79
  assert_equal " -V, Display the version", slop.options[:V].to_s
79
80
  end
81
+
82
+ test 'falls back to default option' do
83
+ slop = Slop.new
84
+ slop.opt :foo, :optional => true, :default => 'lee'
85
+ slop.parse %w/--foo/
86
+ assert_equal 'lee', slop[:foo]
87
+ end
88
+
89
+ test 'key should default to long flag otherwise use short flag' do
90
+ assert_equal 'foo', option(:f, :foo).key
91
+ assert_equal 'b', option(:b).key
92
+ end
80
93
  end
@@ -26,8 +26,22 @@ class SlopTest < TestCase
26
26
  slop.each { |option| assert option }
27
27
  end
28
28
 
29
- test 'parsing options' do
29
+ test 'passing a block' do
30
+ assert Slop.new {}
31
+ slop = nil
32
+ assert Slop.new {|s| slop = s }
33
+ assert_kind_of Slop, slop
34
+ end
35
+
36
+ test 'setting the banner' do
37
+ slop = Slop.new
38
+ slop.banner = "foo bar"
39
+
40
+ assert_equal "foo bar", slop.banner
41
+ assert slop.to_s =~ /^foo bar/
30
42
 
43
+ slop.banner = nil
44
+ assert_equal "", slop.to_s
31
45
  end
32
46
 
33
47
  test '#parse does not remove parsed items' do
@@ -103,6 +117,35 @@ class SlopTest < TestCase
103
117
  assert slop.parse %w/--name 'foo'/
104
118
  end
105
119
 
120
+ test 'returning a hash of options' do
121
+ slop = Slop.new
122
+ slop.opt :name, true
123
+ slop.opt :version
124
+ slop.opt :V, :verbose, :default => false
125
+ slop.parse %w/--name lee --version/
126
+
127
+ assert_equal({'name' => 'lee', 'version' => true, 'verbose' => false}, slop.to_hash)
128
+ end
129
+
130
+ test 'iterating options' do
131
+ slop = Slop.new
132
+ slop.opt :a, :abc
133
+ slop.opt :f, :foo
134
+
135
+ assert_equal 2, slop.count
136
+ slop.each {|opt| assert_kind_of Slop::Option, opt }
137
+ end
138
+
139
+ test 'fetching options and option values' do
140
+ slop = Slop.new
141
+ slop.opt :foo, true
142
+ slop.parse %w/--foo bar/
143
+
144
+ assert_kind_of Slop::Option, slop.options[:foo]
145
+ assert_equal "bar", slop[:foo]
146
+ assert_equal "bar", slop['foo']
147
+ end
148
+
106
149
  test 'printing help' do
107
150
  slop = Slop.new
108
151
  slop.banner = 'Usage: foo [options]'
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slop
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 6
5
- version: 1.0.0.rc1
4
+ prerelease:
5
+ version: 1.0.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Lee Jarvis
@@ -54,9 +54,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
54
54
  required_rubygems_version: !ruby/object:Gem::Requirement
55
55
  none: false
56
56
  requirements:
57
- - - ">"
57
+ - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: 1.3.1
59
+ version: "0"
60
60
  requirements: []
61
61
 
62
62
  rubyforge_project: