main 0.0.2 → 2.0.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/gen_readme.rb CHANGED
@@ -12,7 +12,11 @@ template = IO::read 'README.tmpl'
12
12
  samples = ''
13
13
  prompt = '~ > '
14
14
 
15
+ skip = %w[ e.rb f.rb ]
16
+
15
17
  Dir['sample*/*'].sort.each do |sample|
18
+ next if skip.include? File.basename(sample)
19
+
16
20
  samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
17
21
 
18
22
  cmd = "cat #{ sample }"
@@ -0,0 +1,434 @@
1
+ #
2
+ # The ArrayFields module implements methods which allow an Array to be indexed
3
+ # by String or Symbol. It is not required to manually use this module to
4
+ # extend Arrays - they are auto-extended on a per-object basis when
5
+ # Array#fields= is called
6
+ #
7
+ module ArrayFields
8
+ self::VERSION = '4.5.0' unless defined? self::VERSION
9
+ def self.version() VERSION end
10
+ #
11
+ # multiton cache of fields - wraps fields and fieldpos map to save memory
12
+ #
13
+ class FieldSet
14
+ class << self
15
+ def new fields
16
+ @sets[fields] ||= super
17
+ end
18
+ def init_sets
19
+ @sets = {}
20
+ end
21
+ end
22
+
23
+ init_sets
24
+
25
+ attr :fields
26
+ attr :fieldpos
27
+ def initialize fields
28
+ raise ArgumentError, "<#{ fields.inspect }> not inject-able" unless
29
+ fields.respond_to? :inject
30
+
31
+ @fieldpos =
32
+ fields.inject({}) do |h, f|
33
+ unless String === f or Symbol === f
34
+ raise ArgumentError, "<#{ f.inspect }> neither String nor Symbol"
35
+ end
36
+ h[f] = h.size
37
+ h
38
+ end
39
+
40
+ @fields = fields
41
+ end
42
+ def pos f
43
+ return @fieldpos[f] if @fieldpos.has_key? f
44
+ f = f.to_s
45
+ return @fieldpos[f] if @fieldpos.has_key? f
46
+ f = f.intern
47
+ return @fieldpos[f] if @fieldpos.has_key? f
48
+ nil
49
+ end
50
+ end
51
+ #
52
+ # methods redefined to work with fields as well as numeric indexes
53
+ #
54
+ def [] idx, *args
55
+ if @fieldset and (String === idx or Symbol === idx)
56
+ pos = @fieldset.pos idx
57
+ return nil unless pos
58
+ super(pos, *args)
59
+ else
60
+ super
61
+ end
62
+ end
63
+ def slice idx, *args
64
+ if @fieldset and (String === idx or Symbol === idx)
65
+ pos = @fieldset.pos idx
66
+ return nil unless pos
67
+ super(pos, *args)
68
+ else
69
+ super
70
+ end
71
+ end
72
+
73
+ def []=(idx, *args)
74
+ if @fieldset and (String === idx or Symbol === idx)
75
+ pos = @fieldset.pos idx
76
+ unless pos
77
+ @fieldset.fields << idx
78
+ @fieldset.fieldpos[idx] = pos = size
79
+ end
80
+ super(pos, *args)
81
+ else
82
+ super
83
+ end
84
+ end
85
+ def at idx
86
+ if @fieldset and (String === idx or Symbol === idx)
87
+ pos = @fieldset.pos idx
88
+ return nil unless pos
89
+ super pos
90
+ else
91
+ super
92
+ end
93
+ end
94
+ def delete_at idx
95
+ if @fieldset and (String === idx or Symbol === idx)
96
+ pos = @fieldset.pos idx
97
+ return nil unless pos
98
+ super pos
99
+ else
100
+ super
101
+ end
102
+ end
103
+ def fill(obj, *args)
104
+ idx = args.first
105
+ if idx and @fieldset and (String === idx or Symbol === idx)
106
+ idx = args.shift
107
+ pos = @fieldset.pos idx
108
+ super(obj, pos, *args)
109
+ else
110
+ super
111
+ end
112
+ end
113
+
114
+ def values_at(*idxs)
115
+ idxs.flatten!
116
+ if @fieldset
117
+ idxs.map!{|i| (String === i or Symbol === i) ? @fieldset.pos(i) : i}
118
+ end
119
+ super(*idxs)
120
+ end
121
+ def indices(*idxs)
122
+ idxs.flatten!
123
+ if @fieldset
124
+ idxs.map!{|i| (String === i or Symbol === i) ? @fieldset.pos(i) : i}
125
+ end
126
+ super(*idxs)
127
+ end
128
+ def indexes(*idxs)
129
+ idxs.flatten!
130
+ if @fieldset
131
+ idxs.map!{|i| (String === i or Symbol === i) ? @fieldset.pos(i) : i}
132
+ end
133
+ super(*idxs)
134
+ end
135
+
136
+ def slice!(*args)
137
+ ret = self[*args]
138
+ self[*args] = nil
139
+ ret
140
+ end
141
+ def each_with_field
142
+ each_with_index do |elem, i|
143
+ yield elem, @fieldset.fields[i]
144
+ end
145
+ end
146
+ #
147
+ # methods which give a hash-like interface
148
+ #
149
+ def each_pair
150
+ each_with_index do |elem, i|
151
+ yield @fieldset.fields[i], elem
152
+ end
153
+ end
154
+ def each_key
155
+ @fieldset.each{|field| yield field}
156
+ end
157
+ def each_value *args, &block
158
+ each *args, &block
159
+ end
160
+ def fetch key
161
+ self[key] or raise IndexError, 'key not found'
162
+ end
163
+
164
+ def has_key? key
165
+ @fieldset.fields.include? key
166
+ end
167
+ def member? key
168
+ @fieldset.fields.include? key
169
+ end
170
+ def key? key
171
+ @fieldset.fields.include? key
172
+ end
173
+
174
+ def has_value? value
175
+ if respond_to? 'include?'
176
+ self.include? value
177
+ else
178
+ a = []
179
+ each{|val| a << val}
180
+ a.include? value
181
+ end
182
+ end
183
+ def value? value
184
+ if respond_to? 'include?'
185
+ self.include? value
186
+ else
187
+ a = []
188
+ each{|val| a << val}
189
+ a.include? value
190
+ end
191
+ end
192
+
193
+ def keys
194
+ fields
195
+ end
196
+ def store key, value
197
+ self[key] = value
198
+ end
199
+ def values
200
+ if respond_to? 'to_ary'
201
+ self.to_ary
202
+ else
203
+ a = []
204
+ each{|val| a << val}
205
+ a
206
+ end
207
+ end
208
+
209
+ def to_hash
210
+ if respond_to? 'to_ary'
211
+ h = {}
212
+ @fieldset.fields.zip(to_ary){|f,e| h[f] = e}
213
+ h
214
+ else
215
+ a = []
216
+ each{|val| a << val}
217
+ h = {}
218
+ @fieldset.fields.zip(a){|f,e| h[f] = e}
219
+ h
220
+ end
221
+ end
222
+ def to_h
223
+ if respond_to? 'to_ary'
224
+ h = {}
225
+ @fieldset.fields.zip(to_ary){|f,e| h[f] = e}
226
+ h
227
+ else
228
+ a = []
229
+ each{|val| a << val}
230
+ h = {}
231
+ @fieldset.fields.zip(a){|f,e| h[f] = e}
232
+ h
233
+ end
234
+ end
235
+
236
+ def update other
237
+ other.each{|k,v| self[k] = v}
238
+ to_hash
239
+ end
240
+ def replace other
241
+ Hash === other ? update(other) : super
242
+ end
243
+ def invert
244
+ to_hash.invert
245
+ end
246
+
247
+ def to_pairs
248
+ fields.zip values
249
+ end
250
+ alias_method 'pairs', 'to_pairs'
251
+
252
+ def copy
253
+ cp = clone
254
+ cp.fields = fields.clone
255
+ cp
256
+ end
257
+
258
+ alias_method 'dup', 'copy'
259
+ alias_method 'clone', 'copy'
260
+
261
+ def deepcopy
262
+ cp = Marshal.load(Marshal.dump(self))
263
+ cp.fields = Marshal.load(Marshal.dump(self.fields))
264
+ cp
265
+ end
266
+ end
267
+ Arrayfields = ArrayFields
268
+
269
+ module Arrayfields
270
+ def self.new *pairs
271
+ pairs = pairs.map{|pair| Enumerable === pair ? pair.to_a : pair}.flatten
272
+ raise ArgumentError, "pairs must be evenly sized" unless(pairs.size % 2 == 0)
273
+ (( array = [] )).fields = []
274
+ 0.step(pairs.size - 2, 2) do |a|
275
+ b = a + 1
276
+ array[ pairs[a] ] = pairs[b]
277
+ end
278
+ array
279
+ end
280
+ def self.[] *pairs
281
+ new *pairs
282
+ end
283
+ end
284
+ def Arrayfields(*a, &b) Arrayfields.new(*a, &b) end
285
+ #
286
+ # Fieldable encapsulates methods in common for classes which may have their
287
+ # fields set and subsequently be auto-extended by ArrayFields
288
+ #
289
+ module Fieldable
290
+ #
291
+ # sets fields an dynamically extends this Array instance with methods for
292
+ # keyword access
293
+ #
294
+ def fields= fields
295
+ extend ArrayFields unless ArrayFields === self
296
+
297
+ @fieldset =
298
+ if ArrayFields::FieldSet === fields
299
+ fields
300
+ else
301
+ ArrayFields::FieldSet.new fields
302
+ end
303
+ end
304
+ #
305
+ # access to fieldset
306
+ #
307
+ attr_reader :fieldset
308
+ #
309
+ # access to field list
310
+ #
311
+ def fields
312
+ @fieldset and @fieldset.fields
313
+ end
314
+ end
315
+ #
316
+ # Array instances are extened with two methods only: Fieldable#fields= and
317
+ # Fieldable#fields. only when Fieldable#fields= is called will the full set
318
+ # of ArrayFields methods auto-extend the Array instance. the Array class also
319
+ # has added a class generator when the fields are known apriori.
320
+ #
321
+ class Array
322
+ include Fieldable
323
+
324
+ class << self
325
+ def struct *fields
326
+ fields = fields.flatten
327
+ Class.new(self) do
328
+ include ArrayFields
329
+ const_set :FIELDS, ArrayFields::FieldSet.new(fields)
330
+ fields.each do |field|
331
+ field = field.to_s
332
+ if field =~ %r/^[a-zA-Z_][a-zA-Z0-9_]*$/
333
+ begin
334
+ module_eval <<-code
335
+ def #{ field } *a
336
+ a.size == 0 ? self['#{ field }'] : (self.#{ field } = a.shift)
337
+ end
338
+ def #{ field }= value
339
+ self['#{ field }'] = value
340
+ end
341
+ code
342
+ rescue SyntaxError
343
+ :by_ignoring_it
344
+ end
345
+ end
346
+ end
347
+ def initialize *a, &b
348
+ super
349
+ ensure
350
+ @fieldset = self.class.const_get :FIELDS
351
+ end
352
+ def self.[] *elements
353
+ array = new
354
+ array.replace elements
355
+ array
356
+ end
357
+ end
358
+ end
359
+ def fields *fields, &block
360
+ (( array = new(&block) )).fields = fields.map{|x| Enumerable === x ? x.to_a : x}.flatten
361
+ array
362
+ end
363
+ end
364
+ end
365
+ #
366
+ # proxy class that allows an array to be wrapped in a way that still allows #
367
+ # keyword access. also facilitate usage of ArrayFields with arraylike objects.
368
+ # thnx to Sean O'Dell for the suggestion.
369
+ #
370
+ # sample usage
371
+ #
372
+ # fa = FieldedArray.new %w(zero one two), [0,1,2]
373
+ # p fa['zero'] #=> 0
374
+ #
375
+ #
376
+ class FieldedArray
377
+ include Fieldable
378
+ class << self
379
+ def [](*pairs)
380
+ pairs.flatten!
381
+ raise ArgumentError, "argument must be key/val pairs" unless
382
+ (pairs.size % 2 == 0)
383
+ fields, elements = [], []
384
+ while((f = pairs.shift) and (e = pairs.shift))
385
+ fields << f and elements << e
386
+ end
387
+ new fields, elements
388
+ end
389
+ end
390
+ def initialize fields = [], array = []
391
+ @a = array
392
+ self.fields = fields
393
+ end
394
+ def method_missing(meth, *args, &block)
395
+ @a.send(meth, *args, &block)
396
+ end
397
+ delegates =
398
+ %w(
399
+ to_s
400
+ to_str
401
+ inspect
402
+ )
403
+ delegates.each do |meth|
404
+ class_eval "def #{ meth }(*a,&b); @a.#{ meth }(*a,&b);end"
405
+ end
406
+ end
407
+ Fieldedarray = FieldedArray
408
+
409
+ class PseudoHash < ::Array
410
+ class << self
411
+ def [](*pairs)
412
+ pairs.flatten!
413
+ raise ArgumentError, "argument must be key/val pairs" unless
414
+ (pairs.size % 2 == 0 and pairs.size >= 2)
415
+ keys, values = [], []
416
+ while((k = pairs.shift) and (v = pairs.shift))
417
+ keys << k and values << v
418
+ end
419
+ new keys, values
420
+ end
421
+ end
422
+ def initialize keys = [], values = []
423
+ self.fields = keys
424
+ self.replace values
425
+ end
426
+ def to_yaml opts = {}
427
+ YAML::quick_emit object_id, opts do |out|
428
+ out.map taguri, to_yaml_style do |map|
429
+ each_pair{|f,v| map.add f,v}
430
+ end
431
+ end
432
+ end
433
+ end
434
+ Pseudohash = PseudoHash
data/lib/main.rb CHANGED
@@ -1,32 +1,61 @@
1
1
  module Main
2
- VERSION = '0.0.2'
3
- def version() VERSION end
2
+ #
3
+ # top level constants
4
+ #
5
+ Main::VERSION = '2.0.0' unless
6
+ defined? Main::VERSION
7
+ def self.version() Main::VERSION end
4
8
 
5
- LIBDIR = File.join(File.dirname(File.expand_path(__FILE__)), self.name.downcase, '')
9
+ Main::LIBDIR = File.join(File.dirname(File.expand_path(__FILE__)), self.name.downcase, '') unless
10
+ defined? Main::LIBDIR
11
+ def self.libdir() Main::LIBDIR end
6
12
 
7
- EXIT_SUCCESS = 0
8
- EXIT_FAILURE = 1
9
- EXIT_WARN = 42
13
+ Main::EXIT_SUCCESS = 0 unless defined? Main::EXIT_SUCCESS
14
+ Main::EXIT_FAILURE = 1 unless defined? Main::EXIT_FAILURE
15
+ Main::EXIT_WARN = 42 unless defined? Main::EXIT_WARN
10
16
  #
11
17
  # built-in
12
18
  #
13
19
  require 'logger'
14
20
  require 'enumerator'
21
+ require 'set'
22
+
15
23
  #
16
- # inlcuded from other codeforpeople.com projects
24
+ # we try to use gems to pick up dependancies
17
25
  #
18
- require LIBDIR + 'attributes'
19
- require LIBDIR + 'arrayfields'
26
+
27
+ =begin
28
+ begin
29
+ require 'rubygems'
30
+ rescue LoadError
31
+ 42
32
+ end
33
+ begin
34
+ require 'attributes'
35
+ rescue LoadError
36
+ require libdir + 'attributes'
37
+ end
38
+ begin
39
+ require 'arrayfields'
40
+ rescue LoadError
41
+ require libdir + 'arrayfields'
42
+ end
43
+ =end
44
+ require libdir + 'attributes'
45
+ require libdir + 'arrayfields'
46
+
20
47
  #
21
48
  # main libs
22
49
  #
23
- require LIBDIR + 'util'
24
- require LIBDIR + 'usage'
25
- require LIBDIR + 'cast'
26
- require LIBDIR + 'parameter'
27
- require LIBDIR + 'getoptlong'
28
- require LIBDIR + 'proxy'
29
- require LIBDIR + 'base'
30
- require LIBDIR + 'factories'
50
+ require libdir + 'stdext'
51
+ require libdir + 'softspoken'
52
+ require libdir + 'util'
53
+ require libdir + 'usage'
54
+ require libdir + 'cast'
55
+ require libdir + 'parameter'
56
+ require libdir + 'getoptlong'
57
+ require libdir + 'mode'
58
+ require libdir + 'base'
59
+ require libdir + 'factories'
31
60
  end
32
61