main 2.9.3 → 3.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.
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