parseOpts 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/CHANGELOG +9 -0
  2. data/LICENSE +19 -0
  3. data/README +65 -0
  4. data/Rakefile +40 -0
  5. data/lib/parseOpts.rb +287 -0
  6. data/test/test_parseOpts.rb +271 -0
  7. metadata +58 -0
data/CHANGELOG ADDED
@@ -0,0 +1,9 @@
1
+ Changelog
2
+ =========
3
+
4
+ 15/04/09:
5
+ parseArgs-0.0.1 released
6
+
7
+ 04/05/09:
8
+ Projects renamed parseOpts to avoid clash with existing parseArgs
9
+ parseOpts-0.0.2 released
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2009 Jon Coppeard
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,65 @@
1
+ =parseOpts
2
+
3
+ parseOpts is (yes, another) ruby library for parsing commandline options and arguments.
4
+
5
+ It has the following features:
6
+
7
+ - parses options (switches) as well as arguments
8
+ - options and arguments are specified in an easy to read, declarative format
9
+ - automatically generates a usage message if incorrect arguments are given
10
+ - it is small (currently < 300 lines of code)
11
+
12
+ ==Description
13
+
14
+ A specification written in ruby describes the allowable command line inputs.
15
+
16
+ Individual command line parameters are divided into options and arguments.
17
+
18
+ Options are command line switches, and start with at least one '-' character. They can occur in any
19
+ order, and may or may not take an argument. They may occur multiple times if allowed.
20
+
21
+ Arguments are parameters that may be constrained, either as a choice of options from a list, or by a
22
+ regular expression. It is possible to specificy how often an argument can occur.
23
+
24
+ All options are parsed befor any arguments. All mandatory options and arguments must be present in
25
+ the command line otherwise parsing fails.
26
+
27
+ ==Usage
28
+
29
+ For a simple example, see the following (from examples/example_grep.rb):
30
+
31
+ require "parseOpts"
32
+
33
+ opts = ParseOpts.run do
34
+ opt '-v|--invert-match', 'Select non-matching lines'
35
+ opt '-m|--max-count NUM', 'Stop reading a file after NUM matches'
36
+ arg 'pattern', 'Regular expression to match'
37
+ arg 'file+', 'File to search in'
38
+ end
39
+
40
+ $invert_match = opts['-v']
41
+ $max_count = opts['-m'] ? opts['-m'].to_i : nil
42
+ $pattern = Regexp.new(opts['pattern'])
43
+ $files = opts['file']
44
+
45
+ Running the script with no arguments generates the following usage message:
46
+
47
+ usage: example_grep.rb options* pattern file+
48
+
49
+ Options:
50
+ -v, --invert-match: Select non-matching lines
51
+ -m, --max-count NUM: Stop reading a file after NUM matches
52
+
53
+ Arguments:
54
+ pattern: Regular expression to match
55
+ file: File to search in
56
+
57
+ ==Ideas for future work
58
+
59
+ - define classes for commonly used types to parse argument strings (eg integer, float, etc)
60
+ - format help so lines wrap nicely
61
+ - allow sets of arguments and options in any order (allows subcommands)
62
+
63
+ ==Contact
64
+
65
+ Please contact jon at coppeard dot net with bug reports and suggestions.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require './lib/parseOpts'
6
+
7
+ source_files = Dir['lib/*.rb'] + Dir['test/*.rb'] + [ 'Rakefile' ]
8
+ package_files = %w[README CHANGELOG LICENSE] + source_files
9
+
10
+ Rake::TestTask.new :test do |t|
11
+ t.test_files = [ "test/test*" ]
12
+ end
13
+
14
+ desc "Build documentation"
15
+ task :rdoc => source_files
16
+ Rake::RDocTask.new( :rdoc ) do |rdoc|
17
+ rdoc.rdoc_dir = "api"
18
+ rdoc.title = "parseOpts - a library to parse commandline options and arguments"
19
+ rdoc.option_string << '--line-numbers --inline-source --main README'
20
+ rdoc.rdoc_files.include 'README'
21
+ rdoc.rdoc_files.include 'lib/parseOpts.rb'
22
+ end
23
+
24
+ desc "Build the gem"
25
+ task :gem => package_files
26
+ spec = Gem::Specification.new do |spec|
27
+ spec.name = 'parseOpts'
28
+ spec.version = ParseOpts::VERSION
29
+ spec.summary = "Library to parse commandline options and arguments"
30
+ spec.description = ""
31
+ spec.author = "Jon Coppeard"
32
+ spec.email = "jon at coppeard dot net"
33
+ spec.files = package_files
34
+ spec.has_rdoc = true
35
+ spec.test_file = 'test/test_parseOpts.rb'
36
+ spec.rubyforge_project = 'parseOpts'
37
+ end
38
+ Rake::GemPackageTask.new(spec) do |pkg|
39
+ pkg.need_tar = true
40
+ end
data/lib/parseOpts.rb ADDED
@@ -0,0 +1,287 @@
1
+ # parseOpts parses commandline options and arguments.
2
+ #
3
+ # For more information, please see the {README}[link:files/README.html]
4
+ class ParseOpts
5
+
6
+ VERSION = "0.0.2"
7
+
8
+ class OptSpec # :nodoc: all
9
+
10
+ attr_reader :matches, :arg, :default, :desc, :multiple
11
+
12
+ def initialize(matches, arg, desc, multiple, default)
13
+ raise ArgumentError, "Options must start with -" unless matches.all? {|m| m =~ /^-/ }
14
+ raise ArgumentError, 'Default not allowed unless argument is present' if default && !arg
15
+ @matches, @arg, @desc, @multiple, @default =
16
+ matches, arg, desc, multiple, default
17
+ end
18
+
19
+ def name
20
+ @matches[0]
21
+ end
22
+
23
+ def init
24
+ @matched = false
25
+ @value = if @multiple
26
+ @arg ? [] : 0
27
+ else
28
+ nil
29
+ end
30
+ end
31
+
32
+ def match?(args)
33
+ (!@matched || @multiple) && (@matches.include?(args[0])) && (!@arg || args.size >= 2)
34
+ end
35
+
36
+ def process(args)
37
+ args.shift
38
+ r = @arg ? args.shift : true
39
+ if @multiple && @arg
40
+ @value << r
41
+ elsif @multiple
42
+ @value += 1
43
+ else
44
+ @value = r
45
+ end
46
+ @matched = true
47
+ end
48
+
49
+ def value
50
+ !@matched && @default ? @default : @value
51
+ end
52
+
53
+ end
54
+
55
+ class ArgSpec # :nodoc: all
56
+
57
+ QuantOptions =
58
+ {
59
+ "" => [ false, false ],
60
+ "?" => [ true, false ],
61
+ "*" => [ true, true ],
62
+ "+" => [ false, true ]
63
+ }
64
+
65
+ attr_reader :name, :desc, :multiple, :optional, :quant, :default
66
+
67
+ def initialize(name, quant, desc, pred, default)
68
+ @name, @quant, @desc, @pred, @default = name, quant, desc, pred, default
69
+ raise ArgumentError, "Unknown quantifier" unless QuantOptions.has_key?(quant)
70
+ @optional, @multiple = *QuantOptions[quant]
71
+ raise ArgumentError, "Default not allowed for mandatory argument" if @default && !@optional
72
+ end
73
+
74
+ def init
75
+ @value = @multiple ? [] : nil
76
+ @matched = false
77
+ end
78
+
79
+ def match?(args)
80
+ @pred ? @pred.call(args[0]) : true
81
+ end
82
+
83
+ def process(args)
84
+ @value = if @multiple
85
+ a = [args.shift]
86
+ a << args.shift while args.size > 0 && match?(args)
87
+ a
88
+ else
89
+ args.shift
90
+ end
91
+ @matched = true
92
+ end
93
+
94
+ def value
95
+ @default && !@matched ? @default : @value
96
+ end
97
+
98
+ end
99
+
100
+ # An exception raised by ParseOpts::parse when the command line arguments don't conform to the
101
+ # specification.
102
+ class BadUsageError < Exception; end
103
+
104
+ # Create a new object that parses the command line specified by the given block.
105
+ #
106
+ # The block is evaluated in the context of the new object instance and should call its summary,
107
+ # opt and arg methods.
108
+ def initialize (&block)
109
+ @summary = nil
110
+ @optList, @argList = [], []
111
+ instance_eval(&block)
112
+ end
113
+
114
+ # Set the summary text that is output in the usage message.
115
+ def summary(string)
116
+ @summary = string
117
+ end
118
+
119
+ # Add an option.
120
+ #
121
+ # [spec] A string specifying the option name and alternatives, and whether the option can take an
122
+ # argument. Alternatives are specified by listing them separated by a '|' character and
123
+ # an argument is specified by following that with a space and the argument name.
124
+ #
125
+ # The first word of the specification is the name, and is used as the hash key to return
126
+ # its value.
127
+ #
128
+ # For example: <tt>"-l|--long-name argName"</tt> will recognise both <tt>-l</tt> and
129
+ # <tt>--long-name</tt>, and will take an argument. The key used for the result hash is
130
+ # "-l".
131
+ #
132
+ # [desc] Human readable description of the option.
133
+ # [params] An optional hash of additional parameters.
134
+ #
135
+ # Allowed additonal parameters are:
136
+ # [:multiple] Indicates that this option is allowed to occur more than once. In this case the
137
+ # value returned for this option will be an array.
138
+ # [:default] The default value if this option is not passed. Only allowed when the option takes
139
+ # an argument
140
+ def opt(spec, desc, params = {})
141
+ words = spec.split(/ /)
142
+ raise "Bad format for option spec '#{spec}'" unless words.size <= 2
143
+ arg = words[1]
144
+ matches = words[0].split(/\|/)
145
+ default = params.delete(:default)
146
+ multiple = params.delete(:multiple)
147
+ raise ArgumentError, "Unknown keyword arguments passed: #{params.keys.join(", ")}" unless
148
+ params.size == 0
149
+ @optList << OptSpec.new(matches, arg, desc, multiple, default)
150
+ end
151
+
152
+ # Add an argument.
153
+ #
154
+ # [spec] The name of the argument, possibly followed by a quantifier. The name itself is used
155
+ # as the hash key to return the argument's value(s)
156
+ # [desc] Human readable description of the argument.
157
+ # [params] An optional hash of additional parameters.
158
+ #
159
+ # Possible argument quantifiers are:
160
+ # [?] Indicates that this argument may occur zero or once only
161
+ # [*] Indicates that this argument may occur zero or more times
162
+ # [+] Indicates that this argument may occur one or more times
163
+ #
164
+ # If no quantifier is given, the argument must occur exactly once. If an argument can occur more
165
+ # than once, the value returned for it will be an array of the values passed.
166
+ #
167
+ # Allowed keyword arguments are:
168
+ # [:choice] An array contating the allowed values of this argument.
169
+ #
170
+ # [:match] An object constraining the values of this argument. The matching is done with ruby's
171
+ # <tt>===</tt> operator, so any object that supports this will work - e.g. a regular
172
+ # expression.
173
+ # [:default] A default value if the argument is not present.
174
+ def arg(spec, desc, params = {})
175
+ name = spec.sub(/(\?|\*|\+)$/, "")
176
+ quant = $1 || ""
177
+ pred = if params.has_key?(:choice)
178
+ choices = params.delete(:choice)
179
+ desc += "\n One of: " + choices.join(' ')
180
+ lambda {|x| choices.include?(x) }
181
+ elsif params.has_key?(:match)
182
+ match = params.delete(:match)
183
+ lambda {|x| match === x }
184
+ else
185
+ nil
186
+ end
187
+ default = params.delete(:default)
188
+ raise ArgumentError, "Unknown keyword arguments passed: #{params.keys.join(", ")}" unless
189
+ params.size == 0
190
+ @argList << ArgSpec.new(name, quant, desc, pred, default)
191
+ end
192
+
193
+ # Parse the command line arguments given and return a hash where the keys are the names of the
194
+ # options and arguments and the values are those that have been extracted from the command line.
195
+ #
196
+ # Options are parsed first, and may be present in any order. Option parsing stops when there are
197
+ # no more optons, or if <tt>"--"</tt> is encountered.
198
+ #
199
+ # The remaining input is parsed as arguments.
200
+ #
201
+ # This method raised BadUsageError if the parameters do not conform to the specification given
202
+ # when the object was created.
203
+ def parse(args)
204
+ allSpecs = @optList + @argList
205
+ allSpecs.each {|spec| spec.init }
206
+ parse_next_opt(args) while args.size > 0 && args[0] =~ /^-/ && args[0] != '--'
207
+ args.shift if args[0] == '--'
208
+ @argPos = 0
209
+ while args.size > 0 && @argPos < @argList.size do
210
+ parse_next_arg(@argList[@argPos], args)
211
+ @argPos += 1
212
+ end
213
+ raise BadUsageError if args.size > 0 || @argList[@argPos..-1].find {|s| !s.optional }
214
+ result = {}
215
+ allSpecs.each {|spec| result[spec.name] = spec.value if spec.value}
216
+ return result
217
+ end
218
+
219
+ # Generate a usage message explaining the allowed syntax of the command line.
220
+ def usage_message
221
+ name = $0 =~ /[^\/]+$/ ? $& : ''
222
+ usageArgs = @argList.collect{|s| s.name + s.quant }
223
+ usageArgs.unshift('options*') if @optList.size > 0
224
+ usageArgs.unshift(name)
225
+
226
+ lines = [ "usage: " + usageArgs.join(' ') ]
227
+ lines += [ "", @summary ] if @summary
228
+
229
+ if @optList.size > 0
230
+ lines += [ "", "Options:" ] + @optList.map do |opt|
231
+ line = " " + opt.matches.join(", ")
232
+ line += " " + opt.arg if opt.arg
233
+ line += ": " + opt.desc
234
+ if opt.default
235
+ d = opt.default
236
+ d = d.kind_of?(Array) ? d.join(' ') : d.to_s
237
+ line += "\n Default: " + d
238
+ end
239
+ line
240
+ end
241
+ end
242
+
243
+ if @argList.size > 0
244
+ lines += [ "", "Arguments:" ] + @argList.map do |arg|
245
+ line = " " + arg.name + ": " + arg.desc
246
+ if arg.default
247
+ d = arg.default
248
+ d = d.kind_of?(Array) ? d.join(' ') : d.to_s
249
+ line += "\n Default: " + d
250
+ end
251
+ line
252
+ end
253
+ end
254
+
255
+ lines.join("\n")
256
+ end
257
+
258
+ # Convenience method to construct an parser object as specified by a block and call its parse
259
+ # method with the argument array given, or ARGV if it is ommitted.
260
+ #
261
+ # If parsing fails, the usage message is displayed on stderr and exit is called.
262
+ def ParseOpts.run (args = ARGV, &block)
263
+ parser = ParseOpts.new(&block)
264
+ begin
265
+ parser.parse(args)
266
+ rescue BadUsageError
267
+ $stderr.puts parser.usage_message
268
+ exit(1)
269
+ end
270
+ end
271
+
272
+ private
273
+
274
+ def parse_next_opt(args)
275
+ optSpec = @optList.find {|s| s.match? args } or raise BadUsageError, args[0]
276
+ optSpec.process(args)
277
+ end
278
+
279
+ def parse_next_arg(argSpec, args)
280
+ if !argSpec.match? args
281
+ raise BadUsageError unless argSpec.optional
282
+ else
283
+ argSpec.process(args)
284
+ end
285
+ end
286
+
287
+ end
@@ -0,0 +1,271 @@
1
+ #!/bin/ruby
2
+
3
+ require 'runit/testcase'
4
+ require 'runit/cui/testrunner'
5
+ require 'runit/testsuite'
6
+ require 'parseOpts'
7
+
8
+ class ParseOptsTests < RUNIT::TestCase
9
+
10
+ def words(string)
11
+ string.split /\s+/
12
+ end
13
+
14
+ def assert_ok(expected, string)
15
+ assert_no_exception do
16
+ assert_equal(expected, @parser.parse(words(string)))
17
+ end
18
+ end
19
+
20
+ def assert_bad(string)
21
+ assert_exception(ParseOpts::BadUsageError) { @parser.parse(words(string)) }
22
+ end
23
+
24
+ def test_empty
25
+ @parser = ParseOpts.new {}
26
+ assert_ok({}, '')
27
+ assert_bad('-x')
28
+ assert_bad('x')
29
+ end
30
+
31
+ def test_singleOption
32
+ @parser = ParseOpts.new do
33
+ opt '-t', 'test'
34
+ end
35
+ assert_ok({}, '')
36
+ assert_ok({'-t' => true}, '-t')
37
+ assert_bad('-t bar')
38
+ end
39
+
40
+ def test_optionWithArg
41
+ @parser = ParseOpts.new do
42
+ opt '-t FOO', 'test'
43
+ end
44
+ assert_ok({}, '')
45
+ assert_ok({'-t' => 'bar'}, '-t bar')
46
+ assert_bad('-t')
47
+ assert_bad('-t bar baz')
48
+ end
49
+
50
+ def test_multipleSingleOption
51
+ @parser = ParseOpts.new do
52
+ opt '-t', 'test', :multiple => true
53
+ end
54
+ assert_ok({'-t' => 0}, '')
55
+ assert_ok({'-t' => 1}, '-t')
56
+ assert_ok({'-t' => 2}, '-t -t')
57
+ end
58
+
59
+ def test_multipleOptionWithArg
60
+ @parser = ParseOpts.new do
61
+ opt '-t FOO', 'test', :multiple => true
62
+ end
63
+ assert_ok({'-t' => []}, '')
64
+ assert_ok({'-t' => ['bar']}, '-t bar')
65
+ assert_ok({'-t' => ['bar', 'baz']}, '-t bar -t baz')
66
+ end
67
+
68
+ def test_altOptions
69
+ @parser = ParseOpts.new do
70
+ opt '-a|--aaa', 'test'
71
+ opt '-b|--bbb|--whatever FOO', 'test'
72
+ end
73
+ assert_ok({'-a' => true}, '-a')
74
+ assert_ok({'-a' => true}, '--aaa')
75
+ assert_ok({'-b' => 'bar'}, '-b bar')
76
+ assert_ok({'-b' => 'bar'}, '--bbb bar')
77
+ assert_ok({'-b' => 'baz'}, '--whatever baz')
78
+ end
79
+
80
+ def test_combinationsOfOptions
81
+ @parser = ParseOpts.new do
82
+ opt '-a', 'test'
83
+ opt '-b ARG', 'test'
84
+ opt '-c', 'test', :multiple => true
85
+ opt '-d ARG', 'test', :multiple => true
86
+ end
87
+ assert_ok({'-a' => true, '-c' => 0, '-d' => []}, '-a')
88
+ assert_ok({'-b' => 'foo', '-c' => 0, '-d' => []}, '-b foo')
89
+ assert_ok({'-c' => 2, '-d' => []}, '-c -c')
90
+ assert_ok({'-c' => 0, '-d' => ['bar', 'baz']}, '-d bar -d baz')
91
+
92
+ expected = {'-a' => true, '-b' => 'foo', '-c' => 2, '-d' => ['bar', 'baz']}
93
+ assert_ok(expected, '-a -b foo -c -c -d bar -d baz')
94
+ assert_ok(expected, '-b foo -a -c -c -d bar -d baz')
95
+ assert_ok(expected, '-c -b foo -a -c -d bar -d baz')
96
+ assert_ok(expected, '-d bar -c -b foo -a -c -d baz')
97
+ end
98
+
99
+ def test_optionsWithDefaultArgs
100
+ @parser = ParseOpts.new do
101
+ opt '-b ARG', 'test', :default => 'def'
102
+ opt '-d ARG', 'test', :multiple => true, :default => ['foo']
103
+ end
104
+
105
+ assert_ok({'-b' => 'def', '-d' => ['foo']}, '')
106
+ assert_ok({'-b' => 'bar', '-d' => ['baz']}, '-b bar -d baz')
107
+
108
+ assert_exception(ArgumentError) { ParseOpts.new { opt '-a', '', :default => 'foo' } }
109
+ end
110
+
111
+ def test_optionsWithDefaultArgs2
112
+ @parser = ParseOpts.new do
113
+ opt '-b ARG', 'test', :default => 13
114
+ opt '-d ARG', 'test', :multiple => true, :default => [17]
115
+ end
116
+
117
+ assert_ok({'-b' => 13, '-d' => [17]}, '')
118
+ assert_ok({'-b' => 'bar', '-d' => ['baz']}, '-b bar -d baz')
119
+
120
+ assert_exception(ArgumentError) { ParseOpts.new { opt '-a', '', :default => 'foo' } }
121
+ end
122
+
123
+ def test_argRequired
124
+ @parser = ParseOpts.new do
125
+ arg 'arg', 'test'
126
+ end
127
+ assert_bad('')
128
+ assert_ok({'arg' => 'foo'}, 'foo')
129
+ assert_bad('foo bar')
130
+ end
131
+
132
+ def test_argOptional
133
+ @parser = ParseOpts.new do
134
+ arg 'arg?', 'test'
135
+ end
136
+ assert_ok({}, '')
137
+ assert_ok({'arg' => 'foo'}, 'foo')
138
+ assert_bad('foo bar')
139
+ end
140
+
141
+ def test_argZeroOrMore
142
+ @parser = ParseOpts.new do
143
+ arg 'arg*', 'test'
144
+ end
145
+ assert_ok({'arg' => []}, '')
146
+ assert_ok({'arg' => ['foo']}, 'foo')
147
+ assert_ok({'arg' => ['foo', 'bar']}, 'foo bar')
148
+ end
149
+
150
+ def test_argOneOrMore
151
+ @parser = ParseOpts.new do
152
+ arg 'arg+', 'test'
153
+ end
154
+ assert_bad('')
155
+ assert_ok({'arg' => ['foo']}, 'foo')
156
+ assert_ok({'arg' => ['foo', 'bar']}, 'foo bar')
157
+ end
158
+
159
+ def test_argRegexpMatch
160
+ @parser = ParseOpts.new do
161
+ arg 'arg', 'test', :match => /^\w-\d$/
162
+ end
163
+ assert_ok({'arg' => 'k-9'}, 'k-9')
164
+ assert_bad('foo')
165
+ end
166
+
167
+ def test_argArrayChoice
168
+ @parser = ParseOpts.new do
169
+ arg 'arg', 'test', :choice => ['foo', 'bar']
170
+ end
171
+ assert_ok({'arg' => 'bar'}, 'bar')
172
+ assert_bad('baz')
173
+ end
174
+
175
+ def test_argsWithDefaults
176
+ @parser = ParseOpts.new do
177
+ arg 'a?', 'test', :default => 'foo'
178
+ end
179
+
180
+ assert_ok({'a' => 'foo'}, '')
181
+ assert_ok({'a' => 'bar'}, 'bar')
182
+
183
+ @parser = ParseOpts.new do
184
+ arg 'a*', 'test', :default => ['bar']
185
+ end
186
+
187
+ assert_ok({'a' => ['bar']}, '')
188
+ assert_ok({'a' => ['foo']}, 'foo')
189
+
190
+ assert_exception(ArgumentError) { ParseOpts.new { arg 'a', '', :default => 'foo' } }
191
+ end
192
+
193
+ def test_combinationsOfArgs
194
+ @parser = ParseOpts.new do
195
+ arg 'a', 'test', :match => /^a$/
196
+ arg 'b?', 'test', :match => /^b$/
197
+ arg 'c*', 'test', :match => /^c$/
198
+ arg 'd+', 'test', :match => /^d$/
199
+ end
200
+
201
+ assert_ok({'a' => 'a', 'b' => 'b', 'c' => ['c'], 'd' => ['d']},
202
+ 'a b c d')
203
+ assert_ok({'a' => 'a', 'c' => [], 'd' => ['d']},
204
+ 'a d')
205
+ assert_ok({'a' => 'a', 'b' => 'b', 'c' => ['c', 'c'], 'd' => ['d', 'd']},
206
+ 'a b c c d d')
207
+ end
208
+
209
+ def test_optionsAndArgs
210
+ @parser = ParseOpts.new do
211
+ opt '-a', 'test opt a'
212
+ opt '-b ARG', 'test opt b'
213
+ opt '-c', 'test opt c', :multiple => true
214
+ opt '-d ARG', 'test opt d', :multiple => true
215
+ arg 'e', 'test arg e', :match => /^e$/
216
+ arg 'f?', 'test arg f', :match => /^f$/
217
+ arg 'g*', 'test arg g', :match => /^g$/
218
+ arg 'h+', 'test arg h', :match => /^h$/
219
+ end
220
+
221
+ assert_ok({'-a' => true, '-b' => 'foo', '-c' => 2, '-d' => ['bar', 'baz'],
222
+ 'e' => 'e', 'f' => 'f', 'g' => ['g'], 'h' => ['h']},
223
+ '-a -b foo -c -c -d bar -d baz e f g h')
224
+ end
225
+
226
+ def test_usageMessage
227
+ @parser = ParseOpts.new do
228
+ opt '-a', 'test opt a'
229
+ opt '-b ARG', 'test opt b', :default => "xxx"
230
+ opt '-c|--cc', 'test opt c', :multiple => true
231
+ opt '-d|--dd ARG', 'test opt d', :multiple => true, :default => ["yyy", "zzz"]
232
+ arg 'e', 'test arg e', :match => /^e$/
233
+ arg 'f?', 'test arg f', :match => /^f$/, :default => "aaa"
234
+ arg 'g*', 'test arg g', :match => /^g$/, :default => ["bbb", "ccc"]
235
+ arg 'h+', 'test arg h', :match => /^h$/
236
+ end
237
+
238
+ expectedUsage = <<END
239
+ usage: rake_test_loader.rb options* e f? g* h+
240
+
241
+ Options:
242
+ -a: test opt a
243
+ -b ARG: test opt b
244
+ Default: xxx
245
+ -c, --cc: test opt c
246
+ -d, --dd ARG: test opt d
247
+ Default: yyy zzz
248
+
249
+ Arguments:
250
+ e: test arg e
251
+ f: test arg f
252
+ Default: aaa
253
+ g: test arg g
254
+ Default: bbb ccc
255
+ h: test arg h
256
+ END
257
+
258
+ assert_equal(expectedUsage, @parser.usage_message + "\n")
259
+ end
260
+
261
+ def test_run
262
+ result = ParseOpts.run(['foo']) do
263
+ opt '-a', 'test opt a'
264
+ arg 'b', 'test arg b'
265
+ end
266
+ assert_equal('foo', result.delete('b'))
267
+ assert_equal({}, result)
268
+ end
269
+ end
270
+
271
+ RUNIT::CUI::TestRunner.run(ParseOptsTests.suite)
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: parseOpts
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Jon Coppeard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-06 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: ""
17
+ email: jon at coppeard dot net
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README
26
+ - CHANGELOG
27
+ - LICENSE
28
+ - lib/parseOpts.rb
29
+ - test/test_parseOpts.rb
30
+ - Rakefile
31
+ has_rdoc: true
32
+ homepage:
33
+ post_install_message:
34
+ rdoc_options: []
35
+
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project: parseOpts
53
+ rubygems_version: 1.3.1
54
+ signing_key:
55
+ specification_version: 2
56
+ summary: Library to parse commandline options and arguments
57
+ test_files:
58
+ - test/test_parseOpts.rb