main 2.9.3 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: main
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.3
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ara T. Howard
@@ -9,11 +9,30 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-01 00:00:00 -06:00
12
+ date: 2009-10-11 00:00:00 -06:00
13
13
  default_executable:
14
- dependencies: []
15
-
16
- description:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: fattr
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.3
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: arrayfields
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 4.5.0
34
+ version:
35
+ description: a class factory and dsl for generating command line programs real quick
17
36
  email: ara.t.howard@gmail.com
18
37
  executables: []
19
38
 
@@ -22,13 +41,17 @@ extensions: []
22
41
  extra_rdoc_files: []
23
42
 
24
43
  files:
25
- - lib/main/base.rb
44
+ - a.rb
26
45
  - lib/main/cast.rb
46
+ - lib/main/dsl.rb
27
47
  - lib/main/factories.rb
28
48
  - lib/main/getoptlong.rb
29
49
  - lib/main/logger.rb
30
50
  - lib/main/mode.rb
31
51
  - lib/main/parameter.rb
52
+ - lib/main/program/class_methods.rb
53
+ - lib/main/program/instance_methods.rb
54
+ - lib/main/program.rb
32
55
  - lib/main/softspoken.rb
33
56
  - lib/main/stdext.rb
34
57
  - lib/main/usage.rb
@@ -1,517 +0,0 @@
1
- module Main
2
- class Base
3
- class << self
4
- def wrap_run!
5
- const_set :RUN, instance_method(:run)
6
-
7
- class_eval do
8
- def run *a, &b
9
- argv.push "--#{ argv.shift }" if argv.first == 'help'
10
- return mode_run! if mode_given?
11
-
12
- status =
13
- catch :exit do
14
- begin
15
-
16
- parse_parameters
17
-
18
- if params['help'] and params['help'].given?
19
- print usage.to_s
20
- exit
21
- end
22
-
23
- pre_run
24
- before_run
25
- self.class.const_get(:RUN).bind(self).call(*a, &b)
26
- after_run
27
- post_run
28
-
29
- finalize
30
- rescue Exception => e
31
- handle_exception e
32
- end
33
- nil
34
- end
35
-
36
- handle_throw status
37
- end
38
- end
39
- end
40
-
41
- def method_added m
42
- return if @in_method_added
43
- super if defined? super
44
- @in_method_added = true
45
- begin
46
- wrap_run! if m.to_s == 'run'
47
- ensure
48
- @in_method_added = false
49
- end
50
- end
51
-
52
- def self.inheritable_fattr name, &block
53
- block ||= lambda{}
54
- fattr( name ){
55
- catch :value do
56
- if parent?
57
- value = parent.send name
58
- value =
59
- begin
60
- Util.mcp value
61
- rescue
62
- value.clone rescue value.dup
63
- end
64
- throw :value, value
65
- end
66
- instance_eval &block
67
- end
68
- }
69
- end
70
-
71
- # fattrs
72
- fattr( 'name' ){ File.basename $0 }
73
- fattr( 'synopsis' ){ Main::Usage.default_synopsis(self) }
74
- fattr( 'description' )
75
- fattr( 'usage' ){ Main::Usage.default_usage self }
76
- fattr( 'modes' ){ Main::Mode.list }
77
- fattr( 'mode_definitions' ){ Array.new }
78
- fattr( 'mode_name' ){ 'main' }
79
- fattr( 'parent' ){ nil }
80
- fattr( 'children' ){ Set.new }
81
-
82
- fattr( 'program' ){ File.basename $0 }
83
- fattr( 'author' )
84
- fattr( 'version' )
85
- fattr( 'stdin' ){ $stdin }
86
- fattr( 'stdout' ){ $stdout }
87
- fattr( 'stderr' ){ $stderr }
88
- fattr( 'logger' ){ stderr }
89
- fattr( 'logger_level' ){ Logger::INFO }
90
- fattr( 'exit_status' ){ Main::EXIT_SUCCESS }
91
- fattr( 'exit_success' ){ Main::EXIT_SUCCESS }
92
- fattr( 'exit_failure' ){ Main::EXIT_FAILURE }
93
- fattr( 'exit_warn' ){ Main::EXIT_WARN }
94
- inheritable_fattr( 'parameters' ){ Main::Parameter::List[] }
95
- inheritable_fattr( 'can_has_hash' ){ Hash.new }
96
- inheritable_fattr( 'mixin_table' ){ Hash.new }
97
-
98
- # override a few fattrs
99
- def mode_name=(value)
100
- @mode_name = Mode.new value
101
- end
102
-
103
- def usage *argv, &block
104
- usage! unless defined? @usage
105
- return @usage if argv.empty? and block.nil?
106
- key, value, *ignored = argv
107
- value = block.call if block
108
- @usage[key.to_s] = value.to_s
109
- end
110
-
111
- def create parent = Base, *a, &b
112
- Class.new parent do |child|
113
- child.parent = parent unless parent == Base
114
- parent.children.add child
115
- child.context do
116
- child.class_eval &b if b
117
- child.default_options!
118
- #child.wrap_run! unless child.const_defined?(:RUN)
119
- mode_definitions.each do |name, block|
120
- klass =
121
- create context do
122
- mode_name name.to_s
123
- module_eval &block if block
124
- end
125
- modes.add klass
126
- end
127
- end
128
- end
129
- end
130
-
131
- def context &block
132
- @@context ||= []
133
- unless block
134
- @@context.last
135
- else
136
- begin
137
- @@context.push self
138
- block.call @@context.last
139
- ensure
140
- @@context.pop
141
- end
142
- end
143
- end
144
-
145
- module ::Main
146
- singleton_class{
147
- def current
148
- ::Main::Base.context
149
- end
150
- }
151
- end
152
-
153
- def fully_qualified_mode
154
- list = []
155
- ancestors.each do |ancestor|
156
- break unless ancestor < Base
157
- list << ancestor.mode_name
158
- end
159
- list.reverse[1..-1]
160
- end
161
-
162
- def run(&b) define_method(:run, &b) end
163
-
164
- def new(*a, &b)
165
- allocate.instance_eval do
166
- pre_initialize
167
- before_initialize
168
- main_initialize *a, &b
169
- initialize
170
- after_initialize
171
- post_initialize
172
- self
173
- end
174
- end
175
- end
176
-
177
- module DSL
178
- def parameter *a, &b
179
- (parameters << Parameter.create(:parameter, *a, &b)).last
180
- end
181
-
182
- def option *a, &b
183
- (parameters << Parameter.create(:option, *a, &b)).last
184
- end
185
- alias_method 'opt', 'option'
186
- alias_method 'switch', 'option'
187
-
188
- def default_options!
189
- option 'help', 'h' unless parameters.has_option?('help', 'h')
190
- end
191
-
192
- def argument *a, &b
193
- (parameters << Parameter.create(:argument, *a, &b)).last
194
- end
195
- alias_method 'arg', 'argument'
196
-
197
- def keyword *a, &b
198
- (parameters << Parameter.create(:keyword, *a, &b)).last
199
- end
200
- alias_method 'kw', 'keyword'
201
-
202
- def environment *a, &b
203
- (parameters << Parameter.create(:environment, *a, &b)).last
204
- end
205
- alias_method 'env', 'environment'
206
-
207
- =begin
208
- def mode name, &b
209
- klass =
210
- create context do
211
- mode_name name.to_s
212
- module_eval &b if b
213
- end
214
- modes.add klass
215
- end
216
- =end
217
-
218
- def mode name, &b
219
- mode_definitions << [name, b]
220
- end
221
-
222
- def can_has ptype, *a, &b
223
- key = a.map{|s| s.to_s}.sort_by{|s| -s.size }.first
224
- can_has_hash.update key => [ptype, a, b]
225
- key
226
- end
227
-
228
- def has key, *keys
229
- keys = [key, *keys].flatten.compact.map{|k| k.to_s}
230
- keys.map do |key|
231
- ptype, a, b = can_has_hash[key]
232
- abort "yo - can *not* has #{ key.inspect }!?" unless(ptype and a and b)
233
- send ptype, *a, &b
234
- key
235
- end
236
- end
237
-
238
- def mixin name, *names, &block
239
- names = [name, *names].flatten.compact.map{|name| name.to_s}
240
- if block
241
- names.each do |name|
242
- mixin_table[name] = block
243
- end
244
- else
245
- names.each do |name|
246
- module_eval &mixin_table[name]
247
- end
248
- end
249
- end
250
-
251
- ## TODO - for some reason these hork the usage!
252
-
253
- %w[ examples samples api ].each do |chunkname|
254
- module_eval <<-code
255
- def #{ chunkname } *a, &b
256
- txt = b ? b.call : a.join("\\n")
257
- usage['#{ chunkname }'] = txt
258
- end
259
- code
260
- end
261
- alias_method 'example', 'examples'
262
- alias_method 'sample', 'samples'
263
- end
264
- extend DSL
265
-
266
- fattr 'argv'
267
- fattr 'env'
268
- fattr 'params'
269
- fattr 'logger'
270
- fattr 'stdin'
271
- fattr 'stdout'
272
- fattr 'stderr'
273
-
274
- %w(
275
- program name synopsis description author version
276
- exit_status exit_success exit_failure exit_warn
277
- logger_level
278
- usage
279
- ).each{|a| fattr(a){ self.class.send a}}
280
-
281
- %w( parameters param ).each do |dst|
282
- alias_method "#{ dst }", "params"
283
- alias_method "#{ dst }=", "params="
284
- alias_method "#{ dst }?", "params?"
285
- end
286
-
287
- %w( debug info warn fatal error ).each do |m|
288
- module_eval <<-code
289
- def #{ m } *a, &b
290
- logger.#{ m } *a, &b
291
- end
292
- code
293
- end
294
-
295
- =begin
296
- =end
297
- def pre_initialize() :hook end
298
- def before_initialize() :hook end
299
- def main_initialize argv = ARGV, env = ENV, opts = {}
300
- @argv, @env, @opts = argv, env, opts
301
- setup_finalizers
302
- setup_io_restoration
303
- setup_io_redirection
304
- setup_logging
305
- end
306
- def initialize() :hook end
307
- def after_initialize() :hook end
308
- def post_initialize() :hook end
309
-
310
- def setup_finalizers
311
- @finalizers = finalizers = []
312
- ObjectSpace.define_finalizer(self) do
313
- while((f = finalizers.pop)); f.call; end
314
- end
315
- end
316
-
317
- def finalize
318
- while((f = @finalizers.pop)); f.call; end
319
- end
320
-
321
- def setup_io_redirection
322
- self.stdin = @opts['stdin'] || @opts[:stdin] || self.class.stdin
323
- self.stdout = @opts['stdout'] || @opts[:stdout] || self.class.stdout
324
- self.stderr = @opts['stderr'] || @opts[:stderr] || self.class.stderr
325
- end
326
-
327
- def setup_logging
328
- log = self.class.logger || stderr
329
- self.logger = log
330
- end
331
- def logger= log
332
- unless(defined?(@logger) and @logger == log)
333
- case log
334
- when ::Logger, Logger
335
- @logger = log
336
- when IO, StringIO
337
- @logger = Logger.new log
338
- @logger.level = logger_level
339
- else
340
- @logger = Logger.new *log
341
- @logger.level = logger_level
342
- end
343
- end
344
- @logger
345
- end
346
-
347
- def setup_io_restoration
348
- [STDIN, STDOUT, STDERR].each do |io|
349
- dup = io.dup and @finalizers.push lambda{ io.reopen dup rescue nil }
350
- end
351
- end
352
-
353
- def stdin= io
354
- unless(defined?(@stdin) and (@stdin == io))
355
- @stdin =
356
- if io.respond_to? 'read'
357
- io
358
- else
359
- fd = open io.to_s, 'r+'
360
- @finalizers.push lambda{ fd.close }
361
- fd
362
- end
363
- begin
364
- STDIN.reopen @stdin
365
- rescue
366
- $stdin = @stdin
367
- ::Object.const_set 'STDIN', @stdin
368
- end
369
- end
370
- end
371
-
372
- def stdout= io
373
- unless(defined?(@stdout) and (@stdout == io))
374
- @stdout =
375
- if io.respond_to? 'write'
376
- io
377
- else
378
- fd = open io.to_s, 'w+'
379
- @finalizers.push lambda{ fd.close }
380
- fd
381
- end
382
- STDOUT.reopen @stdout rescue($stdout = @stdout)
383
- end
384
- end
385
-
386
- def stderr= io
387
- unless(defined?(@stderr) and (@stderr == io))
388
- @stderr =
389
- if io.respond_to? 'write'
390
- io
391
- else
392
- fd = open io.to_s, 'w+'
393
- @finalizers.push lambda{ fd.close }
394
- fd
395
- end
396
- STDERR.reopen @stderr rescue($stderr = @stderr)
397
- end
398
- end
399
-
400
- def pre_parse_parameters() :hook end
401
- def before_parse_parameters() :hook end
402
- def parse_parameters
403
- pre_parse_parameters
404
- before_parse_parameters
405
-
406
- self.class.parameters.parse self
407
- @params = Parameter::Table.new
408
- self.class.parameters.each{|p| @params[p.name.to_s] = p}
409
-
410
- after_parse_parameters
411
- post_parse_parameters
412
- end
413
- def after_parse_parameters() :hook end
414
- def post_parse_parameters() :hook end
415
-
416
- def pre_run() :hook end
417
- def before_run() :hook end
418
- def run
419
- raise NotImplementedError, 'run not defined'
420
- end
421
- def after_run() :hook end
422
- def post_run() :hook end
423
-
424
- def mode_given?
425
- begin
426
- modes.size > 0 and
427
- argv.size > 0 and
428
- modes.find_by_mode(argv.first)
429
- rescue Mode::Ambiguous
430
- true
431
- end
432
- end
433
- def mode_run!
434
- mode = modes.find_by_mode argv.shift
435
- klass = modes[mode] or abort "bad mode <#{ mode }>"
436
- main = klass.new @argv, @env, @opts
437
- main.mode = mode
438
- main.run
439
- end
440
- def modes
441
- self.class.modes
442
- end
443
- fattr 'mode'
444
-
445
- def help! status = 0
446
- print usage.to_s
447
- exit(status)
448
- end
449
-
450
- def abort message = 'exit'
451
- raise SystemExit.new(message)
452
- end
453
-
454
- def handle_exception e
455
- if e.respond_to?(:error_handler_before)
456
- fcall(e, :error_handler_before, self)
457
- end
458
-
459
- if e.respond_to?(:error_handler_instead)
460
- fcall(e, :error_handler_instead, self)
461
- else
462
- if e.respond_to? :status
463
- exit_status(( e.status ))
464
- end
465
-
466
- if Softspoken === e or SystemExit === e
467
- quiet = ((SystemExit === e and e.message.respond_to?('abort')) or # see main/stdext.rb
468
- (SystemExit === e and e.message == 'exit'))
469
- stderr.puts e.message unless quiet
470
- else
471
- fatal{ e }
472
- end
473
- end
474
-
475
- if e.respond_to?(:error_handler_after)
476
- fcall(e, :error_handler_after, self)
477
- end
478
-
479
- exit_status(( exit_failure )) if exit_status == exit_success
480
- exit_status(( Integer(exit_status) rescue(exit_status ? 0 : 1) ))
481
- exit exit_status
482
- end
483
-
484
- def fcall obj, m, *argv, &block
485
- m = obj.method m
486
- arity = m.arity
487
- if arity >= 0
488
- argv = argv[0, arity]
489
- else
490
- arity = arity.abs - 1
491
- argv = argv[0, arity] + argv[arity .. -1]
492
- end
493
- m.call *argv, &block
494
- end
495
-
496
- def handle_throw status
497
- exit(( Integer(status) rescue 0 ))
498
- end
499
-
500
- %w[ before instead after ].each do |which|
501
- module_eval <<-code
502
- def error_handler_#{ which } *argv, &block
503
- block.call *argv
504
- end
505
- code
506
- end
507
-
508
- def instance_eval_block *argv, &block
509
- sc =
510
- class << self
511
- self
512
- end
513
- sc.module_eval{ define_method '__instance_eval_block', &block }
514
- fcall self, '__instance_eval_block', *argv, &block
515
- end
516
- end
517
- end