alib 0.3.1 → 0.4.0
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.
- data/a.rb +1 -0
- data/alib-0.4.0.gem +0 -0
- data/b.rb +1 -0
- data/build +0 -0
- data/gemspec.rb +23 -0
- data/install +143 -0
- data/install.rb +143 -0
- data/lib/alib-0.4.0.rb +104 -0
- data/lib/alib-0.4.0/autohash.rb +11 -0
- data/lib/alib-0.4.0/bsearch.rb +255 -0
- data/lib/alib-0.4.0/configfile.rb +113 -0
- data/lib/alib-0.4.0/find2.rb +294 -0
- data/lib/alib-0.4.0/listfile.rb +42 -0
- data/lib/alib-0.4.0/logging.rb +152 -0
- data/lib/alib-0.4.0/main.rb +594 -0
- data/lib/alib-0.4.0/open4.rb +175 -0
- data/lib/alib-0.4.0/orderedautohash.rb +23 -0
- data/lib/alib-0.4.0/orderedhash.rb +243 -0
- data/lib/alib-0.4.0/util.rb +1167 -0
- data/lib/alib.rb +63 -3831
- metadata +23 -3
- data/lib/alib-0.3.1.rb +0 -3872
@@ -0,0 +1,152 @@
|
|
1
|
+
#
|
2
|
+
# the logging module extends classes (both at instance and class level) with
|
3
|
+
# many methods useful for logging. it relies on the builtin Logger class
|
4
|
+
#
|
5
|
+
module ALib::Logging
|
6
|
+
#--{{{
|
7
|
+
#
|
8
|
+
# a module that adds an accessor to Logging objects in ored to fix a bug where
|
9
|
+
# not all logging devices are put into sync mode, resulting in improper log
|
10
|
+
# rolling. this is a hack.
|
11
|
+
#
|
12
|
+
module LoggerExt
|
13
|
+
#--{{{
|
14
|
+
attr :logdev
|
15
|
+
def << *args
|
16
|
+
args.flatten.each{|a| super a}
|
17
|
+
self
|
18
|
+
end
|
19
|
+
#--}}}
|
20
|
+
end # module LoggerExt
|
21
|
+
#
|
22
|
+
# implementations of the methods shared by both classes and objects of classes
|
23
|
+
# which include Logging
|
24
|
+
#
|
25
|
+
module LogMethods
|
26
|
+
#--{{{
|
27
|
+
def __logger_mutex
|
28
|
+
#--{{{
|
29
|
+
unless defined?(@__logger_mutex) and @__logger_mutex
|
30
|
+
begin
|
31
|
+
Thread.critical = true
|
32
|
+
@__logger_mutex = Sync::new unless defined?(@__logger_mutex) and @__logger_mutex
|
33
|
+
ensure
|
34
|
+
Thread.critical = false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
@__logger_mutex
|
38
|
+
#--}}}
|
39
|
+
end
|
40
|
+
def __logger_sync
|
41
|
+
#--{{{
|
42
|
+
__logger_mutex.synchronize{ yield }
|
43
|
+
#--}}}
|
44
|
+
end
|
45
|
+
def logger
|
46
|
+
#--{{{
|
47
|
+
return @logger if defined?(@logger)
|
48
|
+
__logger_sync do
|
49
|
+
unless defined?(@logger)
|
50
|
+
klass = Class === self ? self : self::class
|
51
|
+
self.logger = klass::default_logger
|
52
|
+
end
|
53
|
+
end
|
54
|
+
@logger
|
55
|
+
#--}}}
|
56
|
+
end
|
57
|
+
def logger= log
|
58
|
+
#--{{{
|
59
|
+
__logger_sync do
|
60
|
+
@logger = log
|
61
|
+
@logger.extend LoggerExt
|
62
|
+
@logger.logdev.dev.sync = true rescue nil
|
63
|
+
@logger
|
64
|
+
end
|
65
|
+
#--}}}
|
66
|
+
end
|
67
|
+
%w( debug info warn error fatal ).each do |meth|
|
68
|
+
module_eval <<-code
|
69
|
+
def #{ meth }(*a, &b)
|
70
|
+
__logger_sync{ logger.#{ meth }(*a, &b) }
|
71
|
+
end
|
72
|
+
code
|
73
|
+
end
|
74
|
+
def log_err e
|
75
|
+
#--{{{
|
76
|
+
if logger.debug?
|
77
|
+
error{ errmsg e }
|
78
|
+
else
|
79
|
+
error{ emsg e }
|
80
|
+
end
|
81
|
+
#--}}}
|
82
|
+
end
|
83
|
+
def emsg e
|
84
|
+
#--{{{
|
85
|
+
"#{ e.message } - (#{ e.class })"
|
86
|
+
#--}}}
|
87
|
+
end
|
88
|
+
def btrace e
|
89
|
+
#--{{{
|
90
|
+
e.backtrace.join("\n")
|
91
|
+
#--}}}
|
92
|
+
end
|
93
|
+
def errmsg e
|
94
|
+
#--{{{
|
95
|
+
emsg(e) << "\n" << btrace(e)
|
96
|
+
#--}}}
|
97
|
+
end
|
98
|
+
#--}}}
|
99
|
+
end # module LogMethods
|
100
|
+
|
101
|
+
module LogClassMethods
|
102
|
+
#--{{{
|
103
|
+
def default_logger
|
104
|
+
#--{{{
|
105
|
+
return @default_logger if defined?(@default_logger)
|
106
|
+
__logger_sync do
|
107
|
+
unless defined?(@default_logger)
|
108
|
+
self.default_logger = Logger.new STDERR
|
109
|
+
# @default_logger.warn{ "<#{ self }> using default logger"}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
@default_logger
|
113
|
+
#--}}}
|
114
|
+
end
|
115
|
+
def default_logger= log
|
116
|
+
#--{{{
|
117
|
+
__logger_sync do
|
118
|
+
@default_logger = (Logger === log ? log : Logger::new(log))
|
119
|
+
@default_logger.extend LoggerExt
|
120
|
+
@default_logger.logdev.dev.sync = true rescue nil
|
121
|
+
@default_logger
|
122
|
+
end
|
123
|
+
#--}}}
|
124
|
+
end
|
125
|
+
#--}}}
|
126
|
+
end
|
127
|
+
|
128
|
+
EOL = "\n"
|
129
|
+
DIV0 = ("." * 79) << EOL
|
130
|
+
DIV1 = ("-" * 79) << EOL
|
131
|
+
DIV2 = ("=" * 79) << EOL
|
132
|
+
DIV3 = ("#" * 79) << EOL
|
133
|
+
SEC0 = ("." * 16) << EOL
|
134
|
+
SEC1 = ("-" * 16) << EOL
|
135
|
+
SEC2 = ("=" * 16) << EOL
|
136
|
+
SEC3 = ("#" * 16) << EOL
|
137
|
+
|
138
|
+
class << self
|
139
|
+
#--{{{
|
140
|
+
def append_features c
|
141
|
+
#--{{{
|
142
|
+
ret = super
|
143
|
+
c.extend LogMethods
|
144
|
+
c.extend LogClassMethods
|
145
|
+
ret
|
146
|
+
#--}}}
|
147
|
+
end
|
148
|
+
#--}}}
|
149
|
+
end
|
150
|
+
include LogMethods
|
151
|
+
#--}}}
|
152
|
+
end # module Logging
|
@@ -0,0 +1,594 @@
|
|
1
|
+
#
|
2
|
+
# template main building block classes
|
3
|
+
#
|
4
|
+
|
5
|
+
|
6
|
+
module ALib
|
7
|
+
|
8
|
+
class AbstractMain
|
9
|
+
#--{{{
|
10
|
+
include ALib
|
11
|
+
include ALib::Logging
|
12
|
+
|
13
|
+
EXIT_SUCCESS = 0
|
14
|
+
EXIT_PSEUDO_SUCCESS = 42
|
15
|
+
EXIT_FAILURE = 1
|
16
|
+
|
17
|
+
class << self
|
18
|
+
#--{{{
|
19
|
+
def stringlist(*list)
|
20
|
+
#--{{{
|
21
|
+
list.flatten.compact.map{|item| "#{ item }".strip}
|
22
|
+
#--}}}
|
23
|
+
end
|
24
|
+
def instance_attributes(*names)
|
25
|
+
#--{{{
|
26
|
+
names = stringlist names
|
27
|
+
names.each do |name|
|
28
|
+
getter = "#{ name }"
|
29
|
+
setter = "#{ name }="
|
30
|
+
code = <<-code
|
31
|
+
def #{ name }(*a)
|
32
|
+
unless a.empty?
|
33
|
+
self.#{ name }= a.shift
|
34
|
+
else
|
35
|
+
@#{ name }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
def #{ name }= value
|
39
|
+
@#{ name } = value
|
40
|
+
end
|
41
|
+
alias #{ name }? #{ name }
|
42
|
+
code
|
43
|
+
module_eval code
|
44
|
+
end
|
45
|
+
#--}}}
|
46
|
+
end
|
47
|
+
alias instance_attribute instance_attributes
|
48
|
+
alias i_attrs instance_attributes
|
49
|
+
alias i_attr instance_attributes
|
50
|
+
alias attribute instance_attributes
|
51
|
+
alias attributes instance_attributes
|
52
|
+
|
53
|
+
def class_attributes(*names)
|
54
|
+
#--{{{
|
55
|
+
names = stringlist names
|
56
|
+
names.each do |name|
|
57
|
+
getter = "#{ name }"
|
58
|
+
setter = "#{ name }="
|
59
|
+
code = <<-code
|
60
|
+
class << self
|
61
|
+
def #{ name }(*a)
|
62
|
+
unless a.empty?
|
63
|
+
self.#{ name }= a.shift
|
64
|
+
else
|
65
|
+
@#{ name }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
def #{ name }= value
|
69
|
+
@#{ name } = value
|
70
|
+
end
|
71
|
+
alias #{ name }? #{ name }
|
72
|
+
end
|
73
|
+
code
|
74
|
+
module_eval code
|
75
|
+
end
|
76
|
+
#--}}}
|
77
|
+
end
|
78
|
+
alias class_attribute class_attributes
|
79
|
+
alias c_attrs class_attributes
|
80
|
+
alias c_attr class_attributes
|
81
|
+
|
82
|
+
%w( version author program optspec ).each do |meth|
|
83
|
+
#--{{{
|
84
|
+
module_eval <<-code
|
85
|
+
def #{ meth }(*a)
|
86
|
+
unless a.empty?
|
87
|
+
self.#{ meth }= a.shift
|
88
|
+
else
|
89
|
+
@#{ meth }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
def #{ meth }= value
|
93
|
+
@#{ meth } = value
|
94
|
+
end
|
95
|
+
def #{ meth }?
|
96
|
+
defined? @#{ meth } and @#{ meth }
|
97
|
+
end
|
98
|
+
code
|
99
|
+
#--}}}
|
100
|
+
end
|
101
|
+
alias prognam program
|
102
|
+
alias prognam= program=
|
103
|
+
alias prognam? program?
|
104
|
+
|
105
|
+
%w( usage examples ).each do |meth|
|
106
|
+
#--{{{
|
107
|
+
module_eval <<-code
|
108
|
+
def #{ meth }(*a)
|
109
|
+
unless a.empty?
|
110
|
+
self.#{ meth }= a.shift
|
111
|
+
else
|
112
|
+
@#{ meth }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
def #{ meth }= msg
|
116
|
+
@#{ meth } = unindent_block msg.to_s
|
117
|
+
end
|
118
|
+
def #{ meth }?
|
119
|
+
defined? @#{ meth } and @#{ meth }
|
120
|
+
end
|
121
|
+
code
|
122
|
+
#--}}}
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
def unindent_block buf
|
127
|
+
#--{{{
|
128
|
+
buf = "#{ buf }"
|
129
|
+
lines = buf.to_a
|
130
|
+
indent_pat = %r/^\s*[\s|]/
|
131
|
+
indent = lines.first[ indent_pat ] rescue nil
|
132
|
+
if indent
|
133
|
+
lines.map do |line|
|
134
|
+
line[ indent.size..-1 ] || "\n"
|
135
|
+
end.join
|
136
|
+
else
|
137
|
+
buf
|
138
|
+
end
|
139
|
+
#--}}}
|
140
|
+
end
|
141
|
+
|
142
|
+
def options(*list)
|
143
|
+
#--{{{
|
144
|
+
@optspec ||= []
|
145
|
+
return @optspec if list.empty?
|
146
|
+
list = [list] unless Array === list.first
|
147
|
+
list.each{|spec| (@optspec ||= []) << spec}
|
148
|
+
#--}}}
|
149
|
+
end
|
150
|
+
alias option options
|
151
|
+
|
152
|
+
def required_arguments(*list)
|
153
|
+
#--{{{
|
154
|
+
@required_arguments ||= []
|
155
|
+
list.flatten.each do |arg|
|
156
|
+
return(optional_argument(arg)) if Hash === arg
|
157
|
+
unless instance_methods.include? "#{ arg }"
|
158
|
+
module_eval <<-code
|
159
|
+
def #{ arg }(*__list)
|
160
|
+
if __list.empty?
|
161
|
+
@#{ arg }
|
162
|
+
else
|
163
|
+
send('#{ arg }=', *__list)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
def #{ arg }=(__arg, *__list)
|
167
|
+
if __list.empty?
|
168
|
+
@#{ arg } = __arg
|
169
|
+
else
|
170
|
+
@#{ arg } = ([__arg] + __list)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
def #{ arg }?
|
174
|
+
defined? @#{ arg } and @#{ arg }
|
175
|
+
end
|
176
|
+
code
|
177
|
+
end
|
178
|
+
@required_arguments << "#{ arg }"
|
179
|
+
end
|
180
|
+
@required_arguments
|
181
|
+
#--}}}
|
182
|
+
end
|
183
|
+
alias required_argument required_arguments
|
184
|
+
alias arguments required_arguments
|
185
|
+
alias argument required_arguments
|
186
|
+
|
187
|
+
def optional_arguments(*list)
|
188
|
+
#--{{{
|
189
|
+
@optional_arguments ||= []
|
190
|
+
list.flatten.each do |arg|
|
191
|
+
arg, default =
|
192
|
+
case arg
|
193
|
+
when Hash
|
194
|
+
arg.to_a.first
|
195
|
+
else
|
196
|
+
[arg, nil]
|
197
|
+
end
|
198
|
+
@do_not_gc ||= []
|
199
|
+
@do_not_gc << default unless @do_not_gc.include? default
|
200
|
+
unless instance_methods.include? "#{ arg }"
|
201
|
+
module_eval <<-code
|
202
|
+
def #{ arg }(*__list)
|
203
|
+
unless @#{ arg }
|
204
|
+
@#{ arg } = ObjectSpace::_id2ref #{ default.object_id }
|
205
|
+
end
|
206
|
+
if __list.empty?
|
207
|
+
@#{ arg }
|
208
|
+
else
|
209
|
+
send('#{ arg }=', *__list)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
def #{ arg }=(__arg, *__list)
|
213
|
+
if __list.empty?
|
214
|
+
@#{ arg } = __arg
|
215
|
+
else
|
216
|
+
@#{ arg } = ([__arg] + __list)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
def #{ arg }?
|
220
|
+
defined? @#{ arg } and @#{ arg }
|
221
|
+
end
|
222
|
+
code
|
223
|
+
end
|
224
|
+
@optional_arguments << "#{ arg }"
|
225
|
+
end
|
226
|
+
@optional_arguments
|
227
|
+
#--}}}
|
228
|
+
end
|
229
|
+
alias optional_argument optional_arguments
|
230
|
+
|
231
|
+
def class_initialize
|
232
|
+
#--{{{
|
233
|
+
version '0.0.0'
|
234
|
+
|
235
|
+
author 'ara.t.howard@noaa.gov'
|
236
|
+
|
237
|
+
program File.basename($0)
|
238
|
+
|
239
|
+
optspec [
|
240
|
+
[ '--help', '-h', 'this message' ],
|
241
|
+
[ '--log=path','-l', 'set log file - (default stderr)' ],
|
242
|
+
[ '--verbosity=verbostiy', '-v', '0|fatal < 1|error < 2|warn < 3|info < 4|debug - (default info)' ],
|
243
|
+
]
|
244
|
+
|
245
|
+
usage <<-usage
|
246
|
+
NAME
|
247
|
+
#{ program } v#{ version }
|
248
|
+
|
249
|
+
SYNOPSIS
|
250
|
+
#{ program } [options]+ [file]+
|
251
|
+
usage
|
252
|
+
|
253
|
+
examples ''
|
254
|
+
#--}}}
|
255
|
+
end
|
256
|
+
|
257
|
+
def inherited klass
|
258
|
+
#--{{{
|
259
|
+
ret = super
|
260
|
+
klass.class_initialize
|
261
|
+
ret
|
262
|
+
#--}}}
|
263
|
+
end
|
264
|
+
|
265
|
+
def run(*a, &b)
|
266
|
+
#--{{{
|
267
|
+
new(*a, &b).run
|
268
|
+
#--}}}
|
269
|
+
end
|
270
|
+
#--}}}
|
271
|
+
end
|
272
|
+
|
273
|
+
class_initialize
|
274
|
+
|
275
|
+
attr :logger
|
276
|
+
attr :program
|
277
|
+
attr :argv
|
278
|
+
attr :env
|
279
|
+
attr :cmdline
|
280
|
+
attr :console
|
281
|
+
attr :options
|
282
|
+
attr :listoptions
|
283
|
+
attr :op
|
284
|
+
attr :logdev
|
285
|
+
attr :verbosity
|
286
|
+
alias console? console
|
287
|
+
|
288
|
+
def initialize argv = ARGV, env = ENV
|
289
|
+
#--{{{
|
290
|
+
@argv = Util::mcp(argv.to_a)
|
291
|
+
@env = Util::mcp(env.to_hash)
|
292
|
+
@program = File::expand_path $0
|
293
|
+
@cmdline = ([@program] + @argv).join ' '
|
294
|
+
@console = STDIN.tty?
|
295
|
+
#--}}}
|
296
|
+
end
|
297
|
+
def klass; self.class; end
|
298
|
+
def required_arguments
|
299
|
+
#--{{{
|
300
|
+
klass::required_arguments
|
301
|
+
#--}}}
|
302
|
+
end
|
303
|
+
def optional_arguments
|
304
|
+
#--{{{
|
305
|
+
klass::optional_arguments
|
306
|
+
#--}}}
|
307
|
+
end
|
308
|
+
def run
|
309
|
+
#--{{{
|
310
|
+
logcatch do
|
311
|
+
begin
|
312
|
+
pre_run
|
313
|
+
pre_parse_options
|
314
|
+
parse_options
|
315
|
+
post_parse_options
|
316
|
+
pre_parse_argv
|
317
|
+
parse_argv
|
318
|
+
post_parse_argv
|
319
|
+
init_logging
|
320
|
+
pre_main
|
321
|
+
status = main
|
322
|
+
post_main
|
323
|
+
post_run
|
324
|
+
exit(status ? EXIT_SUCCESS : EXIT_FAILURE)
|
325
|
+
rescue Errno::EPIPE
|
326
|
+
STDOUT.tty? ? raise : exit(EXIT_FAILURE)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
#--}}}
|
330
|
+
end
|
331
|
+
def pre_parse_options; end
|
332
|
+
def post_parse_options; end
|
333
|
+
def pre_parse_argv
|
334
|
+
#--{{{
|
335
|
+
if(@options.has_key?('help') or (@argv.size == 1 and @argv.first =~ %r/help/i))
|
336
|
+
usage STDOUT
|
337
|
+
exit EXIT_SUCCESS
|
338
|
+
end
|
339
|
+
if(@options.has_key?('version') or @argv.first =~ %r/version/i)
|
340
|
+
STDOUT.puts self.class.version
|
341
|
+
exit EXIT_SUCCESS
|
342
|
+
end
|
343
|
+
#--}}}
|
344
|
+
end
|
345
|
+
def post_parse_argv; end
|
346
|
+
def pre_run; end
|
347
|
+
def post_run; end
|
348
|
+
def pre_main; end
|
349
|
+
def post_main; end
|
350
|
+
def logcatch
|
351
|
+
#--{{{
|
352
|
+
ret = nil
|
353
|
+
@logger ||= Logger::new STDERR
|
354
|
+
begin
|
355
|
+
ret = yield
|
356
|
+
rescue Exception => e
|
357
|
+
unless SystemExit === e
|
358
|
+
fatal{ e }
|
359
|
+
exit EXIT_FAILURE
|
360
|
+
if false
|
361
|
+
if logger.debug?
|
362
|
+
fatal{ e }
|
363
|
+
exit EXIT_FAILURE
|
364
|
+
else
|
365
|
+
fatal{ emsg(e) }
|
366
|
+
exit EXIT_FAILURE
|
367
|
+
end
|
368
|
+
end
|
369
|
+
else
|
370
|
+
exit e.status
|
371
|
+
end
|
372
|
+
end
|
373
|
+
ret
|
374
|
+
#--}}}
|
375
|
+
end
|
376
|
+
def usage port = STDERR
|
377
|
+
#--{{{
|
378
|
+
port << klass::usage << "\n" if(klass::usage and not klass::usage.empty?)
|
379
|
+
port << klass::examples << "\n" if(klass::examples and not klass::examples.empty?)
|
380
|
+
|
381
|
+
if klass::optspec
|
382
|
+
port << 'OPTIONS' << "\n"
|
383
|
+
|
384
|
+
klass::optspec.each do |os|
|
385
|
+
a, b, c = os
|
386
|
+
long, short, desc = nil
|
387
|
+
[a,b,c].each do |word|
|
388
|
+
next unless word
|
389
|
+
word.strip!
|
390
|
+
case word
|
391
|
+
when %r/^--[^-]/o
|
392
|
+
long = word
|
393
|
+
when %r/^-[^-]/o
|
394
|
+
short = word
|
395
|
+
else
|
396
|
+
desc = word
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
spec = ((long and short) ? [long, short] : [long])
|
401
|
+
|
402
|
+
if spec
|
403
|
+
port << Util::columnize(spec.join(', '), :width => 80, :indent => 2)
|
404
|
+
port << "\n"
|
405
|
+
end
|
406
|
+
|
407
|
+
if desc
|
408
|
+
port << Util::columnize(desc, :width => 80, :indent => 8)
|
409
|
+
port << "\n"
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
port << "\n"
|
414
|
+
end
|
415
|
+
|
416
|
+
port
|
417
|
+
#--}}}
|
418
|
+
end
|
419
|
+
def parse_options
|
420
|
+
#--{{{
|
421
|
+
@op = OptionParser::new
|
422
|
+
@options = {}
|
423
|
+
@listoptions = Hash::new{|h,k| h[k] = []}
|
424
|
+
klass::optspec.each do |spec|
|
425
|
+
k = spec.first.gsub(%r/(?:--)|(?:=.*$)|(?:\s+)/o,'')
|
426
|
+
@op.def_option(*spec) do |v|
|
427
|
+
@options[k] = v
|
428
|
+
@listoptions[k] << v
|
429
|
+
end
|
430
|
+
end
|
431
|
+
begin
|
432
|
+
op.parse! @argv
|
433
|
+
rescue OptionParser::InvalidOption => e
|
434
|
+
# preverve unknown options
|
435
|
+
#e.recover(argv)
|
436
|
+
invalid_option e
|
437
|
+
end
|
438
|
+
@options
|
439
|
+
#--}}}
|
440
|
+
end
|
441
|
+
def invalid_option e
|
442
|
+
#--{{{
|
443
|
+
# e.recover argv
|
444
|
+
fatal{ e.to_s }
|
445
|
+
exit EXIT_FAILURE
|
446
|
+
#--}}}
|
447
|
+
end
|
448
|
+
def init_logging opts = @options
|
449
|
+
#--{{{
|
450
|
+
log = Util::getopt 'log', opts
|
451
|
+
log_age = Util::getopt 'log_age', opts
|
452
|
+
log_size = Util::getopt 'log_size', opts
|
453
|
+
verbosity = Util::getopt 'verbosity', opts
|
454
|
+
log_age = Integer log_age rescue nil
|
455
|
+
log_size = Integer log_size rescue nil
|
456
|
+
$logger = @logger = Logger::new(log || STDERR, log_age, log_size)
|
457
|
+
#
|
458
|
+
# hack to fix Logger sync bug
|
459
|
+
#
|
460
|
+
begin
|
461
|
+
class << @logger; attr :logdev unless @logger.respond_to?(:logdev); end
|
462
|
+
@logdev = @logger.logdev.dev
|
463
|
+
@logdev.sync = true
|
464
|
+
rescue
|
465
|
+
nil
|
466
|
+
end
|
467
|
+
level = nil
|
468
|
+
verbosity ||= 'info'
|
469
|
+
verbosity =
|
470
|
+
case verbosity
|
471
|
+
when /^\s*(?:4|d|debug)\s*$/io
|
472
|
+
level = 'Logging::DEBUG'
|
473
|
+
4
|
474
|
+
when /^\s*(?:3|i|info)\s*$/io
|
475
|
+
level = 'Logging::INFO'
|
476
|
+
3
|
477
|
+
when /^\s*(?:2|w|warn)\s*$/io
|
478
|
+
level = 'Logging::WARN'
|
479
|
+
2
|
480
|
+
when /^\s*(?:1|e|error)\s*$/io
|
481
|
+
level = 'Logging::ERROR'
|
482
|
+
1
|
483
|
+
when /^\s*(?:0|f|fatal)\s*$/io
|
484
|
+
level = 'Logging::FATAL'
|
485
|
+
0
|
486
|
+
else
|
487
|
+
abort "illegal verbosity setting <#{ verbosity }>"
|
488
|
+
end
|
489
|
+
@logger.level = 2 - ((verbosity % 5) - 2)
|
490
|
+
@logger
|
491
|
+
#--}}}
|
492
|
+
end
|
493
|
+
def parse_argv
|
494
|
+
#--{{{
|
495
|
+
a, b = [], []
|
496
|
+
klass::required_arguments.each do |arg|
|
497
|
+
value = @argv.shift
|
498
|
+
if value
|
499
|
+
send "#{ arg }=", value
|
500
|
+
else
|
501
|
+
die 'msg' => "required_argument <#{ arg }> not given"
|
502
|
+
end
|
503
|
+
a << send("#{ arg }")
|
504
|
+
end
|
505
|
+
klass::optional_arguments.each do |arg|
|
506
|
+
value = @argv.shift
|
507
|
+
if value
|
508
|
+
send "#{ arg }=", value
|
509
|
+
end
|
510
|
+
b << send("#{ arg }")
|
511
|
+
end
|
512
|
+
[a, b, @argv]
|
513
|
+
#--}}}
|
514
|
+
end
|
515
|
+
def die opts = {}
|
516
|
+
#--{{{
|
517
|
+
msg = Util::getopt 'msg', opts, klass.usage
|
518
|
+
errno = Util::getopt 'errno', opts, EXIT_FAILURE
|
519
|
+
STDERR.puts("#{ msg }")
|
520
|
+
exit(Integer(errno))
|
521
|
+
#--}}}
|
522
|
+
end
|
523
|
+
def main
|
524
|
+
#--{{{
|
525
|
+
raise NotImplementedError, 'main'
|
526
|
+
#--}}}
|
527
|
+
end
|
528
|
+
#--}}}
|
529
|
+
end # class AbstractMain
|
530
|
+
|
531
|
+
class SimpleMain < AbstractMain
|
532
|
+
end
|
533
|
+
|
534
|
+
class ConfigurableMain < AbstractMain
|
535
|
+
#--{{{
|
536
|
+
def self.class_initialize
|
537
|
+
#--{{{
|
538
|
+
super
|
539
|
+
class_attribute :config_default_path
|
540
|
+
class_attribute :config_search_path
|
541
|
+
class_attribute :configfile
|
542
|
+
|
543
|
+
config_default_path "#{ prognam }.conf"
|
544
|
+
|
545
|
+
config_search_path %w(. ~ /usr/local/etc /usr/etc /etc)
|
546
|
+
|
547
|
+
configfile Class::new(ALib::ConfigFile) #{ default = DATA; DATA.rewind; }
|
548
|
+
|
549
|
+
optspec << [ '--config=path', 'valid path - specify config file (default nil)' ]
|
550
|
+
optspec << [ '--template=[path]', 'valid path - generate a template config file in path (default stdout)' ]
|
551
|
+
#--}}}
|
552
|
+
end
|
553
|
+
|
554
|
+
attribute :config
|
555
|
+
|
556
|
+
def pre_parse_argv
|
557
|
+
#--{{{
|
558
|
+
super
|
559
|
+
if(@options.has_key?('template') or @argv.first =~ %r/template/i)
|
560
|
+
@argv.shift if @argv.first =~ %r/template/i
|
561
|
+
arg = @argv.first
|
562
|
+
gen_template @options['template'] || @options['config'] || arg
|
563
|
+
exit EXIT_SUCCESS
|
564
|
+
end
|
565
|
+
#--}}}
|
566
|
+
end
|
567
|
+
def gen_template template
|
568
|
+
#--{{{
|
569
|
+
klass::configfile::gen_template(template)
|
570
|
+
self
|
571
|
+
#--}}}
|
572
|
+
end
|
573
|
+
def post_parse_argv
|
574
|
+
#--{{{
|
575
|
+
init_config
|
576
|
+
#--}}}
|
577
|
+
end
|
578
|
+
def init_config opts = @options
|
579
|
+
#--{{{
|
580
|
+
conf = Util::getopt 'config', opts
|
581
|
+
@config =
|
582
|
+
if conf
|
583
|
+
klass::configfile::new(conf)
|
584
|
+
else
|
585
|
+
klass::configfile::any klass::config_default_path, klass::config_search_path
|
586
|
+
end
|
587
|
+
@config
|
588
|
+
#--}}}
|
589
|
+
end
|
590
|
+
#--}}}
|
591
|
+
end
|
592
|
+
|
593
|
+
end
|
594
|
+
|