clip 0.0.1

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/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ === 0.0.1 / 2008-04-03
2
+
3
+ * Initial release for y'all to throw rotten veggies at
4
+
data/README.txt ADDED
@@ -0,0 +1,94 @@
1
+ = clip
2
+
3
+ == DESCRIPTION:
4
+
5
+ Yeah yeah yeah. Why in heaven's name do we need yet another
6
+ command-line parser? Well, OptionParser is all well and good, but
7
+ doesn't grease the skids as much as I'd like. So I wrote this little
8
+ library... driven completely by specs.
9
+
10
+ Cheers!
11
+
12
+ == FEATURES
13
+
14
+ You like command-line parsing, but you hate all of the bloat. Why
15
+ should you have to create a Hash, then create a parser, then fill
16
+ that Hash out then throw the parser away (unless you want to print
17
+ out a usage message) and deal with a Hash? Why, for Pete's sake, should
18
+ the parser and the parsed values be handled by two different objects?
19
+
20
+ Well, now they don't...
21
+
22
+ == SYNOPSIS:
23
+
24
+ And it goes a little something like this...
25
+
26
+ require "rubygems"
27
+ require "clip"
28
+
29
+ parser = Clip do |p|
30
+ p.optional 's', 'server', :desc => 'The server name', :default => 'localhost'
31
+ p.optional 'p', 'port', :desc => 'The port', :default => 8080
32
+ p.required 'f', 'files', :multi => true, :desc => 'Files to send'
33
+ p.flag 'v', 'verbose', :desc => 'Make it chatty'
34
+ end
35
+
36
+ if parser.valid?
37
+ if parser.verbose?
38
+ puts parser.host
39
+ puts parser.port
40
+ puts 'files:'
41
+ parser.files.each do |f|
42
+ puts "\t#{f}"
43
+ end
44
+ end
45
+ else
46
+ # print error message(s) and usage
47
+ $stderr.puts parser.to_s
48
+ end
49
+
50
+ The names of the options and flags that you declare in the block are accessible
51
+ as methods on the returned object, reducing the amount of objects you have to
52
+ deal with when you're parsing command-line parameters.
53
+
54
+ Simply invoking the <tt>to_s</tt> method on a parser instance will dump both the
55
+ correct usage and any errors encountered during parsing. No need for you to manage
56
+ the state of what's required and what isn't by yourself. Also, '--help' and '-h'
57
+ will automatically trigger Clip to dump out usage and exit.
58
+
59
+ Sometimes you have additional arguments you need to process that don't require
60
+ a named option or flag. Whatever remains on the command line that doesn't fit
61
+ either a flag or an option/value pair will be made available via the
62
+ <tt>remainder</tt> method of the returned object.
63
+
64
+ == PROBLEMS/DEFICIENCIES:
65
+
66
+ OK, some of your favorite <tt>OptionParser</tt> features are simply not here.
67
+ You know that cool thing you can do where you tell <tt>OptionParser</tt> the
68
+ class of the kind of object you would like to get for a particular argument?
69
+ Do you like that one? Well, too bad. We don't have that one. Deal with it.
70
+
71
+ == LICENSE:
72
+
73
+ (The MIT License)
74
+
75
+ Copyright (c) 2008 Alex Vollmer
76
+
77
+ Permission is hereby granted, free of charge, to any person obtaining
78
+ a copy of this software and associated documentation files (the
79
+ 'Software'), to deal in the Software without restriction, including
80
+ without limitation the rights to use, copy, modify, merge, publish,
81
+ distribute, sublicense, and/or sell copies of the Software, and to
82
+ permit persons to whom the Software is furnished to do so, subject to
83
+ the following conditions:
84
+
85
+ The above copyright notice and this permission notice shall be
86
+ included in all copies or substantial portions of the Software.
87
+
88
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
89
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
90
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
91
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
92
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
93
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
94
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/bin/sample_parser ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), "../lib/clip")
4
+
5
+ ##
6
+ # This is a very simple example of how to use Clip
7
+ p = Clip do |c|
8
+ c.optional 's', 'server', :desc => 'The server name', :default => 'localhost'
9
+ c.optional 'p', 'port', :desc => 'The port', :default => 8080
10
+ c.optional 'f', 'files', :desc => 'Files to upload', :multi => true
11
+ c.flag 'v', 'verbose', :desc => 'Make it verbose, man'
12
+ end
13
+
14
+ printf("%10s %-20s\n", "attribute", "value")
15
+ [:server, :port, :verbose?].each do |att|
16
+ printf("%10s %-20s\n", att, p.send(att))
17
+ end
18
+ printf("%10s %-20s\n", "files", p.files.inspect)
data/lib/clip.rb ADDED
@@ -0,0 +1,324 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ##
4
+ # Parse arguments (defaults to <tt>ARGV</tt>) with the Clip::Parser
5
+ # configured in the given block. This is the main method you
6
+ # call to get the ball rolling.
7
+ def Clip(args=ARGV)
8
+ parser = Clip::Parser.new
9
+ raise "Dontcha wanna configure your parser?" unless block_given?
10
+ yield parser
11
+ parser.parse(args)
12
+ parser
13
+ end
14
+
15
+ module Clip
16
+ VERSION = "0.0.1"
17
+
18
+ ##
19
+ # Indicates that the parser was incorrectly configured in the
20
+ # block yielded by the +parse+ method.
21
+ class IllegalConfiguration < Exception
22
+ end
23
+
24
+ class Parser
25
+ ##
26
+ # Returns any remaining command line arguments that were not parsed
27
+ # because they were neither flags or option/value pairs
28
+ attr_reader :remainder
29
+
30
+ ##
31
+ # Declare an optional parameter for your parser. This creates an accessor
32
+ # method matching the <tt>long</tt> parameter. The <tt>short</tt> parameter
33
+ # indicates the single-letter equivalent. Options that use the '-'
34
+ # character as a word separator are converted to method names using
35
+ # '_'. For example the name 'exclude-files' would create a method named
36
+ # <tt>exclude_files</tt>.
37
+ #
38
+ # When the <tt>:multi</tt> option is enabled, the associated accessor
39
+ # method will return an <tt>Array</tt> instead of a single scalar value.
40
+ # === options
41
+ # Valid options include:
42
+ # * <tt>desc</tt>: a helpful description (used for printing usage)
43
+ # * <tt>default</tt>: a default value to provide if one is not given
44
+ # * <tt>multi</tt>: indicates that mulitple values are okay for this param.
45
+ #
46
+ # Note that specifying the <tt>:multi</tt> option means that the parameter
47
+ # can be specified several times with different values, or that a single
48
+ # comma-separated value can be specified which will then be broken up into
49
+ # separate tokens.
50
+ def optional(short, long, options={})
51
+ short = short.to_sym
52
+ long = long.to_sym
53
+ check_args(short, long)
54
+
55
+ eval <<-EOF
56
+ def #{long}=(val)
57
+ @#{long} = val
58
+ end
59
+
60
+ def #{long}
61
+ @#{long}
62
+ end
63
+ EOF
64
+
65
+ self.options[long] = Option.new(short, long, options)
66
+ self.options[short] = self.options[long]
67
+ self.order << self.options[long]
68
+ end
69
+
70
+ alias_method :opt, :optional
71
+
72
+ ##
73
+ # Declare a required parameter for your parser. If this parameter
74
+ # is not provided in the parsed content, the parser instance
75
+ # will be invalid (i.e. where valid? returns <tt>false</tt>).
76
+ #
77
+ # This method takes the same options as the optional method.
78
+ def required(short, long, options={})
79
+ optional(short, long, options.merge({ :required => true }))
80
+ end
81
+
82
+ alias_method :req, :required
83
+
84
+ ##
85
+ # Declare a parameter as a simple boolean flag. This declaration
86
+ # will create a "question" method matching the given <tt>long</tt>.
87
+ # For example, declaring with the name of 'verbose' will create a
88
+ # method on your parser called <tt>verbose?</tt>.
89
+ # === options
90
+ # Valid options are:
91
+ # * <tt>desc</tt>: Descriptive text for the flag
92
+ def flag(short, long, options={})
93
+ short = short.to_sym
94
+ long = long.to_sym
95
+
96
+ check_args(short, long)
97
+
98
+ eval <<-EOF
99
+ def flag_#{long}
100
+ @#{long} = true
101
+ end
102
+
103
+ def #{long}?
104
+ return @#{long} || false
105
+ end
106
+ EOF
107
+
108
+ self.options[long] = Flag.new(short, long, options)
109
+ self.options[short] = self.options[long]
110
+ self.order << self.options[long]
111
+ end
112
+
113
+ def initialize # :nodoc:
114
+ @errors = {}
115
+ @valid = true
116
+ end
117
+
118
+ ##
119
+ # Parse the given <tt>args</tt> and set the corresponding instance
120
+ # fields to the given values. If any errors occurred during parsing
121
+ # you can get them from the <tt>Hash</tt> returned by the +errors+ method.
122
+ def parse(args)
123
+ @valid = true
124
+ args = args.split(/\s+/) unless args.kind_of?(Array)
125
+ consumed = []
126
+ if args.member?("--help")
127
+ puts help
128
+ exit 0
129
+ end
130
+ param, value = nil, nil
131
+
132
+ args.each do |token|
133
+ case token
134
+ when /^-(-)?\w/
135
+ consumed << token
136
+ param = token.sub(/^-(-)?/, '').sub('-', '_').to_sym
137
+ value = nil
138
+ else
139
+ if param
140
+ consumed << token
141
+ value = token
142
+ end
143
+ end
144
+
145
+ option = options[param]
146
+ if option
147
+ if (value.nil? && option.kind_of?(Flag)) || value
148
+ option.process(self, value)
149
+ end
150
+ else
151
+ @errors[param] = "Unrecoginzed parameter"
152
+ @valid = false
153
+ next
154
+ end
155
+
156
+ unless value.nil?
157
+ param = nil
158
+ value = nil
159
+ end
160
+ end
161
+
162
+ @remainder = args - consumed
163
+
164
+ # Find required options that are missing arguments
165
+ options.each do |param, opt|
166
+ if opt.kind_of?(Option) and self.send(opt.long).nil?
167
+ if opt.required?
168
+ @valid = false
169
+ @errors[opt.long.to_sym] = "Missing required parameter: #{opt.long}"
170
+ elsif opt.has_default?
171
+ opt.process(self, opt.default)
172
+ end
173
+ end
174
+ end
175
+ end
176
+
177
+ ##
178
+ # Indicates whether or not the parsing process succeeded. If this
179
+ # returns <tt>false</tt> you probably just want to print out a call
180
+ # to the to_s method.
181
+ def valid?
182
+ @valid
183
+ end
184
+
185
+ ##
186
+ # Returns a <tt>Hash</tt> of errors (by the long name) of any errors
187
+ # encountered during parsing. If you simply want to display error
188
+ # messages to the user, you can just print out a call to the
189
+ # to_s method.
190
+ def errors
191
+ @errors
192
+ end
193
+
194
+ ##
195
+ # Returns a formatted <tt>String</tt> indicating the usage of the parser
196
+ def help
197
+ out = ""
198
+ out << "Usage:\n"
199
+ order.each do |option|
200
+ out << "#{option.usage}\n"
201
+ end
202
+ out
203
+ end
204
+
205
+ ##
206
+ # Returns a formatted <tt>String</tt> of the +help+ method prefixed by
207
+ # any parsing errors. Either way you have _one_ method to call to
208
+ # let your users know what to do.
209
+ def to_s
210
+ out = ""
211
+ unless valid?
212
+ out << "Errors:\n"
213
+ errors.each do |field, msg|
214
+ out << "#{field}: #{msg}\n"
215
+ end
216
+ end
217
+ out << help
218
+ end
219
+
220
+ def options # :nodoc:
221
+ (@options ||= {})
222
+ end
223
+
224
+ def order # :nodoc:
225
+ (@order ||= [])
226
+ end
227
+
228
+ private
229
+ def check_args(short, long)
230
+ short = short.to_sym
231
+ long = long.to_sym
232
+
233
+ if long == :help
234
+ raise IllegalConfiguration.new("You cannot override the built-in 'help' parameter")
235
+ end
236
+
237
+ if short == :h
238
+ raise IllegalConfiguration.new("You cannot override the built-in 'h' parameter")
239
+ end
240
+
241
+ if self.options.has_key?(long)
242
+ raise IllegalConfiguration.new("You have already defined a parameter/flag for #{long}")
243
+ end
244
+
245
+ if self.options.has_key?(short)
246
+ raise IllegalConfiguration.new("You already have a defined parameter/flag for the short key '#{short}")
247
+ end
248
+ end
249
+ end
250
+
251
+ class Option # :nodoc:
252
+ attr_accessor :long, :short, :description, :default, :required, :multi
253
+
254
+ def initialize(short, long, options)
255
+ @short = short
256
+ @long = long
257
+ @description = options[:desc]
258
+ @default = options[:default]
259
+ @required = options[:required]
260
+ @multi = options[:multi]
261
+ end
262
+
263
+ def process(parser, value)
264
+ if @multi
265
+ current = parser.send(@long) || []
266
+ current.concat(value.split(','))
267
+ parser.send("#{@long}=".to_sym, current)
268
+ else
269
+ parser.send("#{@long}=".to_sym, value)
270
+ end
271
+ end
272
+
273
+ def required?
274
+ @required == true
275
+ end
276
+
277
+ def has_default?
278
+ not @default.nil?
279
+ end
280
+
281
+ def multi?
282
+ @multi == true
283
+ end
284
+
285
+ def usage
286
+ out = sprintf('-%-2s --%-10s %s',
287
+ @short,
288
+ @long.to_s.gsub('_', '-').to_sym,
289
+ @description)
290
+ out << " (defaults to '#{@default}')" if @default
291
+ out << " REQUIRED" if @required
292
+ out
293
+ end
294
+ end
295
+
296
+ class Flag # :nodoc:
297
+
298
+ attr_accessor :long, :short, :description
299
+
300
+ ##
301
+ # nodoc
302
+ def initialize(short, long, options)
303
+ @short = short
304
+ @long = long
305
+ @description = options[:desc]
306
+ end
307
+
308
+ def process(parser, value)
309
+ parser.send("flag_#{@long}".to_sym)
310
+ end
311
+
312
+ def required?
313
+ false
314
+ end
315
+
316
+ def has_default?
317
+ false
318
+ end
319
+
320
+ def usage
321
+ sprintf('-%-2s --%-10s %s', @short, @long, @description)
322
+ end
323
+ end
324
+ end
data/spec/clip_spec.rb ADDED
@@ -0,0 +1,269 @@
1
+ require "#{File.dirname(__FILE__)}/../lib/clip"
2
+ require "rubygems"
3
+ require "spec"
4
+
5
+ class HaveErrors
6
+
7
+ def matches?(target)
8
+ @target = target
9
+ not @target.errors.empty?
10
+ end
11
+
12
+ def failure_message
13
+ "expected #{@target} to have errors"
14
+ end
15
+
16
+ def negative_failure_message
17
+ "expected #{@target} to have no errors, but... #{@target.errors.inspect}"
18
+ end
19
+ end
20
+
21
+ def have_errors
22
+ HaveErrors.new
23
+ end
24
+
25
+ class HaveErrorsOn
26
+ def initialize(expected)
27
+ @expected = expected
28
+ end
29
+
30
+ def matches?(target)
31
+ @target = target
32
+ not @target.errors[@expected.to_sym].nil?
33
+ end
34
+
35
+ def failure_message
36
+ "expected error message for #{@expected} on #{@target}"
37
+ end
38
+
39
+ def negative_failure_message
40
+ "unexpected error message for #{@expected} on #{@target}"
41
+ end
42
+ end
43
+
44
+ def have_errors_on(expected)
45
+ HaveErrorsOn.new(expected)
46
+ end
47
+
48
+ describe Clip do
49
+
50
+ def parse(line)
51
+ Clip(line) do |p|
52
+ p.flag 'v', 'verbose', :desc => 'Provide verbose output'
53
+ p.optional 's', 'server', :desc => 'The hostname', :default => 'localhost'
54
+ p.optional 'p', 'port', :desc => 'The port number', :default => 8080
55
+ p.required 'f', 'files', :desc => 'Files to upload', :multi => true
56
+ p.optional 'e', 'exclude_from', :desc => 'Directories to exclude'
57
+ end
58
+ end
59
+
60
+ describe "When long command-line parameters are parsed" do
61
+
62
+ it "should create accessor methods for declarations" do
63
+ parser = parse('')
64
+ parser.should respond_to(:server)
65
+ parser.should respond_to(:server=)
66
+ parser.should respond_to(:port)
67
+ parser.should respond_to(:port)
68
+ parser.should respond_to(:files)
69
+ parser.should respond_to(:files=)
70
+ parser.should respond_to(:verbose?)
71
+ parser.should respond_to(:flag_verbose)
72
+ end
73
+
74
+ it "should set fields for flags to 'true'" do
75
+ parser = parse('--verbose --files foo')
76
+ parser.should be_verbose
77
+ parser.should be_valid
78
+ parser.should_not have_errors
79
+ end
80
+
81
+ it "should set fields for flags with the given values" do
82
+ parser = parse('--server localhost --port 8080 --files foo')
83
+ parser.server.should eql("localhost")
84
+ parser.port.should eql("8080")
85
+ parser.should be_valid
86
+ parser.should_not have_errors
87
+ end
88
+
89
+ it "should map flags with '-' to methods with '_'" do
90
+ parser = parse('--exclude-from /Users --files foo')
91
+ parser.exclude_from.should eql("/Users")
92
+ parser.should be_valid
93
+ parser.should_not have_errors
94
+ end
95
+
96
+ it "should be invalid for unknown flags" do
97
+ parser = parse('--non-existent')
98
+ parser.should_not be_valid
99
+ parser.should have_errors_on(:non_existent)
100
+ end
101
+ end
102
+
103
+ describe "When short (single-letter) command-line parse are parsed" do
104
+
105
+ it "should set flags to true" do
106
+ parser = parse("-v --files foo")
107
+ parser.should be_verbose
108
+ parser.should_not have_errors
109
+ parser.should be_valid
110
+ end
111
+
112
+ it "should set fields for short options" do
113
+ parser = parse("-s localhost -p 8080 --files foo")
114
+ parser.should_not have_errors
115
+ parser.should be_valid
116
+ parser.server.should eql("localhost")
117
+ parser.port.should eql("8080")
118
+ parser.should_not be_verbose
119
+ end
120
+ end
121
+
122
+ describe "When parameters are marked as required" do
123
+
124
+ it "should be invalid when there are missing arguments" do
125
+ parser = parse('--server localhost')
126
+ parser.should_not be_valid
127
+ parser.should have_errors_on(:files)
128
+ end
129
+ end
130
+
131
+ describe "When parameters are marked with defaults" do
132
+
133
+ it "should provide default parameter values when none are parsed" do
134
+ parser = parse('--files foo')
135
+ parser.should be_valid
136
+ parser.should_not have_errors
137
+ parser.server.should eql("localhost")
138
+ parser.port.should eql(8080)
139
+ end
140
+ end
141
+
142
+ describe "Multi-valued parameters" do
143
+
144
+ it "should handle multiple value for the same parameter" do
145
+ parser = parse("--files foo --files bar --files baz")
146
+ parser.should be_valid
147
+ parser.should_not have_errors
148
+ parser.files.should == %w[foo bar baz]
149
+ end
150
+
151
+ it "should handle comma-separated values as multiples" do
152
+ parser = parse("--files foo,bar,baz")
153
+ parser.should be_valid
154
+ parser.should_not have_errors
155
+ parser.files.should == %w[foo bar baz]
156
+ end
157
+ end
158
+
159
+ describe "Help output" do
160
+ it "should print out some sensible usage info for to_s" do
161
+ out = parse('--files foo').to_s.split("\n")
162
+ out[0].should match(/Usage/)
163
+ out[1].should match(/-v\s+--verbose\s+Provide verbose output/)
164
+ out[2].should match(/-s\s+--server\s+The hostname.*default.*localhost/)
165
+ out[3].should match(/-p\s+--port\s+The port number/)
166
+ out[4].should match(/-f\s+--files\s+Files to upload.*REQUIRED/)
167
+ out[5].should match(/-e\s+--exclude-from\s+Directories to exclude/)
168
+ end
169
+
170
+ it "should include error messages in to_s" do
171
+ parser = parse('')
172
+ out = parser.to_s.split("\n")
173
+ out[0].should match(/Error/)
174
+ out[1].should match(/missing required.*files/i)
175
+ out[2..-1].join("\n").strip.should == parser.help.strip
176
+ end
177
+ end
178
+
179
+ describe "Additional arguments" do
180
+ it "should be made available" do
181
+ parser = parse('--files foo alpha bravo')
182
+ parser.files.should == %w[foo]
183
+ parser.remainder.should == %w[alpha bravo]
184
+ end
185
+ end
186
+
187
+ describe "Declaring bad options and flags" do
188
+
189
+ def misconfig_parser
190
+ lambda do
191
+ Clip("foo") do |c|
192
+ yield c
193
+ end
194
+ end.should raise_error(Clip::IllegalConfiguration)
195
+ end
196
+
197
+ it "should reject :help as a flag name" do
198
+ misconfig_parser { |c| c.flag 'x', 'help' }
199
+ end
200
+
201
+ it "should reject :help as an optional name" do
202
+ misconfig_parser { |c| c.optional 'x', 'help' }
203
+ end
204
+
205
+ it "should reject 'h' as a short flag name" do
206
+ misconfig_parser { |c| c.flag 'h', 'foo' }
207
+ end
208
+
209
+ it "should reject 'h' as a short parameter name" do
210
+ misconfig_parser { |c| c.optional 'h', 'foo' }
211
+ end
212
+
213
+ it "should reject redefining an existing long name for two options" do
214
+ misconfig_parser do |c|
215
+ c.optional 'f', 'foo'
216
+ c.optional 'x', 'foo'
217
+ end
218
+ end
219
+
220
+ it "should reject redefining an existing long name for an option & flag" do
221
+ misconfig_parser do |c|
222
+ c.optional 'f', 'foo'
223
+ c.flag 'x', 'foo'
224
+ end
225
+ end
226
+
227
+ it "should reject redefining the same flag" do
228
+ misconfig_parser do |c|
229
+ c.flag 'f', 'foo'
230
+ c.flag 'x', 'foo'
231
+ end
232
+ end
233
+
234
+ it "should reject defining a flag with an option" do
235
+ misconfig_parser do |c|
236
+ c.flag 'f', 'foo'
237
+ c.optional 'x', 'foo'
238
+ end
239
+ end
240
+
241
+ it "should reject redefining an existing short name for options" do
242
+ misconfig_parser do |c|
243
+ c.optional 'f', 'foo'
244
+ c.optional 'f', 'files'
245
+ end
246
+ end
247
+
248
+ it "should reject redefining a short option with a flag" do
249
+ misconfig_parser do |c|
250
+ c.optional 'f', 'foo'
251
+ c.flag 'f', 'fail'
252
+ end
253
+ end
254
+
255
+ it "should reject redefining a short flag with a flag" do
256
+ misconfig_parser do |c|
257
+ c.flag 'f', 'fail'
258
+ c.flag 'f', 'foo'
259
+ end
260
+ end
261
+
262
+ it "should reject redefining a flag with an optional" do
263
+ misconfig_parser do |c|
264
+ c.flag 'f', 'fail'
265
+ c.optional 'f', 'foo'
266
+ end
267
+ end
268
+ end
269
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clip
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Alex Vollmer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-04-10 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.5.1
23
+ version:
24
+ description: Command-line parsing made short and sweet
25
+ email:
26
+ - alex.vollmer@gmail.com
27
+ executables:
28
+ - sample_parser
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - History.txt
33
+ - README.txt
34
+ files:
35
+ - History.txt
36
+ - README.txt
37
+ - bin/sample_parser
38
+ - lib/clip.rb
39
+ - spec/clip_spec.rb
40
+ has_rdoc: true
41
+ homepage: http://clip.rubyforge.org
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --main
45
+ - README.txt
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project: clip
63
+ rubygems_version: 1.1.0
64
+ signing_key:
65
+ specification_version: 2
66
+ summary: Command-line parsing made short and sweet
67
+ test_files: []
68
+