opt-simple 0.7.4 → 0.7.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README +148 -40
- data/lib/opt_simple.rb +91 -77
- data/test/test_usage.rb +21 -2
- metadata +1 -1
data/README
CHANGED
@@ -37,6 +37,66 @@ It is recommended to install OptSimple using RubyGems:
|
|
37
37
|
|
38
38
|
== Examples
|
39
39
|
|
40
|
+
=== One example that shows a lot of the behavior you might use
|
41
|
+
|
42
|
+
require 'opt_simple'
|
43
|
+
|
44
|
+
min = 5
|
45
|
+
max = 15
|
46
|
+
|
47
|
+
options,arguments = OptSimple.new.parse_opts! do
|
48
|
+
argument %w[-i --infile], "Infile, multiple allowed", "FILE" do | arg |
|
49
|
+
accumulate_opt arg
|
50
|
+
end
|
51
|
+
|
52
|
+
option %w[-p --pattern --glob-pattern], "glob pattern","PATTERN"
|
53
|
+
|
54
|
+
option %w[-n -num --num-values],"Number of val","VAL" do |arg|
|
55
|
+
set_opt arg.to_i
|
56
|
+
end
|
57
|
+
|
58
|
+
option "--range", "range: min,max (both >0) default is #{min},#{max}" do | arg1,arg2 |
|
59
|
+
min = arg1.to_i
|
60
|
+
max = arg2.to_i
|
61
|
+
|
62
|
+
error "max must be greater than min" unless max > min
|
63
|
+
error "both must be >=0" if min < 0
|
64
|
+
end
|
65
|
+
|
66
|
+
flag %w[-v --verbose],"Verbosity. the more you set, the more we give" do
|
67
|
+
accumulate_opt
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
puts "Options"
|
73
|
+
puts options.inspect
|
74
|
+
|
75
|
+
puts "Arguments"
|
76
|
+
puts arguments.inspect
|
77
|
+
|
78
|
+
puts "ARGV"
|
79
|
+
puts ARGV
|
80
|
+
|
81
|
+
It prints out an automatic usage statement:
|
82
|
+
|
83
|
+
Usage: opt_ex.rb [options]
|
84
|
+
|
85
|
+
MANDATORY ARGS:
|
86
|
+
-i, --infile FILE Infile, multiple allowed
|
87
|
+
|
88
|
+
OPTIONS:
|
89
|
+
-p, --pattern, --glob-pattern PATTERN glob pattern
|
90
|
+
|
91
|
+
-n, -num, --num-values VAL Number of val
|
92
|
+
|
93
|
+
--range ARG range: min,max (both >0) default is 5,15
|
94
|
+
|
95
|
+
-v, --verbose Verbosity. the more you set, the more we give
|
96
|
+
|
97
|
+
-h, --help (for this help message)
|
98
|
+
|
99
|
+
|
40
100
|
=== A very simple example with no error checking. Use at your own risk!
|
41
101
|
|
42
102
|
require 'opt_simple'
|
@@ -46,7 +106,7 @@ It is recommended to install OptSimple using RubyGems:
|
|
46
106
|
}
|
47
107
|
|
48
108
|
options,arguments = OptSimple.new(defaults).parse_opts!
|
49
|
-
|
109
|
+
|
50
110
|
puts "Options"
|
51
111
|
puts options.inspect
|
52
112
|
|
@@ -107,46 +167,46 @@ It is recommended to install OptSimple using RubyGems:
|
|
107
167
|
|
108
168
|
=== An example that shows how to use 'accumulate_opt' on an option to create a list, and on a flag to increment a counter
|
109
169
|
|
110
|
-
require 'opt_simple'
|
111
|
-
|
112
|
-
verbosity = 0
|
113
|
-
|
114
|
-
options,arguments = OptSimple.new.parse_opts! do
|
115
|
-
option %w[-i --infile], "Infile, multiple allowed", "INFILE" do | arg |
|
116
|
-
accumulate_opt arg
|
117
|
-
end
|
118
|
-
|
119
|
-
flag %w[-v --verbose],"Verbosity. the more you set, the more we give" do
|
120
|
-
verbosity += 1
|
121
|
-
end
|
122
|
-
|
123
|
-
flag %w[-m --more-cow-bell], "I've got a fever" do
|
124
|
-
accumulate_opt
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
puts "Options"
|
129
|
-
puts options.inspect
|
130
|
-
|
131
|
-
puts "Arguments"
|
132
|
-
puts arguments.inspect
|
133
|
-
|
134
|
-
puts "Verbosity"
|
135
|
-
puts verbosity
|
136
|
-
|
137
|
-
puts "ARGV"
|
138
|
-
puts ARGV
|
139
|
-
|
140
|
-
|
141
|
-
=== An example that shows that you can easily set your defaults in normal Ruby variables and provide your own help.
|
142
|
-
|
143
170
|
require 'opt_simple'
|
144
171
|
|
172
|
+
verbosity = 0
|
173
|
+
|
174
|
+
options,arguments = OptSimple.new.parse_opts! do
|
175
|
+
option %w[-i --infile], "Infile, multiple allowed", "FILE" do | arg |
|
176
|
+
accumulate_opt arg
|
177
|
+
end
|
178
|
+
|
179
|
+
flag %w[-v --verbose],"Verbosity. the more you set, the more we give" do
|
180
|
+
verbosity += 1
|
181
|
+
end
|
182
|
+
|
183
|
+
flag %w[-m --more-cow-bell], "I've got a fever" do
|
184
|
+
accumulate_opt
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
puts "Options"
|
189
|
+
puts options.inspect
|
190
|
+
|
191
|
+
puts "Arguments"
|
192
|
+
puts arguments.inspect
|
193
|
+
|
194
|
+
puts "Verbosity"
|
195
|
+
puts verbosity
|
196
|
+
|
197
|
+
puts "ARGV"
|
198
|
+
puts ARGV
|
199
|
+
|
200
|
+
|
201
|
+
=== An example that shows that you can easily set your defaults in normal Ruby variables and provide your own help.
|
202
|
+
|
203
|
+
require 'opt_simple'
|
204
|
+
|
145
205
|
in_file = nil
|
146
206
|
min = 0
|
147
207
|
max = 10
|
148
208
|
pattern = "*"
|
149
|
-
|
209
|
+
|
150
210
|
usage_string = <<-UL
|
151
211
|
Usage: $0 [options]
|
152
212
|
|
@@ -155,12 +215,12 @@ puts ARGV
|
|
155
215
|
[-p, --pattern, --glob-pattern (default #{pattern})]
|
156
216
|
[-v (verbose)]
|
157
217
|
[-h, --help (help)]
|
158
|
-
|
218
|
+
|
159
219
|
UL
|
160
|
-
|
220
|
+
|
161
221
|
OptSimple.new.parse_opts! do
|
162
222
|
help usage_string
|
163
|
-
|
223
|
+
|
164
224
|
argument %w[-i --infile],"inFile" do |arg|
|
165
225
|
in_file = arg
|
166
226
|
error "inFile must exist and be readable" unless(File.readable?(in_file))
|
@@ -188,8 +248,56 @@ puts ARGV
|
|
188
248
|
|
189
249
|
puts "ARGV"
|
190
250
|
puts ARGV
|
251
|
+
|
252
|
+
=== An example showing how to register parms in multiple places before parsing the command line
|
253
|
+
|
254
|
+
require 'opt_simple'
|
255
|
+
|
256
|
+
min = 5
|
257
|
+
max = 15
|
258
|
+
|
259
|
+
os = OptSimple.new
|
260
|
+
|
261
|
+
os.register_opts do
|
262
|
+
argument %w[-i --infile], "Infile, multiple allowed", "FILE" do | arg |
|
263
|
+
accumulate_opt arg
|
264
|
+
end
|
265
|
+
|
266
|
+
option %w[-p --pattern --glob-pattern], "glob pattern","PATTERN"
|
267
|
+
end
|
268
|
+
|
269
|
+
os.register_opts do
|
270
|
+
option %w[-n -num --num-values],"Number of val","VAL" do |arg|
|
271
|
+
set_opt arg.to_i
|
272
|
+
end
|
273
|
+
|
274
|
+
option "--range", "range: min,max (both >0) default is #{min},#{max}" do | arg1,arg2 |
|
275
|
+
min = arg1.to_i
|
276
|
+
max = arg2.to_i
|
277
|
+
|
278
|
+
error "max must be greater than min" unless max > min
|
279
|
+
error "both must be >=0" if min < 0
|
280
|
+
end
|
281
|
+
|
282
|
+
flag %w[-v --verbose],"Verbosity. the more you set, the more we give" do
|
283
|
+
accumulate_opt
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
options,arguments = os.parse_opts!
|
288
|
+
|
289
|
+
puts "Options"
|
290
|
+
puts options.inspect
|
291
|
+
|
292
|
+
puts "Arguments"
|
293
|
+
puts arguments.inspect
|
294
|
+
|
295
|
+
puts "ARGV"
|
296
|
+
puts ARGV
|
297
|
+
|
191
298
|
|
192
299
|
== Questions and/or Comments
|
193
|
-
|
300
|
+
|
194
301
|
email {Ethan Stryker}[mailto:e.stryker@gmail.com]
|
195
|
-
|
302
|
+
|
303
|
+
|
data/lib/opt_simple.rb
CHANGED
@@ -57,94 +57,108 @@ class OptSimple
|
|
57
57
|
@banner = str
|
58
58
|
end
|
59
59
|
|
60
|
-
#
|
61
|
-
#
|
62
|
-
def
|
63
|
-
|
64
|
-
if block_given?
|
60
|
+
# Simply register options without actually parsing them.
|
61
|
+
# This allows registering parms in multiple places in your code.
|
62
|
+
def register_opts(&block)
|
63
|
+
begin
|
65
64
|
# call the block to register all the parameters and
|
66
65
|
# their corresponding code blocks
|
67
66
|
# We use instance_exec so that the API is cleaner.
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
67
|
+
instance_exec(@options,@positional_arguments,&block)
|
68
|
+
ensure
|
69
|
+
# we are ensuring that the options that occur before any break statement
|
70
|
+
# actually get parsed.
|
71
|
+
|
72
|
+
# add the help option at the end the first time register_opts is called
|
73
|
+
unless(@parameters.find {|p| p.switches.include?('-h')})
|
75
74
|
flag %w[-h --help] ,"(for this help message)"
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
$stdout.puts self.to_s
|
80
|
-
exit(0)
|
81
|
-
end
|
82
|
-
|
83
|
-
mandatory_check = mandatory_opts.map {|m| m.switches}
|
84
|
-
|
85
|
-
if(loc = @args.index('--'))
|
86
|
-
#remove the '--', but don't include it w/ positional arguments
|
87
|
-
@positional_arguments += @args.slice!(loc..-1)[1..-1]
|
88
|
-
end
|
89
|
-
|
90
|
-
# Handle the case where a user specifies --foo=bar, or --foo=bar,baz
|
91
|
-
equal_args = @args.find_all {|arg| arg.include?('=') }
|
92
|
-
@args.delete_if {|arg| arg.include?('=') }
|
93
|
-
equal_args.each do | e |
|
94
|
-
switch,list = e.split('=')
|
95
|
-
@args << switch
|
96
|
-
list.split(',').each {|val| @args << val }
|
97
|
-
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
98
78
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
chunks = []
|
114
|
-
arg_locations.sort.reverse.each do |loc|
|
115
|
-
chunks.unshift @args.slice!(loc .. loc + parm.block.arity)[1..-1]
|
116
|
-
end
|
79
|
+
# Parse the options, destructively pulling them out of the args array as it goes.
|
80
|
+
# If no block is given, then a default parser with no error checking will be run.
|
81
|
+
def parse_opts!(&block)
|
82
|
+
|
83
|
+
if block_given?
|
84
|
+
register_opts(&block)
|
85
|
+
end
|
86
|
+
|
87
|
+
if @parameters.empty?
|
88
|
+
#parse the @args array by looking for switches/args by regex
|
89
|
+
default_arg_parser
|
90
|
+
else
|
91
|
+
# go through the registered parameters, and pull out
|
92
|
+
# the specified parms from @arg
|
117
93
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
94
|
+
# first look for a call for help
|
95
|
+
unless (%w[-h --help] & @args).empty?
|
96
|
+
$stdout.puts self.to_s
|
97
|
+
exit(0)
|
98
|
+
end
|
99
|
+
|
100
|
+
mandatory_check = mandatory_opts.map {|m| m.switches}
|
101
|
+
|
102
|
+
if(loc = @args.index('--'))
|
103
|
+
#remove the '--', but don't include it w/ positional arguments
|
104
|
+
@positional_arguments += @args.slice!(loc..-1)[1..-1]
|
105
|
+
end
|
106
|
+
|
107
|
+
# Handle the case where a user specifies --foo=bar, or --foo=bar,baz
|
108
|
+
equal_args = @args.find_all {|arg| arg.include?('=') }
|
109
|
+
@args.delete_if {|arg| arg.include?('=') }
|
110
|
+
equal_args.each do | e |
|
111
|
+
switch,list = e.split('=')
|
112
|
+
@args << switch
|
113
|
+
list.split(',').each {|val| @args << val }
|
114
|
+
end
|
115
|
+
|
116
|
+
# now actually parse the args, and call all the stored up blocks from the options
|
117
|
+
@parameters.each do | parm |
|
118
|
+
intersection = @args & parm.switches
|
119
|
+
unless intersection.empty?
|
120
|
+
mandatory_check.delete(parm.switches)
|
121
|
+
|
122
|
+
arg_locations = []
|
123
|
+
@args.each_with_index {|arg,i| arg_locations << i if intersection.include?(arg) }
|
124
|
+
|
125
|
+
# we want to process the args in order to provide predictable behavior
|
126
|
+
# in the case of switch duplication.
|
127
|
+
# We do pull them out in reverse so that the slicing removes pieces from the end
|
128
|
+
# of @args, so we don't disrupt the other locations, but put them into 'chunks'
|
129
|
+
# backwards to restore their order.
|
130
|
+
chunks = []
|
131
|
+
arg_locations.sort.reverse.each do |loc|
|
132
|
+
chunks.unshift @args.slice!(loc .. loc + parm.block.arity)[1..-1]
|
133
|
+
end
|
134
|
+
|
135
|
+
chunks.each do | pieces |
|
136
|
+
if pieces.length < parm.block.arity or
|
137
|
+
pieces.any? {|p| p.start_with?('-')}
|
138
|
+
raise OptSimple::ParameterUsageError.new "Not enough args following #{intersection}",self
|
129
139
|
end
|
130
140
|
|
131
|
-
|
141
|
+
begin
|
142
|
+
parm.instance_exec(*pieces,&parm.block)
|
143
|
+
rescue OptSimple::Error => e
|
144
|
+
raise OptSimple::Error.new e.message,self
|
145
|
+
end
|
132
146
|
end
|
147
|
+
|
148
|
+
@options.merge!(parm.param_options)
|
133
149
|
end
|
134
|
-
|
135
|
-
unless mandatory_check.empty?
|
136
|
-
raise MissingArgument.new "Must set the following parameters: #{mandatory_check.map {|a| a.join(' OR ')}.join(', ')}",self
|
137
|
-
end
|
138
|
-
|
139
|
-
extra_switches = @args.find_all {|a| a.start_with?('-') }
|
140
|
-
raise OptSimple::InvalidOption.new "Unknown options: #{extra_switches.join(' ')}",self unless extra_switches.empty?
|
141
|
-
|
142
|
-
@positional_arguments += @args.slice!(0..-1)
|
143
150
|
end
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
151
|
+
|
152
|
+
unless mandatory_check.empty?
|
153
|
+
raise MissingArgument.new "Must set the following parameters: #{mandatory_check.map {|a| a.join(' OR ')}.join(', ')}",self
|
154
|
+
end
|
155
|
+
|
156
|
+
extra_switches = @args.find_all {|a| a.start_with?('-') }
|
157
|
+
raise OptSimple::InvalidOption.new "Unknown options: #{extra_switches.join(' ')}",self unless extra_switches.empty?
|
158
|
+
|
159
|
+
@positional_arguments += @args.slice!(0..-1)
|
160
|
+
end
|
161
|
+
|
148
162
|
return [@options,@positional_arguments]
|
149
163
|
end
|
150
164
|
|
data/test/test_usage.rb
CHANGED
@@ -55,7 +55,7 @@ class TestHelpStatement < Test::Unit::TestCase
|
|
55
55
|
must "accumulate lists of args when asked" do
|
56
56
|
os = OptSimple.new({},%w[-i foo.bar --infile bar.in])
|
57
57
|
o,a = os.parse_opts! do
|
58
|
-
option %w[-i --infile], "Infile, multiple allowed", "
|
58
|
+
option %w[-i --infile], "Infile, multiple allowed", "FILE" do | arg |
|
59
59
|
accumulate_opt arg
|
60
60
|
end
|
61
61
|
end
|
@@ -78,7 +78,7 @@ class TestHelpStatement < Test::Unit::TestCase
|
|
78
78
|
must "set last arg when duplicated when accumulate opt isn't used" do
|
79
79
|
os = OptSimple.new({},%w[-i foo.bar --infile bar.in -i baz])
|
80
80
|
o,a = os.parse_opts! do
|
81
|
-
option %w[-i --infile], "Infile, multiple allowed", "
|
81
|
+
option %w[-i --infile], "Infile, multiple allowed", "FILE" do | arg |
|
82
82
|
set_opt arg
|
83
83
|
end
|
84
84
|
end
|
@@ -86,5 +86,24 @@ class TestHelpStatement < Test::Unit::TestCase
|
|
86
86
|
assert_equal o['i'],'baz'
|
87
87
|
assert_equal o['infile'],'baz'
|
88
88
|
end
|
89
|
+
|
90
|
+
must "allow parameters to be registered in multiple spots" do
|
91
|
+
os = OptSimple.new({},%w[-i foo.bar --outfile bar.out])
|
92
|
+
os.register_opts do
|
93
|
+
option %w[-i --infile], "Infile", "FILE" do | arg |
|
94
|
+
set_opt arg
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
os.register_opts do
|
99
|
+
option %w[-o --outfile], "outfile", "FILE" do | arg |
|
100
|
+
set_opt arg
|
101
|
+
end
|
102
|
+
end
|
103
|
+
o,a = os.parse_opts!
|
104
|
+
|
105
|
+
assert_equal o['i'],'foo.bar'
|
106
|
+
assert_equal o['o'],'bar.out'
|
107
|
+
end
|
89
108
|
end
|
90
109
|
|