main 0.0.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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?
|