slop 1.0.0.rc1 → 1.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/.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: