main 0.0.1

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.
@@ -0,0 +1,138 @@
1
+ module Main
2
+ class Usage < ::Array
3
+ attribute 'chunkname'
4
+ attribute 'upcase'
5
+ attribute 'eos'
6
+
7
+ def initialize opts={}
8
+ self.fields=[]
9
+ self.chunkname = lambda{|chunkname| chunkname.to_s.strip.upcase}
10
+ self.upcase = true
11
+ self.eos = "\n\n"
12
+ if opts.has_key?(:upcase) or opts.has_key?('upcase')
13
+ self.upcase = opts[:upcase] || opts['optcase']
14
+ end
15
+ end
16
+
17
+ def clear
18
+ super
19
+ ensure
20
+ fields.clear
21
+ end
22
+
23
+ def delete_at key
24
+ self[key] = nil
25
+ end
26
+ alias_method 'delete', 'delete_at'
27
+
28
+ def self.default_synopsis main
29
+ s = "#{ main.name }"
30
+
31
+ main.parameters.each do |p|
32
+ if p.type == :argument
33
+ if p.required?
34
+ s << " #{ p.name }"
35
+ else
36
+ s << " [#{ p.name }]"
37
+ end
38
+ end
39
+ end
40
+
41
+ main.parameters.each do |p|
42
+ if p.type == :keyword
43
+ if p.required?
44
+ s << " #{ p.name }=#{ p.name }"
45
+ else
46
+ s << " [#{ p.name }=#{ p.name }]"
47
+ end
48
+ end
49
+ end
50
+
51
+ n = 0
52
+ main.parameters.each do |p|
53
+ if p.type == :option
54
+ if p.required?
55
+ case p.argument
56
+ when :required
57
+ s << " --#{ p.name }=#{ p.name }"
58
+ when :optional
59
+ s << " --#{ p.name }=[#{ p.name }]"
60
+ else
61
+ s << " --#{ p.name }"
62
+ end
63
+ else
64
+ n += 1
65
+ end
66
+ end
67
+ end
68
+ if n > 0
69
+ s << " [options]+"
70
+ end
71
+
72
+ s
73
+ end
74
+
75
+ def self.default_usage main
76
+ usage = new
77
+
78
+ # name
79
+ usage['name'] =
80
+ if main.version?
81
+ "#{ main.name } v#{ main.version }"
82
+ else
83
+ "#{ main.name }"
84
+ end
85
+
86
+ # synopsis
87
+ usage['synopsis'] = main.synopsis
88
+
89
+ # description
90
+ usage['description'] = main.description if main.description?
91
+
92
+ # parameters
93
+ arguments = main.parameters.select{|p| p.type == :argument}
94
+ keywords = main.parameters.select{|p| p.type == :keyword}
95
+ options = main.parameters.select{|p| p.type == :option}
96
+ environment = main.parameters.select{|p| p.type == :environment}
97
+
98
+ help, nothelp = options.partition{|p| p.name == 'help'}
99
+ options = nothelp + help
100
+
101
+ parameters = arguments + keywords + options + environment
102
+
103
+ s =
104
+ parameters.map do |p|
105
+ ps = ''
106
+ ps << Util.columnize("* #{ p.synopsis }", :indent => 2, :width => 78)
107
+ ps << "\n"
108
+ if p.description?
109
+ ps << Util.columnize(p.description, :indent => 6, :width => 78)
110
+ ps << "\n"
111
+ end
112
+ ps
113
+ end.join("\n")
114
+ usage['parameters'] = s
115
+
116
+ # author
117
+ usage['author'] = main.author if main.author?
118
+
119
+ usage
120
+ end
121
+ class << self
122
+ alias_method "default", "default_usage"
123
+ end
124
+
125
+ def to_s
126
+ s = ''
127
+ each_pair do |key, value|
128
+ up, down = key.to_s.upcase, key.to_s.downcase
129
+ if value
130
+ s << (upcase ? up : down) << "\n"
131
+ s << Util.indent(Util.unindent(value.to_s), 2)
132
+ s << eos
133
+ end
134
+ end
135
+ s
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,91 @@
1
+ module Main
2
+ module Util
3
+ module ClassMethods
4
+ end
5
+
6
+ module InstanceMethods
7
+ end
8
+
9
+ module Methods
10
+ def mcp obj
11
+ Marshal.load(Marshal.dump(obj))
12
+ end
13
+
14
+ def indent chunk, n = 2
15
+ lines = chunk.split %r/\n/
16
+ re = nil
17
+ s = ' ' * n
18
+ lines.map! do |line|
19
+ unless re
20
+ margin = line[%r/^\s*/]
21
+ re = %r/^#{ margin }/
22
+ end
23
+ line.gsub re, s
24
+ end.join("\n")
25
+ end
26
+
27
+ def unindent chunk
28
+ lines = chunk.split %r/\n/
29
+ indent = nil
30
+ re = %r/^/
31
+ lines.map! do |line|
32
+ unless indent
33
+ indent = line[%r/^\s*/]
34
+ re = %r/^#{ indent }/
35
+ end
36
+ line.gsub re, ''
37
+ end.join("\n")
38
+ end
39
+
40
+ def columnize buf, opts = {}
41
+ width = Util.getopt 'width', opts, 80
42
+ indent = Util.getopt 'indent', opts
43
+ indent = Fixnum === indent ? (' ' * indent) : "#{ indent }"
44
+ column = []
45
+ words = buf.split %r/\s+/o
46
+ row = "#{ indent }"
47
+ while((word = words.shift))
48
+ if((row.size + word.size) < (width - 1))
49
+ row << word
50
+ else
51
+ column << row
52
+ row = "#{ indent }"
53
+ row << word
54
+ end
55
+ row << ' ' unless row.size == (width - 1)
56
+ end
57
+ column << row unless row.strip.empty?
58
+ column.join "\n"
59
+ end
60
+
61
+ def getopt opt, hash, default = nil
62
+ keys = opt.respond_to?('each') ? opt : [opt]
63
+
64
+ keys.each do |key|
65
+ return hash[key] if hash.has_key? key
66
+ key = "#{ key }"
67
+ return hash[key] if hash.has_key? key
68
+ key = key.intern
69
+ return hash[key] if hash.has_key? key
70
+ end
71
+
72
+ return default
73
+ end
74
+ end
75
+
76
+ BLESS = lambda do |other|
77
+ other.module_eval{
78
+ include Methods
79
+ include InstanceMethods
80
+ extend Methods
81
+ extend ClassMethods
82
+ }
83
+ end
84
+
85
+ def self.included other
86
+ BLESS[ other ]
87
+ end
88
+
89
+ BLESS[ self ]
90
+ end
91
+ end
File without changes
@@ -0,0 +1,17 @@
1
+ require 'main'
2
+
3
+ ARGV.replace %w( 42 ) if ARGV.empty?
4
+
5
+ Main {
6
+ argument('foo'){
7
+ required # this is the default
8
+ cast :int # value cast to Fixnum
9
+ validate{|foo| foo == 42} # raises error in failure case
10
+ description 'the foo param' # shown in --help
11
+ }
12
+
13
+ def run
14
+ p params['foo'].given?
15
+ p params['foo'].value
16
+ end
17
+ }
@@ -0,0 +1,17 @@
1
+ require 'main'
2
+
3
+ ARGV.replace %w( 40 1 1 ) if ARGV.empty?
4
+
5
+ Main {
6
+ argument('foo'){
7
+ arity 3 # foo will given three times
8
+ cast :int # value cast to Fixnum
9
+ validate{|foo| [40,1].include? foo} # raises error in failure case
10
+ description 'the foo param' # shown in --help
11
+ }
12
+
13
+ def run
14
+ p params['foo'].given?
15
+ p params['foo'].values
16
+ end
17
+ }
@@ -0,0 +1,21 @@
1
+ require 'main'
2
+
3
+ ARGV.replace %w( foo=40 foo=2 bar=false ) if ARGV.empty?
4
+
5
+ Main {
6
+ keyword('foo'){
7
+ required # by default keywords are not required
8
+ arity 2
9
+ cast :float
10
+ }
11
+ keyword('bar'){
12
+ cast :bool
13
+ }
14
+
15
+ def run
16
+ p params['foo'].given?
17
+ p params['foo'].values
18
+ p params['bar'].given?
19
+ p params['bar'].value
20
+ end
21
+ }
@@ -0,0 +1,26 @@
1
+ require 'main'
2
+
3
+ ARGV.replace %w( --foo=40 -f2 ) if ARGV.empty?
4
+
5
+ Main {
6
+ option('foo', 'f'){
7
+ required # by default options are not required, we could use 'foo=foo'
8
+ # above as a shortcut
9
+ argument_required
10
+ arity 2
11
+ cast :float
12
+ }
13
+
14
+ option('bar=[bar]', 'b'){ # note shortcut syntax for optional args
15
+ # argument_optional # we could also use this method
16
+ cast :bool
17
+ default false
18
+ }
19
+
20
+ def run
21
+ p params['foo'].given?
22
+ p params['foo'].values
23
+ p params['bar'].given?
24
+ p params['bar'].value
25
+ end
26
+ }
@@ -0,0 +1,523 @@
1
+ $:.unshift '.'
2
+ $:.unshift './lib'
3
+ $:.unshift '..'
4
+ $:.unshift '../lib'
5
+
6
+ require 'stringio'
7
+ require 'test/unit'
8
+ require 'main'
9
+
10
+ class T < Test::Unit::TestCase
11
+ attr 'status'
12
+
13
+ def setup
14
+ @status = nil
15
+ @logger = Logger.new StringIO.new
16
+ @error = nil
17
+ end
18
+
19
+ def teardown
20
+ end
21
+
22
+ def main argv=[], env={}, &b
23
+ at_exit{ exit! }
24
+ $VERBOSE=nil
25
+ ARGV.replace argv
26
+ ENV.clear
27
+ env.each{|k,v| ENV[k.to_s]=v.to_s}
28
+ main = nil
29
+ begin
30
+ main = Object::Main.new(&b)
31
+ main.logger = @logger
32
+ main.__run__
33
+ rescue Exception => e
34
+ if SystemExit === e
35
+ @status = e.status
36
+ else
37
+ raise
38
+ end
39
+ end
40
+ main
41
+ end
42
+
43
+ #
44
+ # basic test
45
+ #
46
+ def test_0000
47
+ assert_nothing_raised{
48
+ main{
49
+ def run() end
50
+ }
51
+ }
52
+ end
53
+ def test_0010
54
+ x = nil
55
+ assert_nothing_raised{
56
+ main{
57
+ define_method(:run){ x = 42 }
58
+ }
59
+ }
60
+ assert x == 42
61
+ end
62
+ #
63
+ # exit status
64
+ #
65
+ def test_0020
66
+ assert_nothing_raised{
67
+ main{
68
+ def run() end
69
+ }
70
+ }
71
+ assert status == 0
72
+ end
73
+ def test_0030
74
+ assert_nothing_raised{
75
+ main{
76
+ def run() exit 42 end
77
+ }
78
+ }
79
+ assert status == 42
80
+ end
81
+ def test_0040
82
+ assert_nothing_raised{
83
+ fork{
84
+ main{
85
+ def run() exit! 42 end
86
+ }
87
+ }
88
+ Process.wait
89
+ assert $?.exitstatus == 42
90
+ }
91
+ end
92
+ def test_0050
93
+ assert_nothing_raised{
94
+ main{
95
+ def run() raise end
96
+ }
97
+ }
98
+ assert status == 1
99
+ end
100
+ def test_0060
101
+ assert_nothing_raised{
102
+ main{
103
+ def run() raise ArgumentError end
104
+ }
105
+ }
106
+ assert status == 1
107
+ end
108
+ def test_0060
109
+ assert_nothing_raised{
110
+ main{
111
+ def run() exit_status 42; raise end
112
+ }
113
+ }
114
+ assert status == 42
115
+ end
116
+ def test_0070
117
+ assert_nothing_raised{
118
+ main{
119
+ def run() exit_status 42; raise ArgumentError end
120
+ }
121
+ }
122
+ assert status == 42
123
+ end
124
+ #
125
+ # parameter parsing
126
+ #
127
+ def test_0080
128
+ p = nil
129
+ argv = %w[ 42 ]
130
+ assert_nothing_raised{
131
+ main(argv){
132
+ parameter('foo'){ type :argument }
133
+ define_method('run'){ p = param['foo'] }
134
+ }
135
+ }
136
+ assert p.value == argv.first
137
+ assert p.values == argv
138
+ end
139
+ def test_0080
140
+ p = nil
141
+ assert_raises(Main::Parameter::NotGiven){
142
+ main(){
143
+ argument 'foo'
144
+ define_method('run'){ }
145
+ }
146
+ }
147
+ end
148
+ def test_0090
149
+ p = nil
150
+ argv = %w[ 42 ]
151
+ given = nil
152
+ assert_nothing_raised{
153
+ main(argv){
154
+ argument 'foo'
155
+ define_method('run'){ p = param['foo'] }
156
+ }
157
+ }
158
+ assert p.value == argv.first
159
+ assert p.values == argv
160
+ assert p.given?
161
+ end
162
+ def test_0100
163
+ p = nil
164
+ argv = %w[]
165
+ given = nil
166
+ assert_nothing_raised{
167
+ main(argv){
168
+ p = argument('foo'){ optional }
169
+ define_method('run'){ p = param['foo'] }
170
+ }
171
+ }
172
+ assert p.optional?
173
+ assert !p.required?
174
+ assert p.value == nil
175
+ assert p.values == []
176
+ assert !p.given?
177
+ end
178
+ def test_0101
179
+ p = nil
180
+ argv = %w[]
181
+ given = nil
182
+ assert_nothing_raised{
183
+ main(argv){
184
+ p = argument('foo'){ required false }
185
+ define_method('run'){ p = param['foo'] }
186
+ }
187
+ }
188
+ assert p.optional?
189
+ assert !p.required?
190
+ assert p.value == nil
191
+ assert p.values == []
192
+ assert !p.given?
193
+ end
194
+ def test_0110
195
+ p = nil
196
+ argv = %w[ --foo ]
197
+ assert_nothing_raised{
198
+ main(argv){
199
+ option('foo'){ required }
200
+ define_method('run'){ p = param['foo'] }
201
+ }
202
+ }
203
+ assert p.value == true
204
+ assert p.values ==[true]
205
+ assert p.given?
206
+ end
207
+ def test_0120
208
+ p = nil
209
+ argv = []
210
+ assert_nothing_raised{
211
+ main(argv){
212
+ option 'foo'
213
+ define_method('run'){ p = param['foo'] }
214
+ }
215
+ }
216
+ assert p.value == nil
217
+ assert p.values == []
218
+ assert !p.given?
219
+ end
220
+ def test_0130
221
+ p = nil
222
+ assert_nothing_raised{
223
+ main(%w[--foo=42]){
224
+ option('foo'){ required; argument_required }
225
+ define_method('run'){ p = param['foo']}
226
+ }
227
+ }
228
+ assert p.required?
229
+ assert p.argument_required?
230
+ assert !p.optional?
231
+ end
232
+ def test_0131
233
+ assert_raises(Main::Parameter::NotGiven){
234
+ main(){
235
+ option('foo'){ required; argument_required }
236
+ define_method('run'){}
237
+ }
238
+ }
239
+ end
240
+ def test_0140
241
+ assert_raises(Main::Parameter::MissingArgument){
242
+ main(['--foo']){
243
+ option('foo'){ required; argument_required }
244
+ define_method('run'){}
245
+ }
246
+ }
247
+ end
248
+ def test_0150
249
+ param = nil
250
+ assert_nothing_raised{
251
+ main(%w[--foo=42 --bar=42.0 --foobar=true --barfoo=false --uri=http://foo --x=s]){
252
+ option('foo'){
253
+ required
254
+ argument_required
255
+ cast :int
256
+ }
257
+ option('bar'){
258
+ argument_required
259
+ cast :float
260
+ }
261
+ option('foobar'){
262
+ argument_required
263
+ cast :bool
264
+ }
265
+ option('barfoo'){
266
+ argument_required
267
+ cast :string
268
+ }
269
+ option('uri'){
270
+ argument_required
271
+ cast :uri
272
+ }
273
+ option('x'){
274
+ argument_required
275
+ cast{|x| x.to_s.upcase}
276
+ }
277
+ define_method('run'){ param = params }
278
+ }
279
+ }
280
+ assert param['foo'].value == 42
281
+ assert param['bar'].value == 42.0
282
+ assert param['foobar'].value == true
283
+ assert param['barfoo'].value == 'false'
284
+ assert param['uri'].value == URI.parse('http://foo')
285
+ assert param['x'].value == 'S'
286
+ end
287
+ def test_0160
288
+ p = nil
289
+ assert_nothing_raised{
290
+ main(%w[--foo=42]){
291
+ option('foo'){
292
+ required
293
+ argument_required
294
+ cast :int
295
+ validate{|x| x == 42}
296
+ }
297
+ define_method('run'){ p = param['foo']}
298
+ }
299
+ }
300
+ assert p.value == 42
301
+ assert p.required?
302
+ assert p.argument_required?
303
+ assert !p.optional?
304
+ end
305
+ def test_0170
306
+ assert_raises(Main::Parameter::InValid){
307
+ main(%w[--foo=40]){
308
+ option('foo'){
309
+ required
310
+ argument_required
311
+ cast :int
312
+ validate{|x| x == 42}
313
+ }
314
+ define_method('run'){ }
315
+ }
316
+ }
317
+ end
318
+ def test_0180
319
+ assert_nothing_raised{
320
+ main(%w[--foo=42]){
321
+ option('--foo=foo'){
322
+ required
323
+ # argument_required
324
+ cast :int
325
+ validate{|x| x == 42}
326
+ }
327
+ define_method('run'){ }
328
+ }
329
+ }
330
+ end
331
+ def test_0190
332
+ assert_raises(Main::Parameter::MissingArgument){
333
+ main(%w[--foo]){
334
+ option('--foo=foo'){ }
335
+ define_method('run'){ }
336
+ }
337
+ }
338
+ end
339
+ def test_0200
340
+ p = nil
341
+ assert_nothing_raised{
342
+ main(%w[--foo]){
343
+ option('--foo=[foo]'){ }
344
+ define_method('run'){ p = param['foo'] }
345
+ }
346
+ }
347
+ assert p.value == true
348
+ end
349
+ def test_0210
350
+ p = nil
351
+ assert_nothing_raised{
352
+ main(%w[--foo=42]){
353
+ option('--foo=[foo]'){
354
+ cast :int
355
+ validate{|x| x == 42}
356
+ }
357
+ define_method('run'){ p = param['foo'] }
358
+ }
359
+ }
360
+ assert p.value == 42
361
+ end
362
+ def test_0220
363
+ p = nil
364
+ assert_nothing_raised{
365
+ main(%w[--foo=40 --foo=2]){
366
+ option('--foo=foo'){
367
+ arity 2
368
+ cast :int
369
+ validate{|x| x == 40 or x == 2}
370
+ }
371
+ define_method('run'){ p = param['foo'] }
372
+ }
373
+ }
374
+ assert p.value == 40
375
+ assert p.values == [40,2]
376
+ end
377
+ def test_0230
378
+ p = nil
379
+ assert_nothing_raised{
380
+ main(%w[foo=42]){
381
+ keyword('foo'){
382
+ cast :int
383
+ validate{|x| x == 42}
384
+ }
385
+ define_method('run'){ p = param['foo'] }
386
+ }
387
+ }
388
+ assert p.value == 42
389
+ end
390
+ def test_0240
391
+ foo = nil
392
+ bar = nil
393
+ assert_nothing_raised{
394
+ main(%w[foo= bar]){
395
+ keyword 'foo'
396
+ keyword 'bar'
397
+ define_method('run'){
398
+ foo = param['foo']
399
+ bar = param['bar']
400
+ }
401
+ }
402
+ }
403
+ assert foo.value == ''
404
+ assert bar.value == nil
405
+ end
406
+ def test_0250
407
+ foo = nil
408
+ bar = nil
409
+ assert_nothing_raised{
410
+ main(%w[foo=40 bar=2]){
411
+ keyword('foo'){
412
+ cast :int
413
+ }
414
+ keyword('bar'){
415
+ cast :int
416
+ }
417
+ define_method('run'){
418
+ foo = param['foo']
419
+ bar = param['bar']
420
+ }
421
+ }
422
+ }
423
+ assert foo.value == 40
424
+ assert bar.value == 2
425
+ end
426
+ def test_0260
427
+ foo = nil
428
+ bar = nil
429
+ foobar = nil
430
+ assert_nothing_raised{
431
+ main(%w[foo=40 --bar=2 foobar foo=42]){
432
+ kw('foo'){ cast :int; arity 2 }
433
+ opt('bar='){ cast :int }
434
+ arg 'foobar'
435
+
436
+ define_method('run'){
437
+ foo = param['foo']
438
+ bar = param['bar']
439
+ foobar = param['foobar']
440
+ }
441
+ }
442
+ }
443
+ assert foo.value == 40
444
+ assert foo.values == [40, 42]
445
+ assert bar.value == 2
446
+ assert foobar.value == 'foobar'
447
+ end
448
+ def test_0270
449
+ foo = nil
450
+ assert_nothing_raised{
451
+ main([], 'foo' => '42'){
452
+ env('foo'){ cast :int }
453
+ define_method('run'){
454
+ foo = param['foo']
455
+ }
456
+ }
457
+ }
458
+ assert foo.value == 42
459
+ end
460
+ #
461
+ # usage
462
+ #
463
+ def test_0280
464
+ assert_nothing_raised{
465
+ u = Main::Usage.new
466
+ }
467
+ end
468
+ def test_0290
469
+ assert_nothing_raised{
470
+ u = Main::Usage.default main
471
+ }
472
+ end
473
+ def test_0300
474
+ assert_nothing_raised{
475
+ chunk = <<-txt
476
+ a
477
+ b
478
+ c
479
+ txt
480
+ assert Main::Util.unindent(chunk) == "a\nb\nc"
481
+ chunk = <<-txt
482
+ a
483
+ b
484
+ c
485
+ txt
486
+ assert Main::Util.unindent(chunk) == "a\n b\n c"
487
+ }
488
+ end
489
+ def test_0310
490
+ assert_nothing_raised{
491
+ u = Main::Usage.new
492
+ u[:name] = 'foobar'
493
+ assert u[:name] = 'foobar'
494
+ assert u['name'] = 'foobar'
495
+ }
496
+ end
497
+ def test_0320
498
+ assert_nothing_raised{
499
+ u = Main::Usage.new
500
+ u[:name] = 'foobar'
501
+ assert u[:name] == 'foobar'
502
+ assert u['name'] == 'foobar'
503
+ u[:name2] = 'barfoo'
504
+ assert u[:name] == 'foobar'
505
+ assert u['name'] == 'foobar'
506
+ assert u[:name2] == 'barfoo'
507
+ assert u['name2'] == 'barfoo'
508
+ u.delete_at :name
509
+ assert u[:name] == nil
510
+ assert u['name'] == nil
511
+ assert u[:name2] == 'barfoo'
512
+ assert u['name2'] == 'barfoo'
513
+ u.delete_at :name2
514
+ assert u[:name] == nil
515
+ assert u['name'] == nil
516
+ assert u[:name2] == nil
517
+ assert u['name2'] == nil
518
+ }
519
+ end
520
+
521
+ end
522
+
523
+