alib 0.4.0 → 0.5.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.
@@ -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