main 0.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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