parseargs 0.2.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/lib/parseargs-0.2.0.rb +452 -0
- data/lib/parseargs.rb +452 -0
- metadata +40 -0
@@ -0,0 +1,452 @@
|
|
1
|
+
unless defined? $__parseargs__
|
2
|
+
module ParseArgs
|
3
|
+
#--{{{
|
4
|
+
ParseArgs::LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
|
5
|
+
defined? ParseArgs::LIBDIR
|
6
|
+
|
7
|
+
ParseArgs::VERSION = '0.1.0' unless
|
8
|
+
defined? ParseArgs::VERSION
|
9
|
+
|
10
|
+
require 'enumerator'
|
11
|
+
require 'ostruct'
|
12
|
+
|
13
|
+
class ArgumentNotGiven < StandardError; end
|
14
|
+
class KeywordNotGiven < StandardError; end
|
15
|
+
|
16
|
+
module Util
|
17
|
+
#--{{{
|
18
|
+
module Methods
|
19
|
+
#--{{{
|
20
|
+
def get_kw kw, table = nil, ret = nil
|
21
|
+
#--{{{
|
22
|
+
k = kw
|
23
|
+
table ||= self if Hash === self
|
24
|
+
return table[k] if table.has_key? k
|
25
|
+
k = "#{ k }"
|
26
|
+
return table[k] if table.has_key? k
|
27
|
+
k = k.intern
|
28
|
+
return table[k] if table.has_key? k
|
29
|
+
ret ||= (default if Hash === self)
|
30
|
+
return ret
|
31
|
+
#--}}}
|
32
|
+
end
|
33
|
+
def has_kw kw, table = nil
|
34
|
+
#--{{{
|
35
|
+
k = kw
|
36
|
+
table ||= self if Hash === self
|
37
|
+
return true if table.has_key? k
|
38
|
+
k = "#{ k }"
|
39
|
+
return true if table.has_key? k
|
40
|
+
k = k.intern
|
41
|
+
return true if table.has_key? k
|
42
|
+
return false
|
43
|
+
#--}}}
|
44
|
+
end
|
45
|
+
alias has_kw? has_kw
|
46
|
+
#--}}}
|
47
|
+
end
|
48
|
+
def self::append_features klass
|
49
|
+
#--{{{
|
50
|
+
klass.extend Methods
|
51
|
+
klass.class_eval{ include Methods }
|
52
|
+
#--}}}
|
53
|
+
end
|
54
|
+
#--}}}
|
55
|
+
end
|
56
|
+
|
57
|
+
class Parser
|
58
|
+
#--{{{
|
59
|
+
include Util
|
60
|
+
|
61
|
+
class Argument
|
62
|
+
#--{{{
|
63
|
+
include Util
|
64
|
+
|
65
|
+
attr 'name', true
|
66
|
+
attr 'required', true
|
67
|
+
alias required? required
|
68
|
+
attr 'default', true
|
69
|
+
attr 'type', true
|
70
|
+
attr 'ducktype', true
|
71
|
+
attr 'coerce', true
|
72
|
+
attr 'convince', true
|
73
|
+
attr 'validate', true
|
74
|
+
|
75
|
+
def initialize name, opts = {}
|
76
|
+
#--{{{
|
77
|
+
@name = name
|
78
|
+
@required = get_kw 'required', opts
|
79
|
+
@default = get_kw 'default', opts
|
80
|
+
@types = get_kw('type', opts, get_kw('types', opts, []))
|
81
|
+
@ducktypes = get_kw('ducktype', opts, get_kw('ducktypes', opts, []))
|
82
|
+
@coerce = get_kw 'coerce', opts
|
83
|
+
@convince = get_kw 'convince', opts
|
84
|
+
@validate = get_kw 'validate', opts
|
85
|
+
@types = [ @types ].flatten
|
86
|
+
@ducktypes = [ @ducktypes ].flatten
|
87
|
+
if @coerce and (String === @coerce or Symbol === @coerce)
|
88
|
+
msg = @coerce.dup
|
89
|
+
@coerce = lambda{|obj| obj.send msg}
|
90
|
+
end
|
91
|
+
if @convince and Module === @convince
|
92
|
+
mod = @convince
|
93
|
+
@convince = lambda{|obj| obj.extend mod}
|
94
|
+
end
|
95
|
+
if @validate and not Proc === @validate
|
96
|
+
equiv = @validate.dup
|
97
|
+
@validate = lambda{|obj| equiv === obj}
|
98
|
+
end
|
99
|
+
@value_set = false
|
100
|
+
#--}}}
|
101
|
+
end
|
102
|
+
def value= v
|
103
|
+
#--{{{
|
104
|
+
unless @types.empty?
|
105
|
+
ok = false
|
106
|
+
@types.each{|t| if v.is_a? t; ok = true; break; end}
|
107
|
+
if not ok and @coerce
|
108
|
+
v = @coerce[v]
|
109
|
+
ok = false
|
110
|
+
@types.each{|t| if v.is_a? t; ok = true; break; end}
|
111
|
+
end
|
112
|
+
raise TypeError, "value given not of type(#{ @types.join ',' }) in '#{ @name }='" unless ok
|
113
|
+
end
|
114
|
+
unless @ducktypes.empty?
|
115
|
+
ok = true
|
116
|
+
@ducktypes.each{|t| unless v.respond_to? t;ok = false; break; end}
|
117
|
+
if not ok and @convince
|
118
|
+
@convince[v]
|
119
|
+
ok = true
|
120
|
+
@ducktypes.each{|t| unless v.respond_to? t; ok = false; break; end}
|
121
|
+
end
|
122
|
+
if not ok and @coerce
|
123
|
+
v = @coerce[v]
|
124
|
+
ok = true
|
125
|
+
@ducktypes.each{|t| unless v.respond_to? t; ok = false; break; end}
|
126
|
+
end
|
127
|
+
raise TypeError, "value given not of ducktype(#{ @ducktypes.join ',' }) in '#{ @name }='" unless ok
|
128
|
+
end
|
129
|
+
if @validate
|
130
|
+
valid = @validate[v]
|
131
|
+
unless valid
|
132
|
+
vmsg = v.inspect
|
133
|
+
vmsg = vmsg[0,16] << '...' if vmsg.size > 16
|
134
|
+
raise ArgumentError, "invalid value(#{ vmsg }) given in '#{ @name }='"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
@value = v
|
138
|
+
@value_set = true
|
139
|
+
@value
|
140
|
+
#--}}}
|
141
|
+
end
|
142
|
+
def value
|
143
|
+
#--{{{
|
144
|
+
if @value_set
|
145
|
+
@value
|
146
|
+
else
|
147
|
+
@default
|
148
|
+
end
|
149
|
+
#--}}}
|
150
|
+
end
|
151
|
+
def optional
|
152
|
+
#--{{{
|
153
|
+
not required
|
154
|
+
#--}}}
|
155
|
+
end
|
156
|
+
alias optional? optional
|
157
|
+
#--}}}
|
158
|
+
end # class Argument
|
159
|
+
|
160
|
+
class Keyword < Argument
|
161
|
+
#--{{{
|
162
|
+
#--}}}
|
163
|
+
end # class Keyword
|
164
|
+
|
165
|
+
attr :receiver, true
|
166
|
+
def initialize(opts = {}, &b)
|
167
|
+
#--{{{
|
168
|
+
@required_arguments = []
|
169
|
+
@optional_arguments = []
|
170
|
+
@required_keywords = []
|
171
|
+
@optional_keywords = []
|
172
|
+
opts.each{|k,v| send k, v}
|
173
|
+
instance_eval &b
|
174
|
+
#--}}}
|
175
|
+
end
|
176
|
+
def define_arguments(list, required, *descs)
|
177
|
+
#--{{{
|
178
|
+
unless descs.empty?
|
179
|
+
metadata = descs.size >= 2 && Hash === descs.last ? descs.pop : {}
|
180
|
+
descs.flatten!
|
181
|
+
mdefault ||= get_kw('default', metadata)
|
182
|
+
descs.each do |desc|
|
183
|
+
names, default = Hash === desc ? desc.to_a.first : [desc, mdefault]
|
184
|
+
req = default ? false : required
|
185
|
+
names = [ names ] unless names.respond_to? :each
|
186
|
+
names.each do |name|
|
187
|
+
list << Argument::new(name, metadata.merge('required'=>req,'default'=>default))
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
list
|
192
|
+
#--}}}
|
193
|
+
end
|
194
|
+
def required_arguments(*descs)
|
195
|
+
#--{{{
|
196
|
+
if descs.empty?
|
197
|
+
@required_arguments
|
198
|
+
else
|
199
|
+
define_arguments(@required_arguments, true, *descs)
|
200
|
+
end
|
201
|
+
#--}}}
|
202
|
+
end
|
203
|
+
alias required_argument required_arguments
|
204
|
+
alias req_arguments required_arguments
|
205
|
+
alias req_argument required_arguments
|
206
|
+
alias req_args required_arguments
|
207
|
+
alias req_arg required_arguments
|
208
|
+
alias r_args required_arguments
|
209
|
+
alias r_arg required_arguments
|
210
|
+
alias args required_arguments
|
211
|
+
alias arg required_arguments
|
212
|
+
alias arguments required_arguments
|
213
|
+
alias argument required_arguments
|
214
|
+
alias ras required_arguments
|
215
|
+
alias ra required_arguments
|
216
|
+
def optional_arguments(*descs)
|
217
|
+
#--{{{
|
218
|
+
if descs.empty?
|
219
|
+
@optional_arguments
|
220
|
+
else
|
221
|
+
define_arguments(@optional_arguments, false, *descs)
|
222
|
+
end
|
223
|
+
#--}}}
|
224
|
+
end
|
225
|
+
alias optional_argument optional_arguments
|
226
|
+
alias opt_arguments optional_arguments
|
227
|
+
alias opt_argument optional_arguments
|
228
|
+
alias opt_args optional_arguments
|
229
|
+
alias opt_arg optional_arguments
|
230
|
+
alias o_args optional_arguments
|
231
|
+
alias o_arg optional_arguments
|
232
|
+
alias oas optional_arguments
|
233
|
+
alias oa optional_arguments
|
234
|
+
def define_keywords(list, required, *descs)
|
235
|
+
#--{{{
|
236
|
+
unless descs.empty?
|
237
|
+
metadata = descs.size >= 2 && Hash === descs.last ? descs.pop : {}
|
238
|
+
descs.flatten!
|
239
|
+
mdefault ||= get_kw('default', metadata)
|
240
|
+
descs.each do |desc|
|
241
|
+
names, default = Hash === desc ? desc.to_a.first : [desc, mdefault]
|
242
|
+
req = default ? false : required
|
243
|
+
names = [ names ] unless names.respond_to? :each
|
244
|
+
names.each do |name|
|
245
|
+
list << Keyword::new(name, metadata.merge('required'=>req,'default'=>default))
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
list
|
250
|
+
#--}}}
|
251
|
+
end
|
252
|
+
def required_keywords(*descs)
|
253
|
+
#--{{{
|
254
|
+
if descs.empty?
|
255
|
+
@required_keywords
|
256
|
+
else
|
257
|
+
define_keywords(@required_keywords, true, *descs)
|
258
|
+
end
|
259
|
+
#--}}}
|
260
|
+
end
|
261
|
+
alias required_keyword required_keywords
|
262
|
+
alias req_keywords required_keywords
|
263
|
+
alias req_keyword required_keywords
|
264
|
+
alias req_kws required_keywords
|
265
|
+
alias req_kw required_keywords
|
266
|
+
alias r_kws required_keywords
|
267
|
+
alias r_kw required_keywords
|
268
|
+
alias kws required_keywords
|
269
|
+
alias kw required_keywords
|
270
|
+
alias keywords required_keywords
|
271
|
+
alias keyword required_keywords
|
272
|
+
def optional_keywords(*descs)
|
273
|
+
#--{{{
|
274
|
+
if descs.empty?
|
275
|
+
@required_keywords
|
276
|
+
else
|
277
|
+
define_keywords(@optional_keywords, false, *descs)
|
278
|
+
end
|
279
|
+
#--}}}
|
280
|
+
end
|
281
|
+
alias optional_keyword optional_keywords
|
282
|
+
alias opt_keywords optional_keywords
|
283
|
+
alias opt_keyword optional_keywords
|
284
|
+
alias opt_kws optional_keywords
|
285
|
+
alias opt_kw optional_keywords
|
286
|
+
alias o_kws optional_keywords
|
287
|
+
alias o_kw optional_keywords
|
288
|
+
alias okws optional_keywords
|
289
|
+
alias okw optional_keywords
|
290
|
+
#
|
291
|
+
# TODO - thinks about *args signature??
|
292
|
+
#
|
293
|
+
def parse arg
|
294
|
+
#--{{{
|
295
|
+
enumerable, receiver =
|
296
|
+
if Hash === arg
|
297
|
+
a = arg.to_a
|
298
|
+
pair = a.shift
|
299
|
+
unless a.empty?
|
300
|
+
raise ArgumentError, "wrong number of arguments(#{ a.size + 1 } for 1"
|
301
|
+
end
|
302
|
+
pair
|
303
|
+
else
|
304
|
+
[arg, Receiver::new]
|
305
|
+
end
|
306
|
+
|
307
|
+
p_args = enumerable.to_enum.map
|
308
|
+
|
309
|
+
n = p_args.size
|
310
|
+
|
311
|
+
@required_arguments.each do |arg|
|
312
|
+
if p_args.empty?
|
313
|
+
raise ArgumentNotGiven, "<#{ arg.name }>"
|
314
|
+
end
|
315
|
+
p_arg = p_args.shift
|
316
|
+
arg.value = p_arg
|
317
|
+
receiver_set receiver, arg.name, arg.value
|
318
|
+
end
|
319
|
+
|
320
|
+
@optional_arguments.each do |arg|
|
321
|
+
p_arg = p_args.empty? ? arg.default : p_args.shift
|
322
|
+
arg.value = p_arg
|
323
|
+
receiver_set receiver, arg.name, arg.value
|
324
|
+
end
|
325
|
+
|
326
|
+
if receiver.respond_to? "arguments="
|
327
|
+
receiver.arguments = @required_arguments + @optional_arguments
|
328
|
+
end
|
329
|
+
|
330
|
+
p_kws = Hash === p_args.first ? p_args.shift : {}
|
331
|
+
|
332
|
+
@required_keywords.each do |kw|
|
333
|
+
p_kw, p_arg = extract_kw kw, p_kws
|
334
|
+
raise KeywordNotGiven, "<#{ kw.name }>" if p_kw.nil?
|
335
|
+
kw.value = p_arg
|
336
|
+
receiver_set receiver, kw.name, kw.value
|
337
|
+
end
|
338
|
+
|
339
|
+
@optional_keywords.each do |kw|
|
340
|
+
p_kw, p_arg = extract_kw kw, p_kws
|
341
|
+
p_arg = p_kw ? p_arg : kw.default
|
342
|
+
kw.value = p_arg
|
343
|
+
receiver_set receiver, kw.name, kw.value
|
344
|
+
end
|
345
|
+
|
346
|
+
if receiver.respond_to? "keywords="
|
347
|
+
receiver.keywords = @required_keywords + @optional_keywords
|
348
|
+
end
|
349
|
+
|
350
|
+
unless p_args.empty?
|
351
|
+
raise ArgumentError, "wrong number of arguments(#{ n } for #{ n - p_args.size })"
|
352
|
+
end
|
353
|
+
|
354
|
+
receiver
|
355
|
+
#--}}}
|
356
|
+
end
|
357
|
+
def extract_kw kw, kws
|
358
|
+
#--{{{
|
359
|
+
k = kw.name
|
360
|
+
return [k, kws[k]] if kws.has_key? k
|
361
|
+
k = "#{ k }"
|
362
|
+
return [k, kws[k]] if kws.has_key? k
|
363
|
+
k = k.intern
|
364
|
+
return [k, kws[k]] if kws.has_key? k
|
365
|
+
return [nil, nil]
|
366
|
+
#--}}}
|
367
|
+
end
|
368
|
+
def receiver_set receiver, name, value
|
369
|
+
#--{{{
|
370
|
+
begin
|
371
|
+
receiver.send "[]=", name, value
|
372
|
+
rescue NameError
|
373
|
+
begin
|
374
|
+
receiver.send "#{ name }=", value
|
375
|
+
rescue NameError
|
376
|
+
receiver.send "#{ name }", value
|
377
|
+
end
|
378
|
+
end
|
379
|
+
#--}}}
|
380
|
+
end
|
381
|
+
#--}}}
|
382
|
+
end # class Parser
|
383
|
+
|
384
|
+
class Receiver < ::Hash
|
385
|
+
#--{{{
|
386
|
+
include Util
|
387
|
+
attr_accessor 'arguments'
|
388
|
+
alias_method 'args', 'arguments'
|
389
|
+
attr_accessor 'keywords'
|
390
|
+
alias_method 'kws', 'keywords'
|
391
|
+
def method_missing(m, *a, &b)
|
392
|
+
#--{{{
|
393
|
+
return(get_kw(m)) if has_kw? m
|
394
|
+
super
|
395
|
+
#--}}}
|
396
|
+
end
|
397
|
+
#--}}}
|
398
|
+
end
|
399
|
+
|
400
|
+
module ModuleMethods
|
401
|
+
#--{{{
|
402
|
+
def parseargs(*____argv, &____block)
|
403
|
+
#--{{{
|
404
|
+
::ParseArgs::parseargs(*____argv, &____block)
|
405
|
+
#--}}}
|
406
|
+
end
|
407
|
+
#--}}}
|
408
|
+
end # module ModuleMethods
|
409
|
+
|
410
|
+
module InstanceMethods
|
411
|
+
#--{{{
|
412
|
+
def parseargs(*____argv, &____block)
|
413
|
+
#--{{{
|
414
|
+
::ParseArgs::parseargs(*____argv, &____block)
|
415
|
+
#--}}}
|
416
|
+
end
|
417
|
+
#--}}}
|
418
|
+
end # module InstanceMethods
|
419
|
+
|
420
|
+
class << self
|
421
|
+
#--{{{
|
422
|
+
def append_features klass
|
423
|
+
#--{{{
|
424
|
+
klass.extend ModuleMethods
|
425
|
+
klass.class_eval{ include InstanceMethods }
|
426
|
+
#--}}}
|
427
|
+
end
|
428
|
+
def parseargs(*____argv, &____block)
|
429
|
+
#--{{{
|
430
|
+
parser = ParseArgs::Parser::new(&____block)
|
431
|
+
receiver = parser.parse(*____argv)
|
432
|
+
receiver.freeze
|
433
|
+
receiver
|
434
|
+
#--}}}
|
435
|
+
end
|
436
|
+
#--}}}
|
437
|
+
end
|
438
|
+
|
439
|
+
#--}}}
|
440
|
+
end # module ParseArgs
|
441
|
+
|
442
|
+
class Object
|
443
|
+
#--{{{
|
444
|
+
def ParseArgs(*a, &b)
|
445
|
+
#--{{{
|
446
|
+
::ParseArgs::parseargs(*a, &b)
|
447
|
+
#--}}}
|
448
|
+
end
|
449
|
+
#--}}}
|
450
|
+
end
|
451
|
+
$__parseargs__ = __FILE__
|
452
|
+
end
|
data/lib/parseargs.rb
ADDED
@@ -0,0 +1,452 @@
|
|
1
|
+
unless defined? $__parseargs__
|
2
|
+
module ParseArgs
|
3
|
+
#--{{{
|
4
|
+
ParseArgs::LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
|
5
|
+
defined? ParseArgs::LIBDIR
|
6
|
+
|
7
|
+
ParseArgs::VERSION = '0.1.0' unless
|
8
|
+
defined? ParseArgs::VERSION
|
9
|
+
|
10
|
+
require 'enumerator'
|
11
|
+
require 'ostruct'
|
12
|
+
|
13
|
+
class ArgumentNotGiven < StandardError; end
|
14
|
+
class KeywordNotGiven < StandardError; end
|
15
|
+
|
16
|
+
module Util
|
17
|
+
#--{{{
|
18
|
+
module Methods
|
19
|
+
#--{{{
|
20
|
+
def get_kw kw, table = nil, ret = nil
|
21
|
+
#--{{{
|
22
|
+
k = kw
|
23
|
+
table ||= self if Hash === self
|
24
|
+
return table[k] if table.has_key? k
|
25
|
+
k = "#{ k }"
|
26
|
+
return table[k] if table.has_key? k
|
27
|
+
k = k.intern
|
28
|
+
return table[k] if table.has_key? k
|
29
|
+
ret ||= (default if Hash === self)
|
30
|
+
return ret
|
31
|
+
#--}}}
|
32
|
+
end
|
33
|
+
def has_kw kw, table = nil
|
34
|
+
#--{{{
|
35
|
+
k = kw
|
36
|
+
table ||= self if Hash === self
|
37
|
+
return true if table.has_key? k
|
38
|
+
k = "#{ k }"
|
39
|
+
return true if table.has_key? k
|
40
|
+
k = k.intern
|
41
|
+
return true if table.has_key? k
|
42
|
+
return false
|
43
|
+
#--}}}
|
44
|
+
end
|
45
|
+
alias has_kw? has_kw
|
46
|
+
#--}}}
|
47
|
+
end
|
48
|
+
def self::append_features klass
|
49
|
+
#--{{{
|
50
|
+
klass.extend Methods
|
51
|
+
klass.class_eval{ include Methods }
|
52
|
+
#--}}}
|
53
|
+
end
|
54
|
+
#--}}}
|
55
|
+
end
|
56
|
+
|
57
|
+
class Parser
|
58
|
+
#--{{{
|
59
|
+
include Util
|
60
|
+
|
61
|
+
class Argument
|
62
|
+
#--{{{
|
63
|
+
include Util
|
64
|
+
|
65
|
+
attr 'name', true
|
66
|
+
attr 'required', true
|
67
|
+
alias required? required
|
68
|
+
attr 'default', true
|
69
|
+
attr 'type', true
|
70
|
+
attr 'ducktype', true
|
71
|
+
attr 'coerce', true
|
72
|
+
attr 'convince', true
|
73
|
+
attr 'validate', true
|
74
|
+
|
75
|
+
def initialize name, opts = {}
|
76
|
+
#--{{{
|
77
|
+
@name = name
|
78
|
+
@required = get_kw 'required', opts
|
79
|
+
@default = get_kw 'default', opts
|
80
|
+
@types = get_kw('type', opts, get_kw('types', opts, []))
|
81
|
+
@ducktypes = get_kw('ducktype', opts, get_kw('ducktypes', opts, []))
|
82
|
+
@coerce = get_kw 'coerce', opts
|
83
|
+
@convince = get_kw 'convince', opts
|
84
|
+
@validate = get_kw 'validate', opts
|
85
|
+
@types = [ @types ].flatten
|
86
|
+
@ducktypes = [ @ducktypes ].flatten
|
87
|
+
if @coerce and (String === @coerce or Symbol === @coerce)
|
88
|
+
msg = @coerce.dup
|
89
|
+
@coerce = lambda{|obj| obj.send msg}
|
90
|
+
end
|
91
|
+
if @convince and Module === @convince
|
92
|
+
mod = @convince
|
93
|
+
@convince = lambda{|obj| obj.extend mod}
|
94
|
+
end
|
95
|
+
if @validate and not Proc === @validate
|
96
|
+
equiv = @validate.dup
|
97
|
+
@validate = lambda{|obj| equiv === obj}
|
98
|
+
end
|
99
|
+
@value_set = false
|
100
|
+
#--}}}
|
101
|
+
end
|
102
|
+
def value= v
|
103
|
+
#--{{{
|
104
|
+
unless @types.empty?
|
105
|
+
ok = false
|
106
|
+
@types.each{|t| if v.is_a? t; ok = true; break; end}
|
107
|
+
if not ok and @coerce
|
108
|
+
v = @coerce[v]
|
109
|
+
ok = false
|
110
|
+
@types.each{|t| if v.is_a? t; ok = true; break; end}
|
111
|
+
end
|
112
|
+
raise TypeError, "value given not of type(#{ @types.join ',' }) in '#{ @name }='" unless ok
|
113
|
+
end
|
114
|
+
unless @ducktypes.empty?
|
115
|
+
ok = true
|
116
|
+
@ducktypes.each{|t| unless v.respond_to? t;ok = false; break; end}
|
117
|
+
if not ok and @convince
|
118
|
+
@convince[v]
|
119
|
+
ok = true
|
120
|
+
@ducktypes.each{|t| unless v.respond_to? t; ok = false; break; end}
|
121
|
+
end
|
122
|
+
if not ok and @coerce
|
123
|
+
v = @coerce[v]
|
124
|
+
ok = true
|
125
|
+
@ducktypes.each{|t| unless v.respond_to? t; ok = false; break; end}
|
126
|
+
end
|
127
|
+
raise TypeError, "value given not of ducktype(#{ @ducktypes.join ',' }) in '#{ @name }='" unless ok
|
128
|
+
end
|
129
|
+
if @validate
|
130
|
+
valid = @validate[v]
|
131
|
+
unless valid
|
132
|
+
vmsg = v.inspect
|
133
|
+
vmsg = vmsg[0,16] << '...' if vmsg.size > 16
|
134
|
+
raise ArgumentError, "invalid value(#{ vmsg }) given in '#{ @name }='"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
@value = v
|
138
|
+
@value_set = true
|
139
|
+
@value
|
140
|
+
#--}}}
|
141
|
+
end
|
142
|
+
def value
|
143
|
+
#--{{{
|
144
|
+
if @value_set
|
145
|
+
@value
|
146
|
+
else
|
147
|
+
@default
|
148
|
+
end
|
149
|
+
#--}}}
|
150
|
+
end
|
151
|
+
def optional
|
152
|
+
#--{{{
|
153
|
+
not required
|
154
|
+
#--}}}
|
155
|
+
end
|
156
|
+
alias optional? optional
|
157
|
+
#--}}}
|
158
|
+
end # class Argument
|
159
|
+
|
160
|
+
class Keyword < Argument
|
161
|
+
#--{{{
|
162
|
+
#--}}}
|
163
|
+
end # class Keyword
|
164
|
+
|
165
|
+
attr :receiver, true
|
166
|
+
def initialize(opts = {}, &b)
|
167
|
+
#--{{{
|
168
|
+
@required_arguments = []
|
169
|
+
@optional_arguments = []
|
170
|
+
@required_keywords = []
|
171
|
+
@optional_keywords = []
|
172
|
+
opts.each{|k,v| send k, v}
|
173
|
+
instance_eval &b
|
174
|
+
#--}}}
|
175
|
+
end
|
176
|
+
def define_arguments(list, required, *descs)
|
177
|
+
#--{{{
|
178
|
+
unless descs.empty?
|
179
|
+
metadata = descs.size >= 2 && Hash === descs.last ? descs.pop : {}
|
180
|
+
descs.flatten!
|
181
|
+
mdefault ||= get_kw('default', metadata)
|
182
|
+
descs.each do |desc|
|
183
|
+
names, default = Hash === desc ? desc.to_a.first : [desc, mdefault]
|
184
|
+
req = default ? false : required
|
185
|
+
names = [ names ] unless names.respond_to? :each
|
186
|
+
names.each do |name|
|
187
|
+
list << Argument::new(name, metadata.merge('required'=>req,'default'=>default))
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
list
|
192
|
+
#--}}}
|
193
|
+
end
|
194
|
+
def required_arguments(*descs)
|
195
|
+
#--{{{
|
196
|
+
if descs.empty?
|
197
|
+
@required_arguments
|
198
|
+
else
|
199
|
+
define_arguments(@required_arguments, true, *descs)
|
200
|
+
end
|
201
|
+
#--}}}
|
202
|
+
end
|
203
|
+
alias required_argument required_arguments
|
204
|
+
alias req_arguments required_arguments
|
205
|
+
alias req_argument required_arguments
|
206
|
+
alias req_args required_arguments
|
207
|
+
alias req_arg required_arguments
|
208
|
+
alias r_args required_arguments
|
209
|
+
alias r_arg required_arguments
|
210
|
+
alias args required_arguments
|
211
|
+
alias arg required_arguments
|
212
|
+
alias arguments required_arguments
|
213
|
+
alias argument required_arguments
|
214
|
+
alias ras required_arguments
|
215
|
+
alias ra required_arguments
|
216
|
+
def optional_arguments(*descs)
|
217
|
+
#--{{{
|
218
|
+
if descs.empty?
|
219
|
+
@optional_arguments
|
220
|
+
else
|
221
|
+
define_arguments(@optional_arguments, false, *descs)
|
222
|
+
end
|
223
|
+
#--}}}
|
224
|
+
end
|
225
|
+
alias optional_argument optional_arguments
|
226
|
+
alias opt_arguments optional_arguments
|
227
|
+
alias opt_argument optional_arguments
|
228
|
+
alias opt_args optional_arguments
|
229
|
+
alias opt_arg optional_arguments
|
230
|
+
alias o_args optional_arguments
|
231
|
+
alias o_arg optional_arguments
|
232
|
+
alias oas optional_arguments
|
233
|
+
alias oa optional_arguments
|
234
|
+
def define_keywords(list, required, *descs)
|
235
|
+
#--{{{
|
236
|
+
unless descs.empty?
|
237
|
+
metadata = descs.size >= 2 && Hash === descs.last ? descs.pop : {}
|
238
|
+
descs.flatten!
|
239
|
+
mdefault ||= get_kw('default', metadata)
|
240
|
+
descs.each do |desc|
|
241
|
+
names, default = Hash === desc ? desc.to_a.first : [desc, mdefault]
|
242
|
+
req = default ? false : required
|
243
|
+
names = [ names ] unless names.respond_to? :each
|
244
|
+
names.each do |name|
|
245
|
+
list << Keyword::new(name, metadata.merge('required'=>req,'default'=>default))
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
list
|
250
|
+
#--}}}
|
251
|
+
end
|
252
|
+
def required_keywords(*descs)
|
253
|
+
#--{{{
|
254
|
+
if descs.empty?
|
255
|
+
@required_keywords
|
256
|
+
else
|
257
|
+
define_keywords(@required_keywords, true, *descs)
|
258
|
+
end
|
259
|
+
#--}}}
|
260
|
+
end
|
261
|
+
alias required_keyword required_keywords
|
262
|
+
alias req_keywords required_keywords
|
263
|
+
alias req_keyword required_keywords
|
264
|
+
alias req_kws required_keywords
|
265
|
+
alias req_kw required_keywords
|
266
|
+
alias r_kws required_keywords
|
267
|
+
alias r_kw required_keywords
|
268
|
+
alias kws required_keywords
|
269
|
+
alias kw required_keywords
|
270
|
+
alias keywords required_keywords
|
271
|
+
alias keyword required_keywords
|
272
|
+
def optional_keywords(*descs)
|
273
|
+
#--{{{
|
274
|
+
if descs.empty?
|
275
|
+
@required_keywords
|
276
|
+
else
|
277
|
+
define_keywords(@optional_keywords, false, *descs)
|
278
|
+
end
|
279
|
+
#--}}}
|
280
|
+
end
|
281
|
+
alias optional_keyword optional_keywords
|
282
|
+
alias opt_keywords optional_keywords
|
283
|
+
alias opt_keyword optional_keywords
|
284
|
+
alias opt_kws optional_keywords
|
285
|
+
alias opt_kw optional_keywords
|
286
|
+
alias o_kws optional_keywords
|
287
|
+
alias o_kw optional_keywords
|
288
|
+
alias okws optional_keywords
|
289
|
+
alias okw optional_keywords
|
290
|
+
#
|
291
|
+
# TODO - thinks about *args signature??
|
292
|
+
#
|
293
|
+
def parse arg
|
294
|
+
#--{{{
|
295
|
+
enumerable, receiver =
|
296
|
+
if Hash === arg
|
297
|
+
a = arg.to_a
|
298
|
+
pair = a.shift
|
299
|
+
unless a.empty?
|
300
|
+
raise ArgumentError, "wrong number of arguments(#{ a.size + 1 } for 1"
|
301
|
+
end
|
302
|
+
pair
|
303
|
+
else
|
304
|
+
[arg, Receiver::new]
|
305
|
+
end
|
306
|
+
|
307
|
+
p_args = enumerable.to_enum.map
|
308
|
+
|
309
|
+
n = p_args.size
|
310
|
+
|
311
|
+
@required_arguments.each do |arg|
|
312
|
+
if p_args.empty?
|
313
|
+
raise ArgumentNotGiven, "<#{ arg.name }>"
|
314
|
+
end
|
315
|
+
p_arg = p_args.shift
|
316
|
+
arg.value = p_arg
|
317
|
+
receiver_set receiver, arg.name, arg.value
|
318
|
+
end
|
319
|
+
|
320
|
+
@optional_arguments.each do |arg|
|
321
|
+
p_arg = p_args.empty? ? arg.default : p_args.shift
|
322
|
+
arg.value = p_arg
|
323
|
+
receiver_set receiver, arg.name, arg.value
|
324
|
+
end
|
325
|
+
|
326
|
+
if receiver.respond_to? "arguments="
|
327
|
+
receiver.arguments = @required_arguments + @optional_arguments
|
328
|
+
end
|
329
|
+
|
330
|
+
p_kws = Hash === p_args.first ? p_args.shift : {}
|
331
|
+
|
332
|
+
@required_keywords.each do |kw|
|
333
|
+
p_kw, p_arg = extract_kw kw, p_kws
|
334
|
+
raise KeywordNotGiven, "<#{ kw.name }>" if p_kw.nil?
|
335
|
+
kw.value = p_arg
|
336
|
+
receiver_set receiver, kw.name, kw.value
|
337
|
+
end
|
338
|
+
|
339
|
+
@optional_keywords.each do |kw|
|
340
|
+
p_kw, p_arg = extract_kw kw, p_kws
|
341
|
+
p_arg = p_kw ? p_arg : kw.default
|
342
|
+
kw.value = p_arg
|
343
|
+
receiver_set receiver, kw.name, kw.value
|
344
|
+
end
|
345
|
+
|
346
|
+
if receiver.respond_to? "keywords="
|
347
|
+
receiver.keywords = @required_keywords + @optional_keywords
|
348
|
+
end
|
349
|
+
|
350
|
+
unless p_args.empty?
|
351
|
+
raise ArgumentError, "wrong number of arguments(#{ n } for #{ n - p_args.size })"
|
352
|
+
end
|
353
|
+
|
354
|
+
receiver
|
355
|
+
#--}}}
|
356
|
+
end
|
357
|
+
def extract_kw kw, kws
|
358
|
+
#--{{{
|
359
|
+
k = kw.name
|
360
|
+
return [k, kws[k]] if kws.has_key? k
|
361
|
+
k = "#{ k }"
|
362
|
+
return [k, kws[k]] if kws.has_key? k
|
363
|
+
k = k.intern
|
364
|
+
return [k, kws[k]] if kws.has_key? k
|
365
|
+
return [nil, nil]
|
366
|
+
#--}}}
|
367
|
+
end
|
368
|
+
def receiver_set receiver, name, value
|
369
|
+
#--{{{
|
370
|
+
begin
|
371
|
+
receiver.send "[]=", name, value
|
372
|
+
rescue NameError
|
373
|
+
begin
|
374
|
+
receiver.send "#{ name }=", value
|
375
|
+
rescue NameError
|
376
|
+
receiver.send "#{ name }", value
|
377
|
+
end
|
378
|
+
end
|
379
|
+
#--}}}
|
380
|
+
end
|
381
|
+
#--}}}
|
382
|
+
end # class Parser
|
383
|
+
|
384
|
+
class Receiver < ::Hash
|
385
|
+
#--{{{
|
386
|
+
include Util
|
387
|
+
attr_accessor 'arguments'
|
388
|
+
alias_method 'args', 'arguments'
|
389
|
+
attr_accessor 'keywords'
|
390
|
+
alias_method 'kws', 'keywords'
|
391
|
+
def method_missing(m, *a, &b)
|
392
|
+
#--{{{
|
393
|
+
return(get_kw(m)) if has_kw? m
|
394
|
+
super
|
395
|
+
#--}}}
|
396
|
+
end
|
397
|
+
#--}}}
|
398
|
+
end
|
399
|
+
|
400
|
+
module ModuleMethods
|
401
|
+
#--{{{
|
402
|
+
def parseargs(*____argv, &____block)
|
403
|
+
#--{{{
|
404
|
+
::ParseArgs::parseargs(*____argv, &____block)
|
405
|
+
#--}}}
|
406
|
+
end
|
407
|
+
#--}}}
|
408
|
+
end # module ModuleMethods
|
409
|
+
|
410
|
+
module InstanceMethods
|
411
|
+
#--{{{
|
412
|
+
def parseargs(*____argv, &____block)
|
413
|
+
#--{{{
|
414
|
+
::ParseArgs::parseargs(*____argv, &____block)
|
415
|
+
#--}}}
|
416
|
+
end
|
417
|
+
#--}}}
|
418
|
+
end # module InstanceMethods
|
419
|
+
|
420
|
+
class << self
|
421
|
+
#--{{{
|
422
|
+
def append_features klass
|
423
|
+
#--{{{
|
424
|
+
klass.extend ModuleMethods
|
425
|
+
klass.class_eval{ include InstanceMethods }
|
426
|
+
#--}}}
|
427
|
+
end
|
428
|
+
def parseargs(*____argv, &____block)
|
429
|
+
#--{{{
|
430
|
+
parser = ParseArgs::Parser::new(&____block)
|
431
|
+
receiver = parser.parse(*____argv)
|
432
|
+
receiver.freeze
|
433
|
+
receiver
|
434
|
+
#--}}}
|
435
|
+
end
|
436
|
+
#--}}}
|
437
|
+
end
|
438
|
+
|
439
|
+
#--}}}
|
440
|
+
end # module ParseArgs
|
441
|
+
|
442
|
+
class Object
|
443
|
+
#--{{{
|
444
|
+
def ParseArgs(*a, &b)
|
445
|
+
#--{{{
|
446
|
+
::ParseArgs::parseargs(*a, &b)
|
447
|
+
#--}}}
|
448
|
+
end
|
449
|
+
#--}}}
|
450
|
+
end
|
451
|
+
$__parseargs__ = __FILE__
|
452
|
+
end
|
metadata
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: parseargs
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2005-10-23 00:00:00.000000 -06:00
|
8
|
+
summary: parseargs
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: ara.t.howard@noaa.gov
|
12
|
+
homepage: http://codeforpeople.com/lib/ruby/parseargs/
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: parseargs
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
authors:
|
30
|
+
- Ara T. Howard
|
31
|
+
files:
|
32
|
+
- lib/parseargs.rb
|
33
|
+
- lib/parseargs-0.2.0.rb
|
34
|
+
test_files: []
|
35
|
+
rdoc_options: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
executables: []
|
38
|
+
extensions: []
|
39
|
+
requirements: []
|
40
|
+
dependencies: []
|