main 0.0.2 → 2.0.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/README +136 -25
- data/README.tmpl +126 -9
- data/TODO +2 -0
- data/a.rb +26 -0
- data/gemspec.rb +1 -1
- data/gen_readme.rb +4 -0
- data/lib/arrayfields.rb +434 -0
- data/lib/main.rb +46 -17
- data/lib/main/arrayfields.rb +190 -103
- data/lib/main/attributes.rb +84 -25
- data/lib/main/base.rb +146 -23
- data/lib/main/factories.rb +12 -8
- data/lib/main/mode.rb +42 -0
- data/lib/main/parameter.rb +77 -38
- data/lib/main/pervasives.rb +52 -0
- data/lib/main/softspoken.rb +12 -0
- data/lib/main/stdext.rb +18 -0
- data/lib/main/usage.rb +21 -3
- data/samples/e.rb +18 -0
- data/samples/f.rb +27 -0
- data/test/main.rb +156 -30
- metadata +25 -17
- data/lib/main/proxy.rb +0 -54
data/lib/main/attributes.rb
CHANGED
@@ -1,54 +1,113 @@
|
|
1
1
|
module Attributes
|
2
|
-
VERSION = '
|
2
|
+
Attributes::VERSION = '4.0.0' unless defined? Attributes::VERSION
|
3
|
+
def self.version() Attributes::VERSION end
|
3
4
|
|
4
|
-
|
5
|
+
class List < ::Array
|
6
|
+
def << element
|
7
|
+
super
|
8
|
+
self
|
9
|
+
ensure
|
10
|
+
uniq!
|
11
|
+
index!
|
12
|
+
end
|
13
|
+
def index!
|
14
|
+
@index ||= Hash.new
|
15
|
+
each{|element| @index[element] = true}
|
16
|
+
end
|
17
|
+
def include? element
|
18
|
+
@index ||= Hash.new
|
19
|
+
@index[element] ? true : false
|
20
|
+
end
|
21
|
+
def initializers
|
22
|
+
@initializers ||= Hash.new
|
23
|
+
end
|
24
|
+
end
|
5
25
|
|
6
26
|
def attributes *a, &b
|
7
27
|
unless a.empty?
|
8
|
-
|
28
|
+
returned = Hash.new
|
9
29
|
|
30
|
+
hashes, names = a.partition{|x| Hash === x}
|
10
31
|
names_and_defaults = {}
|
11
32
|
hashes.each{|h| names_and_defaults.update h}
|
12
33
|
names.flatten.compact.each{|name| names_and_defaults.update name => nil}
|
13
34
|
|
35
|
+
initializers = __attributes__.initializers
|
36
|
+
|
14
37
|
names_and_defaults.each do |name, default|
|
15
|
-
|
16
|
-
|
38
|
+
raise NameError, "bad instance variable name '@#{ name }'" if "@#{ name }" =~ %r/[!?=]$/o
|
39
|
+
name = name.to_s
|
17
40
|
|
18
|
-
|
19
|
-
|
41
|
+
initialize = b || lambda { default }
|
42
|
+
initializer = lambda do |this|
|
43
|
+
Object.instance_method('instance_eval').bind(this).call &initialize
|
20
44
|
end
|
45
|
+
initializer_id = initializer.object_id
|
46
|
+
__attributes__.initializers[name] = initializer
|
21
47
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
else
|
26
|
-
defined = instance_eval "defined? #{ ivar }"
|
27
|
-
send setter, instance_eval(&init) unless defined
|
28
|
-
instance_variable_get ivar
|
48
|
+
module_eval <<-code
|
49
|
+
def #{ name }=(value)
|
50
|
+
@#{ name } = value
|
29
51
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
52
|
+
code
|
53
|
+
module_eval <<-code
|
54
|
+
def #{ name }(*value)
|
55
|
+
return self.#{ name } = value.first unless value.empty?
|
56
|
+
#{ name }! unless defined? @#{ name }
|
57
|
+
@#{ name }
|
58
|
+
end
|
59
|
+
code
|
60
|
+
module_eval <<-code
|
61
|
+
def #{ name }!
|
62
|
+
initializer = ObjectSpace._id2ref #{ initializer_id }
|
63
|
+
self.#{ name } = initializer.call(self)
|
64
|
+
@#{ name }
|
65
|
+
end
|
66
|
+
code
|
67
|
+
module_eval <<-code
|
68
|
+
def #{ name }?
|
69
|
+
#{ name }
|
70
|
+
end
|
71
|
+
code
|
33
72
|
|
34
|
-
|
35
|
-
|
73
|
+
attributes << name
|
74
|
+
returned[name] = initializer
|
36
75
|
end
|
76
|
+
|
77
|
+
returned
|
37
78
|
else
|
38
|
-
|
79
|
+
begin
|
80
|
+
__attribute_list__
|
81
|
+
rescue NameError
|
82
|
+
singleton_class =
|
83
|
+
class << self
|
84
|
+
self
|
85
|
+
end
|
86
|
+
klass = self
|
87
|
+
singleton_class.module_eval do
|
88
|
+
attribute_list = List.new
|
89
|
+
define_method('attribute_list'){ klass == self ? attribute_list : raise(NameError) }
|
90
|
+
alias_method '__attribute_list__', 'attribute_list'
|
91
|
+
end
|
92
|
+
__attribute_list__
|
93
|
+
end
|
39
94
|
end
|
40
95
|
end
|
41
96
|
|
42
|
-
|
97
|
+
%w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
|
43
98
|
end
|
44
99
|
|
45
100
|
class Object
|
46
101
|
def attributes *a, &b
|
47
|
-
sc =
|
102
|
+
sc =
|
103
|
+
class << self
|
104
|
+
self
|
105
|
+
end
|
48
106
|
sc.attributes *a, &b
|
49
107
|
end
|
50
|
-
|
51
|
-
def attribute(*a, &b) attributes *a, &b end
|
108
|
+
%w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
|
52
109
|
end
|
53
110
|
|
54
|
-
class Module
|
111
|
+
class Module
|
112
|
+
include Attributes
|
113
|
+
end
|
data/lib/main/base.rb
CHANGED
@@ -1,10 +1,78 @@
|
|
1
1
|
module Main
|
2
2
|
class Base
|
3
3
|
class << self
|
4
|
-
|
4
|
+
def wrap_run!
|
5
|
+
const_set :RUN, instance_method(:run)
|
6
|
+
|
7
|
+
class_eval do
|
8
|
+
def run *a, &b
|
9
|
+
begin
|
10
|
+
argv.push "--#{ argv.shift }" if argv.first == 'help'
|
11
|
+
|
12
|
+
return mode_run! if mode_given?
|
13
|
+
|
14
|
+
parse_parameters
|
15
|
+
|
16
|
+
if params['help'] and params['help'].given?
|
17
|
+
print usage.to_s
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
|
21
|
+
pre_run
|
22
|
+
|
23
|
+
self.class.const_get(:RUN).bind(self).call(*a, &b)
|
24
|
+
|
25
|
+
post_run
|
26
|
+
|
27
|
+
finalize
|
28
|
+
rescue Exception => e
|
29
|
+
handle_exception e
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_added m
|
36
|
+
return if @in_method_added
|
37
|
+
super if defined? super
|
38
|
+
@in_method_added = true
|
39
|
+
begin
|
40
|
+
wrap_run! if m.to_s == 'run'
|
41
|
+
ensure
|
42
|
+
@in_method_added = false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.inheritable_attribute name, &block
|
47
|
+
block ||= lambda{}
|
48
|
+
attribute( name ){
|
49
|
+
catch :value do
|
50
|
+
if parent?
|
51
|
+
value = parent.send name
|
52
|
+
value =
|
53
|
+
begin
|
54
|
+
Util.mcp value
|
55
|
+
rescue
|
56
|
+
value.clone rescue value.dup
|
57
|
+
end
|
58
|
+
throw :value, value
|
59
|
+
end
|
60
|
+
instance_eval &block
|
61
|
+
end
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
5
65
|
attribute( 'name' ){ File.basename $0 }
|
6
|
-
attribute( 'synopsis' ){ Usage.default_synopsis
|
66
|
+
attribute( 'synopsis' ){ Usage.default_synopsis(self) }
|
7
67
|
attribute( 'description' )
|
68
|
+
attribute( 'usage' ){ Usage.default_usage self }
|
69
|
+
attribute( 'modes' ){ Mode.list }
|
70
|
+
attribute( 'mode_name' ){ 'main' }
|
71
|
+
def mode_name=(value) @mode_name = Mode.new value end
|
72
|
+
attribute( 'parent' ){ nil }
|
73
|
+
attribute( 'children' ){ Set.new }
|
74
|
+
|
75
|
+
attribute( 'program' ){ File.basename $0 }
|
8
76
|
attribute( 'author' )
|
9
77
|
attribute( 'version' )
|
10
78
|
attribute( 'stdin' ){ $stdin }
|
@@ -16,12 +84,46 @@ module Main
|
|
16
84
|
attribute( 'exit_success' ){ EXIT_SUCCESS }
|
17
85
|
attribute( 'exit_failure' ){ EXIT_FAILURE }
|
18
86
|
attribute( 'exit_warn' ){ EXIT_WARN }
|
19
|
-
|
87
|
+
inheritable_attribute( 'parameters' ){ Parameter::List[] }
|
20
88
|
|
21
|
-
def
|
22
|
-
|
89
|
+
def create parent = Base, *a, &b
|
90
|
+
Class.new parent do |child|
|
91
|
+
child.parent = parent unless parent == Base
|
92
|
+
parent.children.add child
|
93
|
+
child.context do
|
94
|
+
child.class_eval &b if b
|
95
|
+
child.default_options!
|
96
|
+
end
|
97
|
+
end
|
23
98
|
end
|
24
99
|
|
100
|
+
def context &block
|
101
|
+
@@context ||= []
|
102
|
+
unless block
|
103
|
+
@@context.last
|
104
|
+
else
|
105
|
+
begin
|
106
|
+
@@context.push self
|
107
|
+
block.call @@context.last
|
108
|
+
ensure
|
109
|
+
@@context.pop
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def fully_qualified_mode
|
115
|
+
list = []
|
116
|
+
ancestors.each do |ancestor|
|
117
|
+
break unless ancestor < Base
|
118
|
+
list << ancestor.mode_name
|
119
|
+
end
|
120
|
+
list.reverse[1..-1]
|
121
|
+
end
|
122
|
+
|
123
|
+
def run(&b) define_method(:run, &b) end
|
124
|
+
end
|
125
|
+
|
126
|
+
module DSL
|
25
127
|
def parameter *a, &b
|
26
128
|
parameters << Parameter.new(*a, &b)
|
27
129
|
end
|
@@ -33,7 +135,7 @@ module Main
|
|
33
135
|
alias_method 'switch', 'option'
|
34
136
|
|
35
137
|
def default_options!
|
36
|
-
option 'help', 'h'
|
138
|
+
option 'help', 'h' unless parameters.has_option?('help', 'h')
|
37
139
|
end
|
38
140
|
|
39
141
|
def argument *a, &b
|
@@ -51,10 +153,16 @@ module Main
|
|
51
153
|
end
|
52
154
|
alias_method 'env', 'environment'
|
53
155
|
|
54
|
-
def
|
55
|
-
|
156
|
+
def mode name, &b
|
157
|
+
klass =
|
158
|
+
create context do
|
159
|
+
mode_name name
|
160
|
+
module_eval &b if b
|
161
|
+
end
|
162
|
+
modes.add klass
|
56
163
|
end
|
57
164
|
end
|
165
|
+
extend DSL
|
58
166
|
|
59
167
|
attribute 'argv'
|
60
168
|
attribute 'env'
|
@@ -77,14 +185,6 @@ module Main
|
|
77
185
|
alias_method "#{ dst }?", "params?"
|
78
186
|
end
|
79
187
|
|
80
|
-
%w( exit_success! exit_failure! exit_warn! ).each do |code|
|
81
|
-
module_eval <<-code
|
82
|
-
def #{ code } *a, &b
|
83
|
-
exit #{ code.chop }
|
84
|
-
end
|
85
|
-
code
|
86
|
-
end
|
87
|
-
|
88
188
|
%w( debug info warn fatal error ).each do |m|
|
89
189
|
module_eval <<-code
|
90
190
|
def #{ m } *a, &b
|
@@ -137,6 +237,7 @@ module Main
|
|
137
237
|
@logger.level = logger_level
|
138
238
|
end
|
139
239
|
end
|
240
|
+
@logger
|
140
241
|
end
|
141
242
|
|
142
243
|
def setup_io_restoration
|
@@ -160,12 +261,7 @@ module Main
|
|
160
261
|
rescue
|
161
262
|
$stdin = @stdin
|
162
263
|
::Object.const_set 'STDIN', @stdin
|
163
|
-
#p STDIN
|
164
|
-
#p STDIN.read
|
165
264
|
end
|
166
|
-
#p 'STDIN' => STDIN
|
167
|
-
#p '@stdin' => @stdin
|
168
|
-
#p '$stdin' => $stdin
|
169
265
|
end
|
170
266
|
end
|
171
267
|
|
@@ -209,10 +305,37 @@ module Main
|
|
209
305
|
end
|
210
306
|
def post_parse_parameters() :hook end
|
211
307
|
|
212
|
-
def pre_run() end
|
308
|
+
def pre_run() :hook end
|
213
309
|
def run
|
214
310
|
raise NotImplementedError, 'run not defined'
|
215
311
|
end
|
216
|
-
def post_run() end
|
312
|
+
def post_run() :hook end
|
313
|
+
|
314
|
+
def mode_given?
|
315
|
+
self.class.modes.find_by_mode argv.first, :quiet => true if argv.first
|
316
|
+
end
|
317
|
+
|
318
|
+
def mode_run!
|
319
|
+
mode = self.class.modes.find_by_mode argv.shift
|
320
|
+
klass = self.class.modes[mode] or abort "bad mode <#{ mode }>"
|
321
|
+
main = klass.new @argv, @env, @opts
|
322
|
+
main.run
|
323
|
+
end
|
324
|
+
|
325
|
+
def handle_exception e
|
326
|
+
if e.respond_to? :status
|
327
|
+
exit_status(( e.status ))
|
328
|
+
end
|
329
|
+
|
330
|
+
if Softspoken === e or SystemExit === e
|
331
|
+
stderr.puts e.message unless(SystemExit === e and e.message.to_s == 'exit')
|
332
|
+
else
|
333
|
+
fatal{ e }
|
334
|
+
end
|
335
|
+
|
336
|
+
exit_status(( exit_failure )) if exit_status == exit_success
|
337
|
+
exit_status(( Integer(exit_status) rescue(exit_status ? 0 : 1) ))
|
338
|
+
exit exit_status
|
339
|
+
end
|
217
340
|
end
|
218
341
|
end
|
data/lib/main/factories.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
module Main
|
2
|
-
def
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
def Main.create *a, &b
|
3
|
+
::Main::Base.create(::Main::Base, *a, &b)
|
4
|
+
end
|
5
|
+
|
6
|
+
def Main.new *a, &b
|
7
|
+
create(::Main::Base, &b).new *a
|
8
|
+
end
|
9
|
+
|
10
|
+
def Main.run argv = ARGV, env = ENV, opts = {}, &block
|
11
|
+
Base.create(&block).new(argv, env, opts).run
|
8
12
|
end
|
9
13
|
|
10
14
|
module ::Kernel
|
11
|
-
def Main
|
12
|
-
::Main.
|
15
|
+
def Main argv = ARGV, env = ENV, opts = {}, &block
|
16
|
+
::Main.run argv, env, opts, &block
|
13
17
|
end
|
14
18
|
alias_method 'main', 'Main'
|
15
19
|
end
|
data/lib/main/mode.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
class Mode < ::String
|
2
|
+
class Error < ::StandardError; end
|
3
|
+
class Duplicate < Error; end
|
4
|
+
class Ambigous < Error
|
5
|
+
include Main::Softspoken
|
6
|
+
end
|
7
|
+
|
8
|
+
class List < ::Array
|
9
|
+
def initialize *a, &b
|
10
|
+
super
|
11
|
+
ensure
|
12
|
+
self.fields = []
|
13
|
+
end
|
14
|
+
def add klass
|
15
|
+
mode_name = Mode.new klass.mode_name
|
16
|
+
raise Duplicate, mode_name if has_key? mode_name
|
17
|
+
self[mode_name] = klass
|
18
|
+
end
|
19
|
+
def find_by_mode m, options = {}
|
20
|
+
quiet = options['quiet'] || options[:quiet]
|
21
|
+
each_pair do |mode, klass|
|
22
|
+
return mode if mode == m
|
23
|
+
end
|
24
|
+
candidates = []
|
25
|
+
each_pair do |mode, klass|
|
26
|
+
candidates << mode if mode.index(m) == 0
|
27
|
+
end
|
28
|
+
case candidates.size
|
29
|
+
when 0
|
30
|
+
nil
|
31
|
+
when 1
|
32
|
+
candidates.first
|
33
|
+
else
|
34
|
+
quiet ? nil : raise(Ambigous, m)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.list *a, &b
|
40
|
+
List.new *a, &b
|
41
|
+
end
|
42
|
+
end
|
data/lib/main/parameter.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
module Main
|
2
2
|
class Parameter
|
3
|
-
class Error < StandardError
|
4
|
-
|
3
|
+
class Error < StandardError
|
4
|
+
include Softspoken
|
5
|
+
attribute 'wrapped'
|
6
|
+
end
|
5
7
|
class Arity < Error; end
|
8
|
+
class NotGiven < Arity; end
|
6
9
|
class InValid < Error; end
|
7
10
|
class NoneSuch < Error; end
|
8
11
|
class AmbigousOption < Error; end
|
@@ -11,10 +14,6 @@ module Main
|
|
11
14
|
class InvalidOption < Error; end
|
12
15
|
|
13
16
|
class << self
|
14
|
-
def new *a, &b
|
15
|
-
raise
|
16
|
-
end
|
17
|
-
|
18
17
|
def wrapped_error w
|
19
18
|
e = Error.new "(#{ w.message } (#{ w.class }))"
|
20
19
|
e.wrapped = w
|
@@ -137,33 +136,35 @@ module Main
|
|
137
136
|
|
138
137
|
def setup!
|
139
138
|
return false unless given?
|
140
|
-
|
141
|
-
|
142
|
-
|
139
|
+
check_arity
|
140
|
+
apply_casting
|
141
|
+
check_validation
|
143
142
|
true
|
144
143
|
end
|
145
144
|
|
146
|
-
def
|
147
|
-
raise Arity, "#{ typename })" if values.size.zero? and argument_required?
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
145
|
+
def check_arity
|
146
|
+
(raise Arity, "#{ typename })" if values.size.zero? and argument_required?) unless arity == -1
|
147
|
+
|
148
|
+
if arity >= 0
|
149
|
+
min = arity
|
150
|
+
sign = ''
|
151
|
+
else
|
152
|
+
min = arity.abs - 1
|
153
|
+
sign = '-'
|
154
154
|
end
|
155
|
-
end
|
156
155
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
156
|
+
arity = min
|
157
|
+
|
158
|
+
if values.size < arity
|
159
|
+
if argument_required? or argument_none?
|
160
|
+
raise Arity, "#{ typename }) #{ values.size }/#{ sign }#{ arity }" if(values.size < arity)
|
161
|
+
elsif argument_optional?
|
162
|
+
raise Arity, "#{ typename }) #{ values.size }/#{ sign }#{ arity }" if(values.size < arity and values.size > 0)
|
162
163
|
end
|
163
164
|
end
|
164
165
|
end
|
165
166
|
|
166
|
-
def
|
167
|
+
def apply_casting
|
167
168
|
if cast?
|
168
169
|
op = cast.respond_to?('call') ? cast : Cast[cast]
|
169
170
|
values.map! do |val|
|
@@ -172,15 +173,24 @@ module Main
|
|
172
173
|
end
|
173
174
|
end
|
174
175
|
|
176
|
+
def check_validation
|
177
|
+
if validate?
|
178
|
+
values.each do |value|
|
179
|
+
validate[value] or
|
180
|
+
raise InValid, "invalid: #{ typename }=#{ value.inspect }"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
175
185
|
class Argument < Parameter
|
176
|
-
attribute 'required' => true
|
186
|
+
attribute 'required' => true
|
177
187
|
|
178
188
|
attribute 'synopsis' do
|
179
189
|
label = name
|
180
190
|
op = required ? "->" : "~>"
|
181
191
|
value = defaults.size > 0 ? "#{ name }=#{ defaults.join ',' }" : name
|
182
192
|
value = "#{ cast }(#{ value })" if cast
|
183
|
-
"#{ label }
|
193
|
+
"#{ label } (#{ arity } #{ op } #{ value })"
|
184
194
|
end
|
185
195
|
end
|
186
196
|
|
@@ -196,7 +206,7 @@ module Main
|
|
196
206
|
op = required ? "->" : "~>"
|
197
207
|
value = defaults.size > 0 ? "#{ name }=#{ defaults.join ',' }" : name
|
198
208
|
value = "#{ cast }(#{ value })" if cast
|
199
|
-
"#{ label }
|
209
|
+
"#{ label } (#{ arity } #{ op } #{ value })"
|
200
210
|
else
|
201
211
|
label
|
202
212
|
end
|
@@ -212,7 +222,7 @@ module Main
|
|
212
222
|
op = required ? "->" : "~>"
|
213
223
|
value = defaults.size > 0 ? "#{ name }=#{ defaults.join ',' }" : name
|
214
224
|
value = "#{ cast }(#{ value })" if cast
|
215
|
-
"#{ label }
|
225
|
+
"#{ label } (#{ arity } #{ op } #{ value })"
|
216
226
|
end
|
217
227
|
end
|
218
228
|
|
@@ -224,7 +234,7 @@ module Main
|
|
224
234
|
op = required ? "->" : "~>"
|
225
235
|
value = defaults.size > 0 ? "#{ name }=#{ defaults.join ',' }" : name
|
226
236
|
value = "#{ cast }(#{ value })" if cast
|
227
|
-
"#{ label }
|
237
|
+
"#{ label } (#{ arity } #{ op } #{ value })"
|
228
238
|
end
|
229
239
|
end
|
230
240
|
|
@@ -241,7 +251,7 @@ module Main
|
|
241
251
|
end
|
242
252
|
|
243
253
|
def parse_options argv, params = nil
|
244
|
-
params ||=
|
254
|
+
params ||= options
|
245
255
|
|
246
256
|
spec, h, s = [], {}, {}
|
247
257
|
|
@@ -279,6 +289,7 @@ module Main
|
|
279
289
|
c = Parameter.const_get e.class.name.split(/::/).last
|
280
290
|
ex = c.new e.message
|
281
291
|
ex.set_backtrace e.message
|
292
|
+
ex.extend Softspoken
|
282
293
|
raise ex
|
283
294
|
end
|
284
295
|
|
@@ -291,10 +302,23 @@ module Main
|
|
291
302
|
params ||= select{|p| p.type == :argument}
|
292
303
|
|
293
304
|
params.each do |p|
|
294
|
-
p.arity
|
295
|
-
|
296
|
-
|
297
|
-
|
305
|
+
if p.arity >= 0
|
306
|
+
p.arity.times do
|
307
|
+
break if argv.empty?
|
308
|
+
value = argv.shift
|
309
|
+
p.add_value value
|
310
|
+
end
|
311
|
+
else
|
312
|
+
arity = p.arity.abs - 1
|
313
|
+
arity.times do
|
314
|
+
break if argv.empty?
|
315
|
+
value = argv.shift
|
316
|
+
p.add_value value
|
317
|
+
end
|
318
|
+
argv.size.times do
|
319
|
+
value = argv.shift
|
320
|
+
p.add_value value
|
321
|
+
end
|
298
322
|
end
|
299
323
|
end
|
300
324
|
|
@@ -351,11 +375,9 @@ module Main
|
|
351
375
|
|
352
376
|
def defaults!
|
353
377
|
each do |p|
|
354
|
-
#p.add_value p.default if(p.default? and (not p.given?))
|
355
378
|
if(p.defaults? and (not p.given?))
|
356
379
|
p.defaults.each do |default|
|
357
|
-
|
358
|
-
p.values << default # so as NOT to set given?
|
380
|
+
p.values << default # so as NOT to set 'given?'
|
359
381
|
end
|
360
382
|
end
|
361
383
|
end
|
@@ -363,7 +385,23 @@ module Main
|
|
363
385
|
|
364
386
|
def validate!
|
365
387
|
each do |p|
|
366
|
-
|
388
|
+
next if p.arity == -1
|
389
|
+
raise NotGiven, "#{ p.typename } not given" if(p.required? and (not p.given?))
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
[:parameter, :option, :argument, :keyword, :environment].each do |m|
|
394
|
+
define_method("#{ m }s"){ select{|p| p.type == m or m == :parameter} }
|
395
|
+
|
396
|
+
define_method("has_#{ m }?") do |name, *names|
|
397
|
+
catch :has do
|
398
|
+
names = Cast.list_of_string name, *names
|
399
|
+
send("#{ m }s").each do |param|
|
400
|
+
common = Cast.list_of_string(param.names) & names
|
401
|
+
throw :has, true unless common.empty?
|
402
|
+
end
|
403
|
+
false
|
404
|
+
end
|
367
405
|
end
|
368
406
|
end
|
369
407
|
end
|
@@ -472,6 +510,7 @@ module Main
|
|
472
510
|
end
|
473
511
|
|
474
512
|
def arity value
|
513
|
+
value = -1 if value.to_s == '*'
|
475
514
|
p.arity = Integer value
|
476
515
|
end
|
477
516
|
def arity?
|