options 2.0.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -26,6 +26,7 @@ INSTALL
26
26
  gem install options
27
27
 
28
28
  SAMPLES
29
+
29
30
 
30
31
  <========< samples/a.rb >========>
31
32
 
@@ -33,7 +34,7 @@ SAMPLES
33
34
 
34
35
  require 'options'
35
36
 
36
- # options.rb makes is super easy to deal with keyword options in a safe and
37
+ # options.rb makes it super easy to deal with keyword options in a safe and
37
38
  # easy way.
38
39
  #
39
40
 
@@ -149,3 +150,30 @@ SAMPLES
149
150
  {:options=>{:k=>:v}}
150
151
 
151
152
 
153
+ <========< samples/d.rb >========>
154
+
155
+ ~ > cat samples/d.rb
156
+
157
+ require 'options'
158
+
159
+ # options.rb makes it easy to provide good error messages when people
160
+ # misuse a method.
161
+ #
162
+
163
+ def method(*args)
164
+ args, options = Options.parse(args)
165
+ options.validate(:force)
166
+
167
+ force = options.getopt(:force, default=false)
168
+ p force
169
+ end
170
+
171
+ method(:foo, :bar, :force => true)
172
+
173
+
174
+
175
+ ~ > ruby samples/d.rb
176
+
177
+ true
178
+
179
+
@@ -0,0 +1,35 @@
1
+ NAME
2
+ options.rb
3
+
4
+ DESCRIPTION
5
+ options.rb simplifies the common idiom of dealing with keyword options in
6
+ ruby functions. it also deals correctly with symbol vs string keywords and
7
+ prevents many subtle programming errors that can arise from doing so
8
+ incorrectly. options.rb doesn't hack ruby's core with one exception: the
9
+ method Array#options.
10
+
11
+ SYNOPSIS
12
+ require 'options'
13
+
14
+ def method(*args, &block)
15
+ args, options = Options.parse(args)
16
+
17
+ a = args.shift
18
+ b = args.shift
19
+
20
+ force = options.getopt(:force, default = false)
21
+ verbose = options.getopt([:verbose, :VERBOSE])
22
+ foo, bar = options.getopt(:foo, :bar)
23
+ end
24
+
25
+ INSTALL
26
+ gem install options
27
+
28
+ HISTORY
29
+ 2.1.0:
30
+ - 1.9 compatibility
31
+ - Validation of passed options
32
+
33
+ SAMPLES
34
+
35
+ <%= samples %>
@@ -0,0 +1,235 @@
1
+
2
+ This.rubyforge_project = 'codeforpeople'
3
+ This.author = "Ara T. Howard"
4
+ This.email = "ara.t.howard@gmail.com"
5
+ This.homepage = "http://github.com/ahoward/#{ This.lib }/tree/master"
6
+
7
+
8
+ task :default do
9
+ puts(Rake::Task.tasks.map{|task| task.name} - ['default'])
10
+ end
11
+
12
+ task :spec do
13
+ require 'spec/rake/spectask'
14
+ Spec::Rake::SpecTask.new do |t|
15
+ t.spec_files = FileList['spec/*_spec.rb']
16
+ end
17
+ end
18
+
19
+
20
+ task :gemspec do
21
+ ignore_extensions = 'git', 'svn', 'tmp', /sw./, 'bak', 'gem'
22
+ ignore_directories = 'pkg'
23
+ ignore_files = 'test/log'
24
+
25
+ shiteless =
26
+ lambda do |list|
27
+ list.delete_if do |entry|
28
+ next unless test(?e, entry)
29
+ extension = File.basename(entry).split(%r/[.]/).last
30
+ ignore_extensions.any?{|ext| ext === extension}
31
+ end
32
+ list.delete_if do |entry|
33
+ next unless test(?d, entry)
34
+ dirname = File.expand_path(entry)
35
+ ignore_directories.any?{|dir| File.expand_path(dir) == dirname}
36
+ end
37
+ list.delete_if do |entry|
38
+ next unless test(?f, entry)
39
+ filename = File.expand_path(entry)
40
+ ignore_files.any?{|file| File.expand_path(file) == filename}
41
+ end
42
+ end
43
+
44
+ lib = This.lib
45
+ version = This.version
46
+ files = shiteless[Dir::glob("**/**")]
47
+ executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
48
+ has_rdoc = true #File.exist?('doc')
49
+ test_files = "test/#{ lib }.rb" if File.file?("test/#{ lib }.rb")
50
+
51
+ extensions = This.extensions
52
+ if extensions.nil?
53
+ %w( Makefile configure extconf.rb ).each do |ext|
54
+ extensions << ext if File.exists?(ext)
55
+ end
56
+ end
57
+ extensions = [extensions].flatten.compact
58
+
59
+ template =
60
+ if test(?e, 'gemspec.erb')
61
+ Template{ IO.read('gemspec.erb') }
62
+ else
63
+ Template {
64
+ <<-__
65
+ ## #{ lib }.gemspec
66
+ #
67
+
68
+ Gem::Specification::new do |spec|
69
+ spec.name = #{ lib.inspect }
70
+ spec.version = #{ version.inspect }
71
+ spec.platform = Gem::Platform::RUBY
72
+ spec.summary = #{ lib.inspect }
73
+
74
+ spec.files = #{ files.inspect }
75
+ spec.executables = #{ executables.inspect }
76
+
77
+ spec.require_path = "lib"
78
+
79
+ spec.has_rdoc = #{ has_rdoc.inspect }
80
+ spec.test_files = #{ test_files.inspect }
81
+ #spec.add_dependency 'lib', '>= version'
82
+ #spec.add_dependency 'fattr'
83
+
84
+ spec.extensions.push(*#{ extensions.inspect })
85
+
86
+ spec.rubyforge_project = #{ This.rubyforge_project.inspect }
87
+ spec.author = #{ This.author.inspect }
88
+ spec.email = #{ This.email.inspect }
89
+ spec.homepage = #{ This.homepage.inspect }
90
+ end
91
+ __
92
+ }
93
+ end
94
+
95
+ open("#{ lib }.gemspec", "w"){|fd| fd.puts template}
96
+ This.gemspec = "#{ lib }.gemspec"
97
+ end
98
+
99
+ task :gem => [:clean, :gemspec] do
100
+ Fu.mkdir_p This.pkgdir
101
+ before = Dir['*.gem']
102
+ cmd = "gem build #{ This.gemspec }"
103
+ `#{ cmd }`
104
+ after = Dir['*.gem']
105
+ gem = ((after - before).first || after.first) or abort('no gem!')
106
+ Fu.mv gem, This.pkgdir
107
+ This.gem = File.basename(gem)
108
+ end
109
+
110
+ task :readme do
111
+ samples = ''
112
+ prompt = '~ > '
113
+ lib = This.lib
114
+ version = This.version
115
+
116
+ Dir['sample*/*'].sort.each do |sample|
117
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
118
+
119
+ cmd = "cat #{ sample }"
120
+ samples << Util.indent(prompt + cmd, 2) << "\n\n"
121
+ samples << Util.indent(`#{ cmd }`, 4) << "\n"
122
+
123
+ cmd = "ruby #{ sample }"
124
+ samples << Util.indent(prompt + cmd, 2) << "\n\n"
125
+
126
+ cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -Ilib #{ sample })'"
127
+ samples << Util.indent(`#{ cmd } 2>&1`, 4) << "\n"
128
+ end
129
+
130
+ template =
131
+ if test(?e, 'readme.erb')
132
+ Template{ IO.read('readme.erb') }
133
+ else
134
+ Template {
135
+ <<-__
136
+ NAME
137
+ #{ lib }
138
+
139
+ DESCRIPTION
140
+
141
+ INSTALL
142
+ gem install #{ lib }
143
+
144
+ SAMPLES
145
+ #{ samples }
146
+ __
147
+ }
148
+ end
149
+
150
+ open("README", "w"){|fd| fd.puts template}
151
+ end
152
+
153
+
154
+ task :clean do
155
+ Dir[File.join(This.pkgdir, '**/**')].each{|entry| Fu.rm_rf(entry)}
156
+ end
157
+
158
+
159
+ task :release => [:clean, :gemspec, :gem] do
160
+ gems = Dir[File.join(This.pkgdir, '*.gem')].flatten
161
+ raise "which one? : #{ gems.inspect }" if gems.size > 1
162
+ raise "no gems?" if gems.size < 1
163
+ cmd = "rubyforge login && rubyforge add_release #{ This.rubyforge_project } #{ This.lib } #{ This.version } #{ This.pkgdir }/#{ This.gem }"
164
+ puts cmd
165
+ system cmd
166
+ end
167
+
168
+
169
+
170
+
171
+
172
+ BEGIN {
173
+ $VERBOSE = nil
174
+
175
+ require 'ostruct'
176
+ require 'erb'
177
+ require 'fileutils'
178
+
179
+ Fu = FileUtils
180
+
181
+ This = OpenStruct.new
182
+
183
+ This.file = File.expand_path(__FILE__)
184
+ This.dir = File.dirname(This.file)
185
+ This.pkgdir = File.join(This.dir, 'pkg')
186
+
187
+ lib = ENV['LIB']
188
+ unless lib
189
+ lib = File.basename(Dir.pwd)
190
+ end
191
+ This.lib = lib
192
+
193
+ version = ENV['VERSION']
194
+ unless version
195
+ name = lib.capitalize
196
+ require "./lib/#{ lib }"
197
+ version = eval(name).send(:version)
198
+ end
199
+ This.version = version
200
+
201
+ abort('no lib') unless This.lib
202
+ abort('no version') unless This.version
203
+
204
+ module Util
205
+ def indent(s, n = 2)
206
+ s = unindent(s)
207
+ ws = ' ' * n
208
+ s.gsub(%r/^/, ws)
209
+ end
210
+
211
+ def unindent(s)
212
+ indent = nil
213
+ s.each do |line|
214
+ next if line =~ %r/^\s*$/
215
+ indent = line[%r/^\s*/] and break
216
+ end
217
+ indent ? s.gsub(%r/^#{ indent }/, "") : s
218
+ end
219
+ extend self
220
+ end
221
+
222
+ class Template
223
+ def initialize(&block)
224
+ @block = block
225
+ @template = block.call.to_s
226
+ end
227
+ def expand(b=nil)
228
+ ERB.new(Util.unindent(@template)).result(b||@block)
229
+ end
230
+ alias_method 'to_s', 'expand'
231
+ end
232
+ def Template(*args, &block) Template.new(*args, &block) end
233
+
234
+ Dir.chdir(This.dir)
235
+ }
@@ -1,5 +1,5 @@
1
1
  module Options
2
- VERSION = '2.0.0'
2
+ VERSION = '2.1.1'
3
3
 
4
4
  class << Options
5
5
  def version
@@ -46,8 +46,15 @@ module Options
46
46
  end
47
47
 
48
48
  def parse(args)
49
- args.extend(Arguments) unless args.is_a?(Arguments)
50
- args.options.pop
49
+ case args
50
+ when Array
51
+ args.extend(Arguments) unless args.is_a?(Arguments)
52
+ [args, args.options.pop]
53
+ when Hash
54
+ Options.for(args)
55
+ else
56
+ raise ArgumentError, "`args` should be and Array or Hash"
57
+ end
51
58
  end
52
59
  end
53
60
 
@@ -131,13 +138,13 @@ module Options
131
138
  def normalize!
132
139
  Options.normalize!(self)
133
140
  end
134
- alias_method 'normalized!', 'normalized!'
141
+ alias_method 'normalized!', 'normalize!'
135
142
  alias_method 'to_options!', 'normalize!'
136
143
 
137
144
  def normalize
138
145
  Options.normalize(self)
139
146
  end
140
- alias_method 'normalized', 'normalized'
147
+ alias_method 'normalized', 'normalize'
141
148
  alias_method 'to_options', 'normalize'
142
149
 
143
150
  def stringify!
@@ -163,6 +170,23 @@ module Options
163
170
  def pop!
164
171
  @popped = arguments.pop
165
172
  end
173
+
174
+ # Validates that the options provided are acceptable.
175
+ #
176
+ # @param [Symbol] *acceptable_options List of options that are
177
+ # allowed
178
+ def validate(*acceptable_options)
179
+ remaining = (provided_options - acceptable_options).map{|opt| opt.to_s}.sort
180
+ raise ArgumentError, "Unrecognized options: #{remaining.join(', ')}" unless remaining.empty?
181
+
182
+ self
183
+ end
184
+
185
+ protected
186
+
187
+ def provided_options
188
+ normalize!.keys
189
+ end
166
190
  end
167
191
 
168
192
  module Arguments
@@ -1,26 +1,26 @@
1
- ### gemspec: options-2.0.0
1
+ ## options.gemspec
2
+ #
2
3
 
3
- Gem::Specification::new do |spec|
4
- spec.name = "options"
5
- spec.version = "2.0.0"
6
- spec.platform = Gem::Platform::RUBY
7
- spec.summary = "options"
4
+ Gem::Specification::new do |spec|
5
+ spec.name = "options"
6
+ spec.version = "2.1.1"
7
+ spec.platform = Gem::Platform::RUBY
8
+ spec.summary = "options"
8
9
 
9
- spec.files = ["gemspec.rb", "lib", "lib/options.rb", "options.gemspec", "README", "README.rb", "samples", "samples/a.rb", "samples/b.rb", "samples/c.rb"]
10
- spec.executables = []
11
-
12
- spec.require_path = "lib"
10
+ spec.files = ["lib", "lib/options.rb", "options.gemspec", "Rakefile", "README", "README.erb", "samples", "samples/a.rb", "samples/b.rb", "samples/c.rb", "samples/d.rb", "spec", "spec/options_spec.rb", "spec/spec_helper.rb"]
11
+ spec.executables = []
12
+
13
+ spec.require_path = "lib"
13
14
 
14
- spec.has_rdoc = true
15
- spec.test_files = nil
16
- #spec.add_dependency 'lib', '>= version'
17
- #spec.add_dependency 'fattr'
15
+ spec.has_rdoc = true
16
+ spec.test_files = nil
17
+ #spec.add_dependency 'lib', '>= version'
18
+ #spec.add_dependency 'fattr'
18
19
 
19
- spec.extensions.push(*[])
20
-
21
- spec.rubyforge_project = 'codeforpeople'
22
- spec.author = "Ara T. Howard"
23
- spec.email = "ara.t.howard@gmail.com"
24
- spec.homepage = "http://github.com/ahoward/options/tree/master"
25
- end
20
+ spec.extensions.push(*[])
26
21
 
22
+ spec.rubyforge_project = "codeforpeople"
23
+ spec.author = "Ara T. Howard"
24
+ spec.email = "ara.t.howard@gmail.com"
25
+ spec.homepage = "http://github.com/ahoward/options/tree/master"
26
+ end
@@ -1,6 +1,6 @@
1
1
  require 'options'
2
2
 
3
- # options.rb makes is super easy to deal with keyword options in a safe and
3
+ # options.rb makes it super easy to deal with keyword options in a safe and
4
4
  # easy way.
5
5
  #
6
6
 
@@ -0,0 +1,17 @@
1
+ require 'options'
2
+
3
+ # options.rb makes it easy to provide good error messages when people
4
+ # misuse a method.
5
+ #
6
+
7
+ def method(*args)
8
+ args, options = Options.parse(args)
9
+ options.validate(:force)
10
+
11
+ force = options.getopt(:force, default=false)
12
+ p force
13
+ end
14
+
15
+ method(:foo, :bar, :force => true)
16
+
17
+
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+ require 'options'
3
+
4
+ describe Options do
5
+ describe "parsing" do
6
+ it "should be able to handle an options hash" do
7
+ opts = Options.parse({:this => 'that'})
8
+ opts.getopt(:this).should eql('that')
9
+ end
10
+
11
+ it "should be able to handle args list w/ options hash" do
12
+ args, opts = Options.parse([:foo, {:this => 'that'}])
13
+ opts.getopt(:this).should eql('that')
14
+ args.should eql([:foo])
15
+ end
16
+ end
17
+
18
+ describe "validation" do
19
+ it "should be able to detect extraneous options" do
20
+ lambda{
21
+ Options.parse({:this => 'test'}).validate(:foo, :bar)
22
+ }.should raise_error(ArgumentError, "Unrecognized options: this")
23
+ end
24
+
25
+ it "should list all extraneous options in message" do
26
+ lambda{
27
+ Options.parse({:this => 'test', :that => 'test'}).validate(:foo)
28
+ }.should raise_error(ArgumentError, "Unrecognized options: that, this")
29
+ end
30
+
31
+ it "should accept options from simple list" do
32
+ lambda{
33
+ Options.parse({:foo => 'this', :bar => 'that'}).validate(:foo, :bar)
34
+ }.should_not raise_error
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'pathname'
4
+ require 'pp'
5
+
6
+ $LOAD_PATH.unshift Pathname(__FILE__).dirname + "../lib"
7
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: options
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ara T. Howard
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-31 00:00:00 -06:00
12
+ date: 2009-08-19 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -22,16 +22,20 @@ extensions: []
22
22
  extra_rdoc_files: []
23
23
 
24
24
  files:
25
- - gemspec.rb
26
25
  - lib
27
26
  - lib/options.rb
28
27
  - options.gemspec
28
+ - Rakefile
29
29
  - README
30
- - README.rb
30
+ - README.erb
31
31
  - samples
32
32
  - samples/a.rb
33
33
  - samples/b.rb
34
34
  - samples/c.rb
35
+ - samples/d.rb
36
+ - spec
37
+ - spec/options_spec.rb
38
+ - spec/spec_helper.rb
35
39
  has_rdoc: true
36
40
  homepage: http://github.com/ahoward/options/tree/master
37
41
  post_install_message:
data/README.rb DELETED
@@ -1,80 +0,0 @@
1
- #! /usr/bin/env ruby
2
-
3
- template = <<-__
4
- NAME
5
- options.rb
6
-
7
- DESCRIPTION
8
- options.rb simplifies the common idiom of dealing with keyword options in
9
- ruby functions. it also deals correctly with symbol vs string keywords and
10
- prevents many subtle programming errors that can arise from doing so
11
- incorrectly. options.rb doesn't hack ruby's core with one exception: the
12
- method Array#options.
13
-
14
- SYNOPSIS
15
- require 'options'
16
-
17
- def method(*args, &block)
18
- args, options = Options.parse(args)
19
-
20
- a = args.shift
21
- b = args.shift
22
-
23
- force = options.getopt(:force, default = false)
24
- verbose = options.getopt([:verbose, :VERBOSE])
25
- foo, bar = options.getopt(:foo, :bar)
26
- end
27
-
28
- INSTALL
29
- gem install options
30
-
31
- SAMPLES
32
- <%= samples %>
33
- __
34
-
35
-
36
- require 'erb'
37
- require 'pathname'
38
-
39
- $VERBOSE=nil
40
-
41
- def indent(s, n = 2)
42
- s = unindent(s)
43
- ws = ' ' * n
44
- s.gsub(%r/^/, ws)
45
- end
46
-
47
- def unindent(s)
48
- indent = nil
49
- s.each do |line|
50
- next if line =~ %r/^\s*$/
51
- indent = line[%r/^\s*/] and break
52
- end
53
- indent ? s.gsub(%r/^#{ indent }/, "") : s
54
- end
55
-
56
- samples = ''
57
- prompt = '~ > '
58
-
59
- Dir.chdir(File.dirname(__FILE__))
60
-
61
- Dir['sample*/*'].sort.each do |sample|
62
- samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
63
-
64
- cmd = "cat #{ sample }"
65
- samples << indent(prompt + cmd, 2) << "\n\n"
66
- samples << indent(`#{ cmd }`, 4) << "\n"
67
-
68
- cmd = "ruby #{ sample }"
69
- samples << indent(prompt + cmd, 2) << "\n\n"
70
-
71
- cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -Ilib #{ sample })'"
72
- #cmd = "ruby -Ilib #{ sample }"
73
- samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
74
- end
75
-
76
- erb = ERB.new(unindent(template))
77
- result = erb.result(binding)
78
- #open('README', 'w'){|fd| fd.write result}
79
- #puts unindent(result)
80
- puts result
data/gemspec.rb DELETED
@@ -1,62 +0,0 @@
1
- #! /usr/bin/env ruby
2
-
3
- lib, version, *ignored = ARGV
4
-
5
- unless lib
6
- lib = File.basename(Dir.pwd)
7
- end
8
-
9
- unless version
10
- mod = lib.capitalize
11
- require "./lib/#{ lib }"
12
- version = eval(mod).send(:version)
13
- end
14
-
15
- abort('no lib') unless lib
16
- abort('no version') unless version
17
-
18
- puts "### gemspec: #{ lib }-#{ version }"
19
-
20
- $VERBOSE = nil
21
-
22
- shiteless = lambda{|list| list.delete_if{|file| file =~ %r/\.(git|svn|tmp|sw.|bak|gem)$/}}
23
-
24
- files = shiteless[Dir::glob("**/**")]
25
- executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
26
- has_rdoc = true #File.exist?('doc')
27
- test_files = "test/#{ lib }.rb" if File.file?("test/#{ lib }.rb")
28
-
29
- extensions = []
30
- %w( Makefile configure extconf.rb rakefile Rakefile mkrf_conf ).each do |ext|
31
- extensions << ext if File.exists?(ext)
32
- end
33
-
34
- template = <<-__
35
-
36
- Gem::Specification::new do |spec|
37
- spec.name = #{ lib.inspect }
38
- spec.version = #{ version.inspect }
39
- spec.platform = Gem::Platform::RUBY
40
- spec.summary = #{ lib.inspect }
41
-
42
- spec.files = #{ files.inspect }
43
- spec.executables = #{ executables.inspect }
44
-
45
- spec.require_path = "lib"
46
-
47
- spec.has_rdoc = #{ has_rdoc.inspect }
48
- spec.test_files = #{ test_files.inspect }
49
- #spec.add_dependency 'lib', '>= version'
50
- #spec.add_dependency 'fattr'
51
-
52
- spec.extensions.push(*#{ extensions.inspect })
53
-
54
- spec.rubyforge_project = 'codeforpeople'
55
- spec.author = "Ara T. Howard"
56
- spec.email = "ara.t.howard@gmail.com"
57
- spec.homepage = "http://github.com/ahoward/#{ lib }/tree/master"
58
- end
59
-
60
- __
61
-
62
- puts template