alib 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,9 +10,33 @@ module ALib
10
10
  include ALib
11
11
  include ALib::Logging
12
12
 
13
- EXIT_SUCCESS = 0
14
- EXIT_PSEUDO_SUCCESS = 42
15
- EXIT_FAILURE = 1
13
+ module Constants
14
+ EXIT_SUCCESS = 0
15
+ EXIT_PSEUDO_SUCCESS = 42
16
+ EXIT_OK = 42
17
+ EXIT_FAILURE = 1
18
+ end
19
+ include Constants
20
+
21
+ def self.exit_success() EXIT_SUCCESS end
22
+ def exit_success() EXIT_SUCCESS end
23
+ def self.status_success() EXIT_SUCCESS end
24
+ def status_success() EXIT_SUCCESS end
25
+
26
+ def self.exit_pseudo_success() EXIT_PSEUDO_SUCCESS end
27
+ def exit_pseudo_success() EXIT_PSEUDO_SUCCESS end
28
+ def self.status_pseudo_success() EXIT_PSEUDO_SUCCESS end
29
+ def status_pseudo_success() EXIT_PSEUDO_SUCCESS end
30
+
31
+ def self.exit_ok() EXIT_OK end
32
+ def exit_ok() EXIT_OK end
33
+ def self.status_ok() EXIT_OK end
34
+ def status_ok() EXIT_OK end
35
+
36
+ def self.exit_failure() EXIT_FAILURE end
37
+ def exit_failure() EXIT_FAILURE end
38
+ def self.status_failure() EXIT_FAILURE end
39
+ def status_failure() EXIT_FAILURE end
16
40
 
17
41
  class << self
18
42
  #--{{{
@@ -79,7 +103,7 @@ module ALib
79
103
  alias c_attrs class_attributes
80
104
  alias c_attr class_attributes
81
105
 
82
- %w( version author program optspec ).each do |meth|
106
+ %w( version author program optspec name examples synopsis ).each do |meth|
83
107
  #--{{{
84
108
  module_eval <<-code
85
109
  def #{ meth }(*a)
@@ -99,9 +123,11 @@ module ALib
99
123
  #--}}}
100
124
  end
101
125
  alias prognam program
126
+ alias progname program
102
127
  alias prognam= program=
103
128
  alias prognam? program?
104
129
 
130
+ =begin
105
131
  %w( usage examples ).each do |meth|
106
132
  #--{{{
107
133
  module_eval <<-code
@@ -121,6 +147,51 @@ module ALib
121
147
  code
122
148
  #--}}}
123
149
  end
150
+ =end
151
+
152
+ def usage arg = nil
153
+ #--{{{
154
+ if arg
155
+ @usage = arg.to_s
156
+ else
157
+ if defined? @usage
158
+ @usage
159
+ else
160
+ s = ""
161
+
162
+ unless name.to_s.empty?
163
+ #s << "\n"
164
+ s << "NAME\n"
165
+ s << indent_block("#{ name }\n", 2)
166
+ end
167
+
168
+ unless synopsis.to_s.empty?
169
+ s << "\n"
170
+ s << "SYNOPSIS\n"
171
+ s << indent_block("#{ synopsis }\n", 2)
172
+ end
173
+
174
+ unless examples.to_s.empty?
175
+ s << "\n"
176
+ s << "EXAMPLES\n"
177
+ s << indent_block("#{ examples }\n", 2)
178
+ end
179
+
180
+ s
181
+ end
182
+ end
183
+ #--}}}
184
+ end
185
+
186
+ =begin
187
+ usage <<-usage
188
+ NAME
189
+ #{ program } v#{ version }
190
+
191
+ SYNOPSIS
192
+ #{ program } [options]* [file]*
193
+ usage
194
+ =end
124
195
 
125
196
 
126
197
  def unindent_block buf
@@ -139,6 +210,13 @@ module ALib
139
210
  #--}}}
140
211
  end
141
212
 
213
+ def indent_block buf, n = 2
214
+ #--{{{
215
+ space = ' ' * n.to_i
216
+ unindent_block(buf).gsub %r/^/, space
217
+ #--}}}
218
+ end
219
+
142
220
  def options(*list)
143
221
  #--{{{
144
222
  @optspec ||= []
@@ -236,27 +314,31 @@ module ALib
236
314
 
237
315
  program File.basename($0)
238
316
 
317
+ name "#{ program } v#{ version }"
318
+
239
319
  optspec [
240
320
  [ '--help', '-h', 'this message' ],
241
321
  [ '--log=path','-l', 'set log file - (default stderr)' ],
242
322
  [ '--verbosity=verbostiy', '-v', '0|fatal < 1|error < 2|warn < 3|info < 4|debug - (default info)' ],
243
323
  ]
244
324
 
325
+ =begin
245
326
  usage <<-usage
246
327
  NAME
247
328
  #{ program } v#{ version }
248
329
 
249
330
  SYNOPSIS
250
- #{ program } [options]+ [file]+
331
+ #{ program } [options]* [file]*
251
332
  usage
333
+ =end
252
334
 
253
335
  examples ''
254
336
  #--}}}
255
337
  end
256
338
 
257
- def inherited klass
339
+ def inherited klass, &b
258
340
  #--{{{
259
- ret = super
341
+ ret = super(klass, &b)
260
342
  klass.class_initialize
261
343
  ret
262
344
  #--}}}
@@ -267,9 +349,24 @@ module ALib
267
349
  new(*a, &b).run
268
350
  #--}}}
269
351
  end
352
+
353
+ def defaults head = nil, *tail
354
+ #--{{{
355
+ @defaults ||= {}
356
+ return @defaults if head.nil?
357
+ return @defaults.update(head) if head.is_a?(Hash)
358
+ return @defaults.values_at(*head) if head.is_a?(Array)
359
+ return @defaults[head.to_s] if tail.empty?
360
+ keys = [head, tail].flatten.map{|k| k.to_s}
361
+ return @defaults.values_at(*keys)
362
+ #--}}}
363
+ end
364
+ alias_method "default", "defaults"
270
365
  #--}}}
271
366
  end
272
367
 
368
+ #class_attribute
369
+
273
370
  class_initialize
274
371
 
275
372
  attr :logger
@@ -285,7 +382,12 @@ module ALib
285
382
  attr :verbosity
286
383
  alias console? console
287
384
 
288
- def initialize argv = ARGV, env = ENV
385
+ def exit_status e = nil
386
+ (e ? (@exit_success = e) : (defined?(@exit_success) and @exit_success))
387
+ end
388
+ alias_method "exit_status?", "exit_status"
389
+
390
+ def __initialize__ argv = ARGV, env = ENV
289
391
  #--{{{
290
392
  @argv = Util::mcp(argv.to_a)
291
393
  @env = Util::mcp(env.to_hash)
@@ -294,7 +396,16 @@ module ALib
294
396
  @console = STDIN.tty?
295
397
  #--}}}
296
398
  end
399
+
400
+ def self.new *a, &b
401
+ #--{{{
402
+ (obj = allocate).instance_eval{ __initialize__ *a, &b }
403
+ obj
404
+ #--}}}
405
+ end
406
+
297
407
  def klass; self.class; end
408
+
298
409
  def required_arguments
299
410
  #--{{{
300
411
  klass::required_arguments
@@ -310,26 +421,39 @@ module ALib
310
421
  logcatch do
311
422
  begin
312
423
  pre_run
424
+
313
425
  pre_parse_options
314
426
  parse_options
315
427
  post_parse_options
428
+
316
429
  pre_parse_argv
317
430
  parse_argv
318
431
  post_parse_argv
432
+
433
+ pre_init_logging
319
434
  init_logging
435
+ post_init_logging
436
+
437
+ initialize
438
+
320
439
  pre_main
321
440
  status = main
322
441
  post_main
442
+
323
443
  post_run
324
- exit(status ? EXIT_SUCCESS : EXIT_FAILURE)
444
+
445
+ exit(exit_status ? exit_status : (status ? EXIT_SUCCESS : EXIT_FAILURE))
325
446
  rescue Errno::EPIPE
326
447
  STDOUT.tty? ? raise : exit(EXIT_FAILURE)
327
448
  end
328
449
  end
329
450
  #--}}}
330
451
  end
452
+ def initialize; end
331
453
  def pre_parse_options; end
332
454
  def post_parse_options; end
455
+ def pre_init_logging; end
456
+ def post_init_logging; end
333
457
  def pre_parse_argv
334
458
  #--{{{
335
459
  if(@options.has_key?('help') or (@argv.size == 1 and @argv.first =~ %r/help/i))
@@ -350,7 +474,8 @@ module ALib
350
474
  def logcatch
351
475
  #--{{{
352
476
  ret = nil
353
- @logger ||= Logger::new STDERR
477
+ # @logger ||= Logger::new STDERR
478
+ logger!
354
479
  begin
355
480
  ret = yield
356
481
  rescue Exception => e
@@ -453,7 +578,7 @@ module ALib
453
578
  verbosity = Util::getopt 'verbosity', opts
454
579
  log_age = Integer log_age rescue nil
455
580
  log_size = Integer log_size rescue nil
456
- $logger = @logger = Logger::new(log || STDERR, log_age, log_size)
581
+ $logger = self.logger = Logger::new(log || STDERR, log_age, log_size)
457
582
  #
458
583
  # hack to fix Logger sync bug
459
584
  #
@@ -486,8 +611,8 @@ module ALib
486
611
  else
487
612
  abort "illegal verbosity setting <#{ verbosity }>"
488
613
  end
489
- @logger.level = 2 - ((verbosity % 5) - 2)
490
- @logger
614
+ logger.level = 2 - ((verbosity % 5) - 2)
615
+ logger
491
616
  #--}}}
492
617
  end
493
618
  def parse_argv
@@ -522,9 +647,286 @@ module ALib
522
647
  end
523
648
  def main
524
649
  #--{{{
525
- raise NotImplementedError, 'main'
650
+ 42
651
+ #--}}}
652
+ end
653
+ def options? *keys
654
+ #--{{{
655
+ list = keys.map{|key| @options.has_key? key}
656
+ list.size > 0 and list.all?
657
+ #--}}}
658
+ end
659
+ alias_method "option?", "options?"
660
+ def options *keys
661
+ #--{{{
662
+ if keys.empty?
663
+ @options
664
+ else
665
+ keys.map{|key| @options[key]}
666
+ end
667
+ #--}}}
668
+ end
669
+ def option key
670
+ #--{{{
671
+ options(key).first
672
+ #--}}}
673
+ end
674
+ def arguments *args
675
+ #--{{{
676
+ args.map{|arg| send arg}
677
+ #--}}}
678
+ end
679
+ def argument arg
680
+ #--{{{
681
+ arguments(arg).first
682
+ #--}}}
683
+ end
684
+ def defaults *a, &b
685
+ #--{{{
686
+ self.class.defaults *a, &b
526
687
  #--}}}
527
688
  end
689
+ alias_method "default", "defaults"
690
+
691
+ def argv_plus_stdin
692
+ #--{{{
693
+ stdin = argv.delete '-'
694
+ STDIN.each{|line| argv << line} if stdin
695
+ argv.map!{|arg| arg.strip}
696
+ argv
697
+ #--}}}
698
+ end
699
+
700
+ #
701
+ # param dsl and class
702
+ #
703
+ class Param < ::String
704
+ #--{{{
705
+ include Util::Casting
706
+
707
+ def self.pattr name
708
+ #--{{{
709
+ module_eval <<-code
710
+ def #{ name } *_a, &b
711
+ _a.push lambda{ instance_eval &b } if b
712
+ _a.size == 0 ? (defined? @#{ name } and @#{ name }) : (@#{ name }=_a.shift)
713
+ end
714
+ def #{ name }?
715
+ defined?(@#{ name }) and @#{ name }
716
+ end
717
+ def #{ name }= val
718
+ #{ name }( val )
719
+ end
720
+ code
721
+ #--}}}
722
+ end
723
+
724
+ %w(
725
+ this
726
+ rhs
727
+ required_argument
728
+ optional_argument
729
+ long
730
+ short
731
+ description
732
+ default
733
+ munge
734
+ cast
735
+ ).each{|a| pattr a}
736
+
737
+ alias_method 'desc', 'description'
738
+ alias_method 'synopsis', 'description'
739
+
740
+ {
741
+ 'requires_argument' => 'required_argument',
742
+ 'argument_required' => 'required_argument',
743
+ 'arg_required' => 'required_argument',
744
+ 'req_arg' => 'required_argument',
745
+ 'opt_arg' => 'optional_argument',
746
+ 'argument_optional' => 'optional_argument',
747
+ 'arg_optional' => 'optional_argument',
748
+ }.each{|dst,src| define_method(dst){ send src, true }}
749
+
750
+ def initialize name, this = nil, &block
751
+ #--{{{
752
+ if name.is_a?(Array)
753
+ a, b, ignored = name
754
+ a, b = a.to_s, b.to_s
755
+ name = a.size > b.size ? a : b
756
+ st = a.size > b.size ? b : a
757
+ short st
758
+ end
759
+
760
+ name = name.to_s
761
+ @this = this
762
+
763
+ re = %r/\s*=\s*([^=]+)\s*$/
764
+ m, @rhs = re.match(name).to_a
765
+ name.gsub! re, '' if @rhs
766
+ name.gsub! %r/^\s*--/, ''
767
+
768
+ super(name.to_s.gsub(%r/^\s*--/,''))
769
+ instance_eval &block if block
770
+ #--}}}
771
+ end
772
+ def long
773
+ #--{{{
774
+ @long ||= "--#{ self }"
775
+ #--}}}
776
+ end
777
+ def to_a
778
+ #--{{{
779
+ [ long, short, description ].compact
780
+ #--}}}
781
+ end
782
+ def to_option
783
+ #--{{{
784
+ optspec = []
785
+
786
+ if long
787
+ s = "#{ long }"
788
+ if required_argument
789
+ s << "=#{ self }"
790
+ elsif optional_argument
791
+ s << "=[#{ self }]"
792
+ elsif rhs
793
+ s << "=#{ rhs }" unless s[%r/=/]
794
+ end
795
+ optspec << s
796
+ end
797
+
798
+ if short
799
+ s = "#{ short }".strip.gsub(%r/^-*/,'-')
800
+ optspec << s
801
+ end
802
+
803
+ if description
804
+ s = "#{ description }"
805
+ optspec << s
806
+ end
807
+
808
+ optspec
809
+ #--}}}
810
+ end
811
+ def argument what = :required
812
+ #--{{{
813
+ case what.to_s
814
+ when /opt/i
815
+ send "optional_argument", true
816
+ when /req/i
817
+ send "required_argument", true
818
+ else
819
+ raise "what <#{ what }>"
820
+ end
821
+ #--}}}
822
+ end
823
+ alias_method 'arg', 'argument'
824
+ def cast &b
825
+ #--{{{
826
+ b and @cast = b
827
+ cast? ? @cast : nil
828
+ #--}}}
829
+ end
830
+ def cast?
831
+ #--{{{
832
+ defined? @cast
833
+ #--}}}
834
+ end
835
+ def param name # call up!
836
+ #--{{{
837
+ @this.param name
838
+ #--}}}
839
+ end
840
+ def value this = self
841
+ #--{{{
842
+ if defined? @default
843
+ @default.respond_to?('call') ? @default.call : @default
844
+ else
845
+ nil
846
+ end
847
+ #--}}}
848
+ end
849
+ #--}}}
850
+ end
851
+ #
852
+ # meta-hooks for param dsl
853
+ #
854
+ class << self
855
+ #--{{{
856
+ def params
857
+ #--{{{
858
+ @params ||= {}
859
+ #--}}}
860
+ end
861
+ alias_method "parms", "params"
862
+ def param name, this = self, &block
863
+ #--{{{
864
+ parm =
865
+ if block or name.is_a?(Array)
866
+ param = Param.new name, this, &block
867
+ option *param.to_option
868
+ default param => param.default
869
+ params[ param.to_s ] = param
870
+ else
871
+ name = name.to_s
872
+ defined = params[ name ]
873
+ if defined
874
+ defined
875
+ else
876
+ param = Param.new name, this, &block
877
+ option *param.to_option
878
+ default param => param.default
879
+ params[ param.to_s ] = param
880
+ end
881
+ end
882
+ parm.value
883
+ #--}}}
884
+ end
885
+ alias_method "parm", "param"
886
+ def get_param name
887
+ params[ name.to_s ]
888
+ end
889
+ #--}}}
890
+ end
891
+ def params
892
+ #--{{{
893
+ self.class.params
894
+ #--}}}
895
+ end
896
+ alias_method "parms", "params"
897
+ def param? name
898
+ #--{{{
899
+ key = name.to_s
900
+ options.has_key? key
901
+ #--}}}
902
+ end
903
+ def param name, *a
904
+ #--{{{
905
+ key = name.to_s
906
+ pm = params[key] or raise "no such param <#{ key }>!"
907
+
908
+ value =
909
+ if options.has_key? key
910
+ options[key] || default(key)
911
+ else
912
+ a.empty? ? default(key) : a.shift
913
+ end
914
+
915
+ #value = value.call if value.respond_to?('call')
916
+ value = instance_eval &value if Proc === value
917
+
918
+ #value = pm.cast[value] if(option?(key) and pm.cast?)
919
+ value = pm.cast[value] if(value and pm.cast?)
920
+
921
+ value
922
+ #--}}}
923
+ end
924
+ alias_method "parm", "param"
925
+
926
+
927
+ def self.main &block
928
+ define_method :main, &block
929
+ end
528
930
  #--}}}
529
931
  end # class AbstractMain
530
932