filigree 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a1d6915cb3d2543b432be0c5edbf4a3217ab373e
4
- data.tar.gz: 4855e4e67ea643c57890627905bb4be09d0d784d
3
+ metadata.gz: 7264462695b42d279eabfc6cf85ff3569dc256ce
4
+ data.tar.gz: 29f78a7573518bcffe8b4ac1a7e4c17ada4e1679
5
5
  SHA512:
6
- metadata.gz: 79fcfefdb28a5ce107c5568a6110a1e4d9bfcde37e95663fe4292b9ebc9cda0d5057d0efbdfbcaada9158856a39075d01875b56f0e88a7e023192f64ba10750e
7
- data.tar.gz: 76d3b55b506b2b37e1a801d8e6795cc044a05ad47f008d22a9cbf83000ab8b148117e1577040484f2a22abd3de24757ca20e7a985a4f0b6e60ec1c98ea412e7c
6
+ metadata.gz: 9e38b5a5cc832448271b531dafe9c31fa9cc897274bd9e75dad2bb8bc11bbc1c10dc00a2a441aaeeb7e137d98d88aa3bdf4534d94abcb23a021b289aaf19c906
7
+ data.tar.gz: 4b56356808f786d479cc5cadcbfb769188f4c1bbdbd3bcb3255aa9f77a0ce8f2e5dc5e447c6dc1e2ec3046df1611c1e4c1977517a43182e25ad0f7073ab21798
data/README.md CHANGED
@@ -1,17 +1,23 @@
1
1
  Filigree: For more beautiful Ruby
2
2
  =================================
3
3
 
4
- Filigree is a collection of classes, modules, and functions that I found myself re-writing in each of my projects. In addition, I have thrown in a couple of other features that I've always wanted. Here are some of those features:
4
+ <div style="float: left; padding-right: 25px">
5
+ <img src="https://raw.github.com/chriswailes/filigree/master/resources/filigree_logo_large.jpg" alt="Filigree: For more beautiful Ruby" height=256 width=256>
6
+ </div>
5
7
 
6
- * Abstract classes and methods
7
- * An implementation of pattern matching
8
- * An implementation of the visitor pattern
9
- * Module for defining class methods in a mixin
10
- * Modules for configuration and command handling
11
- * Easy dynamic type checking
12
- * Small extensions to standard library classes
8
+ Filigree is a collection of classes, modules, and functions that I found myself re-writing in each of my projects. In addition, I have thrown in a couple of other features that I've always wanted. Most of these features can be used independently. Bellow is a list of many of the files and the features that each file provides:
13
9
 
14
- I'm going to go over some of the more important features below, but I won't be able to cover everything. Explore the rest of the documentation to discover additional features.
10
+ * **filigree/abstract_class.rb** - Abstract class and method implementations
11
+ * **filigree/application.rb** - A basic application framework
12
+ * **filigree/class_methods_module.rb** - Easy way to include class methods in a mixin
13
+ * **filigree/commands.rb** - Framework for defining and processing command lines
14
+ * **filigree/configuration.rb** - Framework for parsing configuration strings
15
+ * **filigree/match.rb** - An implementation of pattern matching for Ruby
16
+ * **filigree/request_file.rb** - Conditionally do something if a file can be included; great for Rakefiles
17
+ * **filigree/types.rb** - Helper functions/classes for type checking ruby code; great for FFI integration
18
+ * **filigree/visitor.rb** - Implementation of the Visitor pattern based on pattern matching library
19
+
20
+ The above is not a complete list of files provided by this gem, and the documentation bellow only covers the most important features of the library. Explore the rest of the documentation to discover additional features.
15
21
 
16
22
  Abstract Classes and Methods
17
23
  ----------------------------
@@ -130,7 +136,7 @@ match Foo.new(4, 2) do
130
136
  end
131
137
  ```
132
138
 
133
- Of particular note is the destructuring of arrays. When an array is destructured like so, `Array.(xs)`, the array is bound to `xs`. If an additional pattern is added, `Array.(x, xs)`, then `x` will hold the first element of the array and `xs` will hold the remailing characters. As more patterns are added more elements will be pulled off of the front of the array. You can match an array with a specific number of elements by using an empty array litteral: `Array.(x, [])`
139
+ Of particular note is the destructuring of arrays. When an array is destructured like so, `Array.(xs)`, the array is bound to `xs`. If an additional pattern is added, `Array.(x, xs)`, then `x` will hold the first element of the array and `xs` will hold the remaining characters. As more patterns are added more elements will be pulled off of the front of the array. You can match an array with a specific number of elements by using an empty array literal: `Array.(x, [])`
134
140
 
135
141
  Both `match` and `with` can take multiple arguments. When this happens, each object is paired up with the corresponding pattern. If they all match, then the `with` clause matches. In this way you can match against tuples.
136
142
 
@@ -184,6 +190,16 @@ mv.visit(Add.new(6, 8)) # => 14
184
190
  mv.visit(Mul.new(7, 6)) # => 42
185
191
  ```
186
192
 
193
+ The only complicated aspect of the Visitor mixin is the method used to select the order in which the patterns are tested. If patterns were tested in order of definition then a subclass of a visitor would be unable to define a more specific pattern than one defined int he parent visitor. To address this issue the most _specific_ patterns are tested first. This gets a bit complicated when it gets to destructuring patterns, but most cases are fairly simple. Pattern specificity is as follows:
194
+
195
+ 1. Literals
196
+ 2. Destructurings
197
+ 3. Regular expressions
198
+ 4. Instances
199
+ 5. Wildcard
200
+
201
+ There are special rules for destructuring and instance patterns. In both cases, a pattern for a subclass is preferred to a pattern for a superclass. Destructuring patterns have the additional rule that longer, more specific destructurings are preferred to shorter, less specific destructurings. Lastly, any pattern that has a guard expression is more specific than an otherwise equivalent expression that doesn't have a guard expression.
202
+
187
203
  Class Methods
188
204
  -------------
189
205
 
@@ -317,15 +333,6 @@ var = Foo.new(42, '42')
317
333
  var.bar = '42' # Raises a TypeError
318
334
  ```
319
335
 
320
- Array#map
321
- ---------
322
-
323
- The Array class has been monkey patched so that it takes an optional symbol argument. If it is provided, the symbol is sent to each of the objects in the array and the result is used for the new array.
324
-
325
- ```Ruby
326
- [1, 2, 3, 4].map :to_sym # => [:1, :2, :3, :4]
327
- ```
328
-
329
336
  Contributing
330
337
  ------------
331
338
 
data/lib/filigree.rb CHANGED
@@ -12,7 +12,6 @@
12
12
  # Filigree
13
13
  require 'filigree/abstract_class'
14
14
  require 'filigree/application'
15
- require 'filigree/array'
16
15
  require 'filigree/boolean'
17
16
  require 'filigree/class'
18
17
  require 'filigree/class_methods_module'
@@ -10,7 +10,6 @@
10
10
  # Standard Library
11
11
 
12
12
  # Filigree
13
- require 'filigree/array'
14
13
  require 'filigree/class_methods_module'
15
14
  require 'filigree/configuration'
16
15
 
@@ -85,7 +84,7 @@ module Filigree
85
84
  # @return [void]
86
85
  def add_command(command_obj)
87
86
  @command_list << command_obj
88
- namespace = reify_namespace(command_obj.name.split.map(:to_sym))
87
+ namespace = reify_namespace(command_obj.name.split.map(&:to_sym))
89
88
  namespace[:nil] = command_obj
90
89
  end
91
90
 
@@ -225,7 +224,7 @@ module Filigree
225
224
  comm_list = self.class.command_list
226
225
 
227
226
  sorted_comm_list = comm_list.sort { |a, b| a.name <=> b.name }
228
- max_length = comm_list.map(:name).inject(0) { |max, str| max <= str.length ? str.length : max }
227
+ max_length = comm_list.lazy.map { |opt| opt.name.length }.max
229
228
 
230
229
 
231
230
  sorted_comm_list.each do |comm|
@@ -378,9 +378,9 @@ module Filigree
378
378
  # @return [String]
379
379
  def self.to_s(options, indent = 0)
380
380
  lines = []
381
-
382
- max_long = options.inject(0) { |max, opt| max <= opt.long.length ? opt.long.length : max }
383
- max_short = options.inject(0) { |max, opt| !opt.short.nil? && max <= opt.short.length ? opt.short.length : max }
381
+
382
+ max_long = options.lazy.map { |opt| opt.long.length }.max
383
+ max_short = options.lazy.map(&:short).reject { |opt| opt.nil? }.map(&:length).max
384
384
 
385
385
  options.each do |opt|
386
386
  lines << opt.to_s(max_long, max_short, indent)
@@ -13,6 +13,7 @@ require 'singleton'
13
13
 
14
14
  # Filigree
15
15
  require 'filigree/abstract_class'
16
+ require 'filigree/class'
16
17
 
17
18
  ##########
18
19
  # Errors #
@@ -166,7 +167,32 @@ end
166
167
  #######################
167
168
 
168
169
  module Filigree
169
-
170
+
171
+ ###########
172
+ # Methods #
173
+ ###########
174
+
175
+ # Wrap non-pattern objects in pattern objects so they can all be treated
176
+ # in the same way during pattern sorting and matching.
177
+ #
178
+ # @param [Array<Object>] pattern Naked pattern object
179
+ #
180
+ # @return [Array<BasicPattern>] Wrapped pattern object
181
+ def Filigree::wrap_pattern_elements(pattern)
182
+ pattern.map do |el|
183
+ case el
184
+ when BasicPattern then el
185
+ when Class then InstancePattern.new(el)
186
+ when Regexp then RegexpPattern.new(el)
187
+ else LiteralPattern.new(el)
188
+ end
189
+ end
190
+ end
191
+
192
+ #######################
193
+ # Modules and Classes #
194
+ #######################
195
+
170
196
  # A module indicating that an object may be destructured. The including
171
197
  # class must define the `destructure` instance method, which takes one
172
198
  # argument specifying the number of pattern elements it is being matched
@@ -178,7 +204,7 @@ module Filigree
178
204
  #
179
205
  # @return [DestructuringPattern]
180
206
  def call(*pattern)
181
- DestructuringPattern.new(self, *pattern)
207
+ DestructuringPattern.new(self, Filigree::wrap_pattern_elements(pattern))
182
208
  end
183
209
  end
184
210
 
@@ -235,7 +261,9 @@ module Filigree
235
261
  # @return [void]
236
262
  def with(*pattern, &block)
237
263
  guard = if pattern.last.is_a?(Proc) then pattern.pop end
238
-
264
+
265
+ pattern = Filigree::wrap_pattern_elements(pattern)
266
+
239
267
  @patterns << (mp = OuterPattern.new(pattern, guard, block))
240
268
 
241
269
  if block
@@ -264,7 +292,18 @@ module Filigree
264
292
 
265
293
  # This class provides the basis for all match patterns.
266
294
  class BasicPattern
267
- extend AbstractClass
295
+ extend AbstractClass
296
+ include Comparable
297
+
298
+ # Base implementation of bi-directional comparison for patterns.
299
+ #
300
+ # @param [BasicPattern] other Right-hand side of the comparison
301
+ #
302
+ # @return [Integer] Value corresponding to less than, equal to, or
303
+ # greater than the right-hand side pattern.
304
+ def <=>(other)
305
+ self.weight - other.weight
306
+ end
268
307
 
269
308
  # Wraps this pattern in a {BindingPattern}, causing the object that
270
309
  # this pattern matches to be bound to this name in the with block.
@@ -273,32 +312,6 @@ module Filigree
273
312
  def as(binding_pattern)
274
313
  binding_pattern.tap { |bp| bp.pattern_elem = self }
275
314
  end
276
-
277
- # Test to see if a single object matches a single pattern, using the
278
- # given environment to store bindings.
279
- #
280
- # @param [Object] pattern_elem Object representing the pattern
281
- # @param [Object] object Object to be matched
282
- # @param [Object] env Environment in which to store bindings
283
- #
284
- # @return [Boolean] If the pattern element matched
285
- def match_pattern_element(pattern_elem, object, env)
286
- case pattern_elem
287
- when Class
288
- object.is_a?(pattern_elem)
289
-
290
- when Regexp
291
- (object.is_a?(String) and (md = pattern_elem.match(object))).tap do |match|
292
- env.send("match_data=", md) if match
293
- end
294
-
295
- when BasicPattern
296
- pattern_elem.match?(object, env)
297
-
298
- else
299
- object == pattern_elem
300
- end
301
- end
302
315
  end
303
316
 
304
317
  # A pattern that matches any object
@@ -311,28 +324,59 @@ module Filigree
311
324
  def match?(_, _)
312
325
  true
313
326
  end
327
+
328
+ def weight
329
+ 4
330
+ end
314
331
  end
315
332
 
316
333
  # An abstract class that matches only a single object to a single pattern.
317
334
  class SingleObjectPattern < BasicPattern
318
335
  extend AbstractClass
319
336
 
337
+ # @return [BasicPattern]
338
+ attr_reader :pattern_elem
339
+
320
340
  # Create a new pattern with a single element.
321
341
  #
322
342
  # @param [Object] pattern_elem Object representing the pattern
323
343
  def initialize(pattern_elem)
324
344
  @pattern_elem = pattern_elem
325
345
  end
346
+ end
347
+
348
+ # A pattern for checking to see if an object is an instance of a given
349
+ # class.
350
+ class InstancePattern < SingleObjectPattern
351
+ # Specialized version of the bi-directional comparison operator.
352
+ #
353
+ # @param [BasicPattern] other Right-hand side of the comparison
354
+ #
355
+ # @return [-1, 0, 1] Value corresponding to less than, equal to, or
356
+ # greater than the right-hand side pattern.
357
+ def <=>(other)
358
+ if other.is_a?(InstancePattern)
359
+ if self.pattern_elem == other.pattern_elem then 0
360
+ elsif self.pattern_elem.subclass_of?(other.pattern_elem) then 1
361
+ else -1
362
+ end
363
+ else
364
+ super
365
+ end
366
+ end
326
367
 
327
- # Testing the pattern only involves testing the single pattern
328
- # element.
368
+ # Test the object to see if the object is an instance of the given
369
+ # class.
329
370
  #
330
371
  # @param [Object] object Object to test pattern against
331
- # @param [Object] env Binding environment
332
372
  #
333
373
  # @return [Boolean]
334
- def match?(object, env)
335
- match_pattern_element(@pattern_elem, object, env)
374
+ def match?(object, _)
375
+ object.is_a?(@pattern_elem)
376
+ end
377
+
378
+ def weight
379
+ 3
336
380
  end
337
381
  end
338
382
 
@@ -346,22 +390,52 @@ module Filigree
346
390
  def match?(object, _)
347
391
  object == @pattern_elem
348
392
  end
393
+
394
+ def weight
395
+ 0
396
+ end
397
+ end
398
+
399
+ # A pattern that tests a string against a regular expression.
400
+ class RegexpPattern < SingleObjectPattern
401
+ # Test the object to see if it matches the wrapped regular
402
+ # expression.
403
+ #
404
+ # @param [Object] object Object to test pattern against
405
+ # @param [Object] env Binding environment
406
+ #
407
+ # @return [Boolean]
408
+ def match?(object, env)
409
+ (object.is_a?(String) and (md = @pattern_elem.match(object))).tap do |match|
410
+ env.send("match_data=", md) if match
411
+ end
412
+ end
413
+
414
+ def weight
415
+ 2
416
+ end
349
417
  end
350
418
 
351
419
  # A pattern that binds a sub-pattern's matching object to a name in the
352
420
  # binding environment.
353
421
  class BindingPattern < SingleObjectPattern
354
- attr_accessor :pattern_elem
422
+
423
+ attr_writer :pattern_elem
355
424
 
356
425
  # Create a new binding pattern.
357
426
  #
358
427
  # @param [Symbol] name Name to bind to
359
428
  # @param [Object] pattern_elem Sub-pattern
360
- def initialize(name, pattern_elem = nil)
429
+ def initialize(name, pattern_elem = WildcardPattern.instance)
361
430
  @name = name
362
431
  super(pattern_elem)
363
432
  end
364
433
 
434
+ # Overridden method to prevent binding BindingPattern objects.
435
+ def as(_, _)
436
+ raise 'Binding a BindingPattern is not allowed.'
437
+ end
438
+
365
439
  # Test the object for equality to the pattern element. Binds the
366
440
  # object to the binding pattern's name if it does match.
367
441
  #
@@ -370,9 +444,11 @@ module Filigree
370
444
  #
371
445
  # @return [Boolean]
372
446
  def match?(object, env)
373
- (@pattern_elem.nil? or super).tap do |match|
374
- env.send("#{@name}=", object) if match
375
- end
447
+ @pattern_elem.match?(object, env).tap { |match| env.send("#{@name}=", object) if match }
448
+ end
449
+
450
+ def weight
451
+ @pattern_elem.weight
376
452
  end
377
453
  end
378
454
 
@@ -380,6 +456,9 @@ module Filigree
380
456
  class MultipleObjectPattern < BasicPattern
381
457
  extend AbstractClass
382
458
 
459
+ # @return [Array<BasicPattern>]
460
+ attr_reader :pattern
461
+
383
462
  # Create a new pattern with multiple elements.
384
463
  #
385
464
  # @param [Array<Object>] pattern Array of pattern elements
@@ -387,6 +466,21 @@ module Filigree
387
466
  @pattern = pattern
388
467
  end
389
468
 
469
+ # A wrapper method to sort MultipleObjectPattern objects by their
470
+ # arity.
471
+ #
472
+ # @param [BasicPattern] other Right-hand side of the comparison
473
+ #
474
+ # @return [Integer] Value corresponding to less than, equal to, or
475
+ # greater than the right-hand side pattern.
476
+ def base_compare(other)
477
+ if self.pattern.length == other.pattern.length
478
+ yield
479
+ else
480
+ self.pattern.length - other.pattern.length
481
+ end
482
+ end
483
+
390
484
  # Test multiple objects against multiple pattern elements.
391
485
  #
392
486
  # @param [Object] objects Object to test pattern against
@@ -395,7 +489,7 @@ module Filigree
395
489
  def match?(objects, env)
396
490
  if objects.length == @pattern.length
397
491
  @pattern.zip(objects).each do |pattern_elem, object|
398
- return false unless match_pattern_element(pattern_elem, object, env)
492
+ return false unless pattern_elem.match?(object, env)
399
493
  end
400
494
 
401
495
  true
@@ -406,9 +500,31 @@ module Filigree
406
500
  end
407
501
  end
408
502
 
409
- # The that contains all of the pattern elements passed to a with clause.
503
+ # The class that contains all of the pattern elements passed to a with clause.
410
504
  class OuterPattern < MultipleObjectPattern
411
505
  attr_writer :block
506
+ attr_reader :guard
507
+
508
+ # Specialized version of the bi-directional comparison operator.
509
+ #
510
+ # @param [BasicPattern] other Right-hand side of the comparison
511
+ #
512
+ # @return [-1, 0, 1] Value corresponding to less than, equal to, or
513
+ # greater than the right-hand side pattern.
514
+ def <=>(other)
515
+ base_compare(other) do
516
+ comp_res =
517
+ self.pattern.zip(other.pattern).inject(0) do |total, pair|
518
+ total + (pair.first <=> pair.last)
519
+ end <=> 0
520
+
521
+ if comp_res == 0
522
+ self.guard ? (other.guard ? 0 : 1) : (other.guard ? -1 : comp_res)
523
+ else
524
+ comp_res
525
+ end
526
+ end
527
+ end
412
528
 
413
529
  # Create a new outer pattern with the given pattern elements, guard,
414
530
  # and block.
@@ -444,11 +560,39 @@ module Filigree
444
560
  # A pattern that matches an instance of a class and destructures it so
445
561
  # that the values contained by the object may be matched upon.
446
562
  class DestructuringPattern < MultipleObjectPattern
563
+
564
+ # @return [Class]
565
+ attr_reader :klass
566
+
567
+ # Specialized version of the bi-directional comparison operator.
568
+ #
569
+ # @param [BasicPattern] other Right-hand side of the comparison
570
+ #
571
+ # @return [Integer] Value corresponding to less than, equal to, or
572
+ # greater than the right-hand side pattern.
573
+ def <=>(other)
574
+ if other.is_a?(DestructuringPattern)
575
+ if self.klass == other.klass
576
+ base_compare(other) do
577
+ self.pattern.zip(other.pattern).inject(0) do |total, pair|
578
+ total + (pair.first <=> pair.last)
579
+ end / self.pattern.length
580
+ end
581
+
582
+ elsif self.klass.subclass_of?(other.klass) then 1
583
+ else -1
584
+ end
585
+
586
+ else
587
+ super
588
+ end
589
+ end
590
+
447
591
  # Create a new destructuring pattern.
448
592
  #
449
593
  # @param [Class] klass Class to match instances of. It must be destructurable.
450
594
  # @param [Object] pattern Pattern elements to use in matching the object's values
451
- def initialize(klass, *pattern)
595
+ def initialize(klass, pattern)
452
596
  @klass = klass
453
597
  super(pattern)
454
598
  end
@@ -464,6 +608,10 @@ module Filigree
464
608
  def match?(object, env)
465
609
  object.is_a?(@klass) and super(object.destructure(@pattern.length), env)
466
610
  end
611
+
612
+ def weight
613
+ 1
614
+ end
467
615
  end
468
616
  end
469
617
 
@@ -494,6 +642,16 @@ class Class
494
642
  #
495
643
  # @param [BindingPattern] binding_pattern Name to bind the instance to
496
644
  def as(binding_pattern)
497
- binding_pattern.tap { |bp| bp.pattern_elem = self }
645
+ binding_pattern.tap { |bp| bp.pattern_elem = Filigree::InstancePattern.new(self) }
646
+ end
647
+ end
648
+
649
+ class Regexp
650
+ # Causes a string matching the regular expression to be bound the the
651
+ # given name.
652
+ #
653
+ # @param [BindingPattern] binding_pattern Name to bind the instance to
654
+ def as(binding_pattern)
655
+ binding_pattern.tap { |bp| bp.pattern_elem = Filigree::RegexpPattern.new(self) }
498
656
  end
499
657
  end
@@ -4,5 +4,5 @@
4
4
  # Description: This file specifies the version number of Filigree.
5
5
 
6
6
  module Filigree
7
- VERSION = '0.1.2'
7
+ VERSION = '0.2.0'
8
8
  end
@@ -88,11 +88,38 @@ module Filigree
88
88
  LiteralPattern.new(obj)
89
89
  end
90
90
 
91
+ # Inserts a new pattern in the appropriate place in the patterns
92
+ # list.
93
+ #
94
+ # @param [OuterPattern] new_pat New pattern to add
95
+ #
96
+ # @return [void]
97
+ def add_pattern(new_pat)
98
+ @patterns.each_with_index do |old_pat, index|
99
+ if new_pat > old_pat
100
+ @patterns.insert(index, new_pat)
101
+ return
102
+ end
103
+ end
104
+
105
+ @patterns << new_pat
106
+ end
107
+
108
+ # A callback used to pass patterns declared in a parent class to
109
+ # a subclass.
110
+ #
111
+ # @param [Class] klass Subclass
112
+ #
113
+ # @return [void]
114
+ def inherited(klass)
115
+ klass.install_icvars(@patterns.clone)
116
+ end
117
+
91
118
  # Install the instance class variables in the including class.
92
119
  #
93
120
  # @return [void]
94
- def install_icvars
95
- @patterns = Array.new
121
+ def install_icvars(inherited_patterns = Array.new)
122
+ @patterns = inherited_patterns
96
123
  @deferred = Array.new
97
124
  end
98
125
 
@@ -106,8 +133,9 @@ module Filigree
106
133
  # @return [void]
107
134
  def on(*pattern, &block)
108
135
  guard = if pattern.last.is_a?(Proc) then pattern.pop end
109
-
110
- @patterns << (mp = OuterPattern.new(pattern, guard, block))
136
+
137
+ pattern = Filigree::wrap_pattern_elements(pattern)
138
+ add_pattern (mp = OuterPattern.new(pattern, guard, block))
111
139
 
112
140
  if block
113
141
  @deferred.each { |pattern| pattern.block = block }
data/test/tc_visitor.rb CHANGED
@@ -157,9 +157,32 @@ class VisitorTester < Minitest::Test
157
157
  end
158
158
  end
159
159
 
160
+ class NumericVisitor
161
+ include Filigree::Visitor
162
+
163
+ on Numeric do |n|
164
+ "Numeric: #{n}"
165
+ end
166
+ end
167
+
168
+ class SubclassVisitor < NumericVisitor
169
+ on Integer do |i|
170
+ "Integer: #{i}"
171
+ end
172
+ end
173
+
160
174
  def setup
161
175
  end
162
176
 
177
+ def test_inheritance
178
+ sv = SubclassVisitor.new
179
+
180
+ assert_equal "Numeric: 3.1415296", sv.visit(3.1415296)
181
+ assert_equal "Integer: 42", sv.visit(42)
182
+
183
+ assert_raises(MatchError) { sv.visit(:hoopy) }
184
+ end
185
+
163
186
  def test_simple_visitor
164
187
  sv = SimpleVisitor.new
165
188
 
data/test/ts_filigree.rb CHANGED
@@ -20,7 +20,6 @@ end
20
20
  # Test Cases
21
21
  require 'tc_abstract_class'
22
22
  require 'tc_application'
23
- require 'tc_array'
24
23
  require 'tc_boolean'
25
24
  require 'tc_class'
26
25
  require 'tc_class_methods_module'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: filigree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wailes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-26 00:00:00.000000000 Z
11
+ date: 2014-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -175,35 +175,33 @@ files:
175
175
  - AUTHORS
176
176
  - README.md
177
177
  - Rakefile
178
- - lib/filigree/request_file.rb
179
- - lib/filigree/class_methods_module.rb
180
- - lib/filigree/visitor.rb
181
178
  - lib/filigree/types.rb
182
- - lib/filigree/object.rb
183
- - lib/filigree/string.rb
184
- - lib/filigree/commands.rb
185
- - lib/filigree/abstract_class.rb
186
179
  - lib/filigree/boolean.rb
180
+ - lib/filigree/match.rb
187
181
  - lib/filigree/application.rb
182
+ - lib/filigree/abstract_class.rb
183
+ - lib/filigree/class.rb
184
+ - lib/filigree/string.rb
188
185
  - lib/filigree/version.rb
189
186
  - lib/filigree/configuration.rb
190
- - lib/filigree/array.rb
191
- - lib/filigree/match.rb
192
- - lib/filigree/class.rb
187
+ - lib/filigree/visitor.rb
188
+ - lib/filigree/object.rb
189
+ - lib/filigree/commands.rb
190
+ - lib/filigree/request_file.rb
191
+ - lib/filigree/class_methods_module.rb
193
192
  - lib/filigree.rb
194
- - test/tc_commands.rb
195
- - test/tc_array.rb
193
+ - test/tc_boolean.rb
194
+ - test/tc_object.rb
196
195
  - test/tc_types.rb
197
- - test/tc_class.rb
196
+ - test/tc_configuration.rb
197
+ - test/tc_commands.rb
198
198
  - test/tc_string.rb
199
- - test/tc_application.rb
200
- - test/tc_match.rb
201
199
  - test/tc_abstract_class.rb
202
- - test/tc_object.rb
203
- - test/tc_class_methods_module.rb
204
- - test/tc_configuration.rb
205
- - test/tc_boolean.rb
206
200
  - test/tc_visitor.rb
201
+ - test/tc_class_methods_module.rb
202
+ - test/tc_match.rb
203
+ - test/tc_class.rb
204
+ - test/tc_application.rb
207
205
  - test/ts_filigree.rb
208
206
  homepage: https://github.com/chriswailes/filigree
209
207
  licenses:
@@ -230,18 +228,17 @@ signing_key:
230
228
  specification_version: 4
231
229
  summary: Extra functionality for Ruby.
232
230
  test_files:
233
- - test/tc_commands.rb
234
- - test/tc_array.rb
231
+ - test/tc_boolean.rb
232
+ - test/tc_object.rb
235
233
  - test/tc_types.rb
236
- - test/tc_class.rb
234
+ - test/tc_configuration.rb
235
+ - test/tc_commands.rb
237
236
  - test/tc_string.rb
238
- - test/tc_application.rb
239
- - test/tc_match.rb
240
237
  - test/tc_abstract_class.rb
241
- - test/tc_object.rb
242
- - test/tc_class_methods_module.rb
243
- - test/tc_configuration.rb
244
- - test/tc_boolean.rb
245
238
  - test/tc_visitor.rb
239
+ - test/tc_class_methods_module.rb
240
+ - test/tc_match.rb
241
+ - test/tc_class.rb
242
+ - test/tc_application.rb
246
243
  - test/ts_filigree.rb
247
244
  has_rdoc:
@@ -1,35 +0,0 @@
1
- # Author: Chris Wailes <chris.wailes@gmail.com>
2
- # Project: Filigree
3
- # Date: 2013/05/04
4
- # Description: Additional features for Arrays.
5
-
6
- ############
7
- # Requires #
8
- ############
9
-
10
- # Standard Library
11
-
12
- # Filigree
13
-
14
- #######################
15
- # Classes and Modules #
16
- #######################
17
-
18
- class Array
19
- alias :aliased_map :map
20
-
21
- # Map now takes an optional symbol argument. If a symbol is provided the
22
- # specified method is invoked on each of the objects in the array.
23
- #
24
- # @param [Symbol] method Method to be invoked on the array elements.
25
- # @param [Proc] block Normal Array#each block.
26
- #
27
- # @return [Array<Object>]
28
- def map(method = nil, &block)
29
- if method
30
- self.aliased_map { |obj| obj.send(method) }
31
- else
32
- self.aliased_map(&block)
33
- end
34
- end
35
- end
data/test/tc_array.rb DELETED
@@ -1,28 +0,0 @@
1
- # Author: Chris Wailes <chris.wailes@gmail.com>
2
- # Project: Filigree
3
- # Date: 2014/02/05
4
- # Description: Test cases for the Array extensions.
5
-
6
- ############
7
- # Requires #
8
- ############
9
-
10
- # Gems
11
- require 'minitest/autorun'
12
-
13
- # Filigree
14
- require 'filigree/array'
15
-
16
- #######################
17
- # Classes and Modules #
18
- #######################
19
-
20
- class ArrayTester < Minitest::Test
21
-
22
- def setup
23
- end
24
-
25
- def test_map_with_method
26
- assert_equal [:cat, :dog, :cow], ['cat', 'dog', 'cow'].map(:to_sym)
27
- end
28
- end