Class: ALib::AbstractMain

Inherits:
Object show all
Includes:
ALib, Logging
Defined in:
lib/alib-0.4.0/main.rb

Direct Known Subclasses

ConfigurableMain, SimpleMain

Constant Summary collapse

EXIT_SUCCESS =
0
EXIT_PSEUDO_SUCCESS =
42
EXIT_FAILURE =
1

Constants included from Logging

Logging::DIV0, Logging::DIV1, Logging::DIV2, Logging::DIV3, Logging::EOL, Logging::SEC0, Logging::SEC1, Logging::SEC2, Logging::SEC3

Constants included from ALib

AUTOLOAD, BSearch, Configfile, Find, LIBDIR, Listfile, METACLASS, OrderedAutoHash, VERSION

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logging

append_features

Methods included from Logging::LogMethods

#__logger_mutex, #__logger_sync, #btrace, #emsg, #errmsg, #log_err, #logger=

Methods included from ALib

configurable_main, load, simple_main, version

Constructor Details

#initialize(argv = ARGV, env = ENV) ⇒ AbstractMain

Returns a new instance of AbstractMain.



288
289
290
291
292
293
294
295
296
# File 'lib/alib-0.4.0/main.rb', line 288

def initialize argv = ARGV, env = ENV
#--{{{
  @argv = Util::mcp(argv.to_a)
  @env = Util::mcp(env.to_hash)
  @program = File::expand_path $0
  @cmdline = ([@program] + @argv).join ' '
  @console = STDIN.tty?
#--}}}
end

Instance Attribute Details

#argvObject (readonly)

Returns the value of attribute argv.



277
278
279
# File 'lib/alib-0.4.0/main.rb', line 277

def argv
  @argv
end

#cmdlineObject (readonly)

Returns the value of attribute cmdline.



279
280
281
# File 'lib/alib-0.4.0/main.rb', line 279

def cmdline
  @cmdline
end

#consoleObject (readonly) Also known as: console?

Returns the value of attribute console.



280
281
282
# File 'lib/alib-0.4.0/main.rb', line 280

def console
  @console
end

#envObject (readonly)

Returns the value of attribute env.



278
279
280
# File 'lib/alib-0.4.0/main.rb', line 278

def env
  @env
end

#listoptionsObject (readonly)

Returns the value of attribute listoptions.



282
283
284
# File 'lib/alib-0.4.0/main.rb', line 282

def listoptions
  @listoptions
end

#logdevObject (readonly)

Returns the value of attribute logdev.



284
285
286
# File 'lib/alib-0.4.0/main.rb', line 284

def logdev
  @logdev
end

#loggerObject (readonly)

Returns the value of attribute logger.



275
276
277
# File 'lib/alib-0.4.0/main.rb', line 275

def logger
  @logger
end

#opObject (readonly)

Returns the value of attribute op.



283
284
285
# File 'lib/alib-0.4.0/main.rb', line 283

def op
  @op
end

#optionsObject (readonly)

Returns the value of attribute options.



281
282
283
# File 'lib/alib-0.4.0/main.rb', line 281

def options
  @options
end

#programObject (readonly)

Returns the value of attribute program.



276
277
278
# File 'lib/alib-0.4.0/main.rb', line 276

def program
  @program
end

#verbosityObject (readonly)

Returns the value of attribute verbosity.



285
286
287
# File 'lib/alib-0.4.0/main.rb', line 285

def verbosity
  @verbosity
end

Class Method Details

.argumentObject



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/alib-0.4.0/main.rb', line 185

def required_arguments(*list)
#--{{{
  @required_arguments ||= []
  list.flatten.each do |arg| 
    return(optional_argument(arg)) if Hash === arg
    unless instance_methods.include? "#{ arg }"
      module_eval "        def \#{ arg }(*__list)\n          if __list.empty?\n            @\#{ arg }\n          else\n            send('\#{ arg }=', *__list)\n          end\n        end\n        def \#{ arg }=(__arg, *__list)\n          if __list.empty?\n            @\#{ arg } = __arg\n          else\n            @\#{ arg } = ([__arg] + __list)\n          end\n        end\n        def \#{ arg }?\n          defined? @\#{ arg } and @\#{ arg }\n        end\n      code\n    end\n    @required_arguments << \"\#{ arg }\"\n  end\n  @required_arguments\n#--}}}\nend\n"

.argumentsObject



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/alib-0.4.0/main.rb', line 184

def required_arguments(*list)
#--{{{
  @required_arguments ||= []
  list.flatten.each do |arg| 
    return(optional_argument(arg)) if Hash === arg
    unless instance_methods.include? "#{ arg }"
      module_eval "        def \#{ arg }(*__list)\n          if __list.empty?\n            @\#{ arg }\n          else\n            send('\#{ arg }=', *__list)\n          end\n        end\n        def \#{ arg }=(__arg, *__list)\n          if __list.empty?\n            @\#{ arg } = __arg\n          else\n            @\#{ arg } = ([__arg] + __list)\n          end\n        end\n        def \#{ arg }?\n          defined? @\#{ arg } and @\#{ arg }\n        end\n      code\n    end\n    @required_arguments << \"\#{ arg }\"\n  end\n  @required_arguments\n#--}}}\nend\n"

.class_attributes(*names) ⇒ Object Also known as: class_attribute, c_attrs, c_attr



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/alib-0.4.0/main.rb', line 53

def class_attributes(*names)
#--{{{
  names = stringlist names
  names.each do |name|
    getter = "#{ name }"
    setter = "#{ name }="
    code = "      class << self\n        def \#{ name }(*a)\n          unless a.empty?\n            self.\#{ name }= a.shift\n          else\n            @\#{ name }\n          end\n        end\n        def \#{ name }= value\n          @\#{ name } = value\n        end\n        alias \#{ name }? \#{ name }\n      end\n    code\n    module_eval code\n  end\n#--}}}\nend\n"

.class_initializeObject



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/alib-0.4.0/main.rb', line 231

def class_initialize
#--{{{
  version '0.0.0'

  author '[email protected]'

  program File.basename($0)

  optspec [
    [ '--help', '-h', 'this message' ],
    [ '--log=path','-l', 'set log file - (default stderr)' ],
    [ '--verbosity=verbostiy', '-v', '0|fatal < 1|error < 2|warn < 3|info < 4|debug - (default info)' ],
  ]

  usage "    NAME\n      \#{ program } v\#{ version }\n\n    SYNOPSIS\n      \#{ program } [options]+ [file]+\n  usage\n\n  examples ''\n#--}}}\nend\n"

.inherited(klass) ⇒ Object



257
258
259
260
261
262
263
# File 'lib/alib-0.4.0/main.rb', line 257

def inherited klass
#--{{{
  ret = super
  klass.class_initialize
  ret
#--}}}
end

.instance_attributes(*names) ⇒ Object Also known as: instance_attribute, i_attrs, i_attr, attribute, attributes

–}}}



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/alib-0.4.0/main.rb', line 24

def instance_attributes(*names)
#--{{{
  names = stringlist names
  names.each do |name|
    getter = "#{ name }"
    setter = "#{ name }="
    code = "      def \#{ name }(*a)\n        unless a.empty?\n          self.\#{ name }= a.shift\n        else\n          @\#{ name }\n        end\n      end\n      def \#{ name }= value\n        @\#{ name } = value\n      end\n      alias \#{ name }? \#{ name }\n    code\n    module_eval code\n  end\n#--}}}\nend\n"

.optional_argumentObject

–}}}



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/alib-0.4.0/main.rb', line 229

def optional_arguments(*list)
#--{{{
  @optional_arguments ||= []
  list.flatten.each do |arg| 
    arg, default =
      case arg
        when Hash
          arg.to_a.first
        else
          [arg, nil]
      end
    @do_not_gc ||= [] 
    @do_not_gc << default unless @do_not_gc.include? default
    unless instance_methods.include? "#{ arg }"
      module_eval "        def \#{ arg }(*__list)\n          unless @\#{ arg }\n            @\#{ arg } = ObjectSpace::_id2ref \#{ default.object_id }\n          end\n          if __list.empty?\n            @\#{ arg }\n          else\n            send('\#{ arg }=', *__list)\n          end\n        end\n        def \#{ arg }=(__arg, *__list)\n          if __list.empty?\n            @\#{ arg } = __arg\n          else\n            @\#{ arg } = ([__arg] + __list)\n          end\n        end\n        def \#{ arg }?\n          defined? @\#{ arg } and @\#{ arg }\n        end\n      code\n    end\n    @optional_arguments << \"\#{ arg }\"\n  end\n  @optional_arguments\n#--}}}\nend\n"

.optional_arguments(*list) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/alib-0.4.0/main.rb', line 187

def optional_arguments(*list)
#--{{{
  @optional_arguments ||= []
  list.flatten.each do |arg| 
    arg, default =
      case arg
        when Hash
          arg.to_a.first
        else
          [arg, nil]
      end
    @do_not_gc ||= [] 
    @do_not_gc << default unless @do_not_gc.include? default
    unless instance_methods.include? "#{ arg }"
      module_eval "        def \#{ arg }(*__list)\n          unless @\#{ arg }\n            @\#{ arg } = ObjectSpace::_id2ref \#{ default.object_id }\n          end\n          if __list.empty?\n            @\#{ arg }\n          else\n            send('\#{ arg }=', *__list)\n          end\n        end\n        def \#{ arg }=(__arg, *__list)\n          if __list.empty?\n            @\#{ arg } = __arg\n          else\n            @\#{ arg } = ([__arg] + __list)\n          end\n        end\n        def \#{ arg }?\n          defined? @\#{ arg } and @\#{ arg }\n        end\n      code\n    end\n    @optional_arguments << \"\#{ arg }\"\n  end\n  @optional_arguments\n#--}}}\nend\n"

.options(*list) ⇒ Object Also known as: option



142
143
144
145
146
147
148
149
# File 'lib/alib-0.4.0/main.rb', line 142

def options(*list)
#--{{{
  @optspec ||= []
  return @optspec if list.empty?
  list = [list] unless Array === list.first
  list.each{|spec| (@optspec ||= []) << spec}
#--}}}
end

.required_argumentObject

–}}}



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/alib-0.4.0/main.rb', line 183

def required_arguments(*list)
#--{{{
  @required_arguments ||= []
  list.flatten.each do |arg| 
    return(optional_argument(arg)) if Hash === arg
    unless instance_methods.include? "#{ arg }"
      module_eval "        def \#{ arg }(*__list)\n          if __list.empty?\n            @\#{ arg }\n          else\n            send('\#{ arg }=', *__list)\n          end\n        end\n        def \#{ arg }=(__arg, *__list)\n          if __list.empty?\n            @\#{ arg } = __arg\n          else\n            @\#{ arg } = ([__arg] + __list)\n          end\n        end\n        def \#{ arg }?\n          defined? @\#{ arg } and @\#{ arg }\n        end\n      code\n    end\n    @required_arguments << \"\#{ arg }\"\n  end\n  @required_arguments\n#--}}}\nend\n"

.required_arguments(*list) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/alib-0.4.0/main.rb', line 152

def required_arguments(*list)
#--{{{
  @required_arguments ||= []
  list.flatten.each do |arg| 
    return(optional_argument(arg)) if Hash === arg
    unless instance_methods.include? "#{ arg }"
      module_eval "        def \#{ arg }(*__list)\n          if __list.empty?\n            @\#{ arg }\n          else\n            send('\#{ arg }=', *__list)\n          end\n        end\n        def \#{ arg }=(__arg, *__list)\n          if __list.empty?\n            @\#{ arg } = __arg\n          else\n            @\#{ arg } = ([__arg] + __list)\n          end\n        end\n        def \#{ arg }?\n          defined? @\#{ arg } and @\#{ arg }\n        end\n      code\n    end\n    @required_arguments << \"\#{ arg }\"\n  end\n  @required_arguments\n#--}}}\nend\n"

.run(*a, &b) ⇒ Object



265
266
267
268
269
# File 'lib/alib-0.4.0/main.rb', line 265

def run(*a, &b)
#--{{{
  new(*a, &b).run
#--}}}
end

.stringlist(*list) ⇒ Object

–{{{



19
20
21
22
23
# File 'lib/alib-0.4.0/main.rb', line 19

def stringlist(*list)
#--{{{
  list.flatten.compact.map{|item| "#{ item }".strip}
#--}}}
end

.unindent_block(buf) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/alib-0.4.0/main.rb', line 126

def unindent_block buf
#--{{{
  buf = "#{ buf }"
  lines = buf.to_a
  indent_pat = %r/^\s*[\s|]/
  indent = lines.first[ indent_pat ] rescue nil
  if indent
    lines.map do |line| 
      line[ indent.size..-1 ] || "\n"
    end.join 
  else
    buf 
  end
#--}}}
end

Instance Method Details

#die(opts = {}) ⇒ Object

–}}}



515
516
517
518
519
520
521
522
# File 'lib/alib-0.4.0/main.rb', line 515

def die opts = {} 
#--{{{
  msg = Util::getopt 'msg', opts, klass.usage
  errno = Util::getopt 'errno', opts, EXIT_FAILURE
  STDERR.puts("#{ msg }")
  exit(Integer(errno))
#--}}}
end

#init_logging(opts = @options) ⇒ Object

–}}}



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
# File 'lib/alib-0.4.0/main.rb', line 448

def init_logging opts = @options 
#--{{{
  log = Util::getopt 'log', opts
  log_age = Util::getopt 'log_age', opts
  log_size = Util::getopt 'log_size', opts
  verbosity = Util::getopt 'verbosity', opts
  log_age = Integer log_age rescue nil
  log_size = Integer log_size rescue nil
  $logger = @logger = Logger::new(log || STDERR, log_age, log_size)
#
# hack to fix Logger sync bug
#
  begin
    class << @logger; attr :logdev unless @logger.respond_to?(:logdev); end
    @logdev = @logger.logdev.dev 
    @logdev.sync = true
  rescue
    nil
  end
  level = nil
  verbosity ||= 'info'
  verbosity =
    case verbosity
      when /^\s*(?:4|d|debug)\s*$/io
        level = 'Logging::DEBUG'
        4
      when /^\s*(?:3|i|info)\s*$/io
        level = 'Logging::INFO'
        3
      when /^\s*(?:2|w|warn)\s*$/io
        level = 'Logging::WARN'
        2
      when /^\s*(?:1|e|error)\s*$/io
        level = 'Logging::ERROR'
        1
      when /^\s*(?:0|f|fatal)\s*$/io
        level = 'Logging::FATAL'
        0
      else
        abort "illegal verbosity setting <#{ verbosity }>" 
    end
  @logger.level = 2 - ((verbosity % 5) - 2) 
  @logger
#--}}}
end

#invalid_option(e) ⇒ Object

–}}}



441
442
443
444
445
446
447
# File 'lib/alib-0.4.0/main.rb', line 441

def invalid_option e
#--{{{
  # e.recover argv
  fatal{ e.to_s }
  exit EXIT_FAILURE
#--}}}
end

#klassObject

–}}}



297
# File 'lib/alib-0.4.0/main.rb', line 297

def klass; self.class; end

#logcatchObject



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/alib-0.4.0/main.rb', line 350

def logcatch 
#--{{{
  ret = nil
  @logger ||= Logger::new STDERR
  begin
    ret = yield
  rescue Exception => e
    unless SystemExit === e
      fatal{ e }
      exit EXIT_FAILURE
    if false
      if logger.debug?
        fatal{ e }
        exit EXIT_FAILURE
      else
        fatal{ emsg(e) }
        exit EXIT_FAILURE
      end
    end
    else
      exit e.status 
    end
  end
  ret
#--}}}
end

#mainObject

–}}}

Raises:

  • (NotImplementedError)


523
524
525
526
527
# File 'lib/alib-0.4.0/main.rb', line 523

def main 
#--{{{
  raise NotImplementedError, 'main'
#--}}}
end

#optional_argumentsObject

–}}}



303
304
305
306
307
# File 'lib/alib-0.4.0/main.rb', line 303

def optional_arguments
#--{{{
  klass::optional_arguments
#--}}}
end

#parse_argvObject

–}}}



493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
# File 'lib/alib-0.4.0/main.rb', line 493

def parse_argv
#--{{{
  a, b = [], []
  klass::required_arguments.each do |arg|
    value = @argv.shift
    if value 
      send "#{ arg }=", value
    else
      die 'msg' => "required_argument <#{ arg }> not given"
    end
    a << send("#{ arg }")
  end
  klass::optional_arguments.each do |arg|
    value = @argv.shift
    if value 
      send "#{ arg }=", value
    end
    b << send("#{ arg }")
  end
  [a, b, @argv]
#--}}}
end

#parse_optionsObject

–}}}



419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'lib/alib-0.4.0/main.rb', line 419

def parse_options
#--{{{
  @op = OptionParser::new
  @options = {}
  @listoptions = Hash::new{|h,k| h[k] = []} 
  klass::optspec.each do |spec|
    k = spec.first.gsub(%r/(?:--)|(?:=.*$)|(?:\s+)/o,'')
    @op.def_option(*spec) do |v| 
      @options[k] = v
      @listoptions[k] << v
    end
  end
  begin
    op.parse! @argv 
  rescue OptionParser::InvalidOption => e
    # preverve unknown options
    #e.recover(argv)
    invalid_option e
  end
  @options
#--}}}
end

#post_mainObject



349
# File 'lib/alib-0.4.0/main.rb', line 349

def post_main; end

#post_parse_argvObject

–}}}



345
# File 'lib/alib-0.4.0/main.rb', line 345

def post_parse_argv; end

#post_parse_optionsObject



332
# File 'lib/alib-0.4.0/main.rb', line 332

def post_parse_options; end

#post_runObject



347
# File 'lib/alib-0.4.0/main.rb', line 347

def post_run; end

#pre_mainObject



348
# File 'lib/alib-0.4.0/main.rb', line 348

def pre_main; end

#pre_parse_argvObject



333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/alib-0.4.0/main.rb', line 333

def pre_parse_argv
#--{{{
  if(@options.has_key?('help') or (@argv.size == 1 and @argv.first =~ %r/help/i))
    usage STDOUT
    exit EXIT_SUCCESS
  end
  if(@options.has_key?('version') or @argv.first =~ %r/version/i)
    STDOUT.puts self.class.version
    exit EXIT_SUCCESS
  end
#--}}}
end

#pre_parse_optionsObject

–}}}



331
# File 'lib/alib-0.4.0/main.rb', line 331

def pre_parse_options; end

#pre_runObject



346
# File 'lib/alib-0.4.0/main.rb', line 346

def pre_run; end

#required_argumentsObject



298
299
300
301
302
# File 'lib/alib-0.4.0/main.rb', line 298

def required_arguments
#--{{{
  klass::required_arguments
#--}}}
end

#runObject

–}}}



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/alib-0.4.0/main.rb', line 308

def run
#--{{{
  logcatch do
    begin
      pre_run
      pre_parse_options
      parse_options
      post_parse_options
      pre_parse_argv
      parse_argv
      post_parse_argv
      init_logging
      pre_main
      status = main
      post_main
      post_run
      exit(status ? EXIT_SUCCESS : EXIT_FAILURE)
    rescue Errno::EPIPE
      STDOUT.tty? ?  raise : exit(EXIT_FAILURE)
    end
  end
#--}}}
end

#usage(port = STDERR) ⇒ Object

–}}}



376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
# File 'lib/alib-0.4.0/main.rb', line 376

def usage port = STDERR
#--{{{
  port << klass::usage << "\n" if(klass::usage and not klass::usage.empty?)
  port << klass::examples << "\n" if(klass::examples and not klass::examples.empty?)

  if klass::optspec 
    port << 'OPTIONS' << "\n"

    klass::optspec.each do |os| 
      a, b, c = os
      long, short, desc = nil
      [a,b,c].each do |word|
        next unless word
        word.strip!
        case word
          when %r/^--[^-]/o
            long = word
          when %r/^-[^-]/o
            short = word
          else
            desc = word
        end
      end

      spec = ((long and short) ? [long, short] : [long])

      if spec
        port << Util::columnize(spec.join(', '), :width => 80, :indent => 2)
        port << "\n"
      end

      if desc
        port << Util::columnize(desc, :width => 80, :indent => 8)
        port << "\n"
      end
    end

    port << "\n"
  end

  port
#--}}}
end