modular_tree 0.0.1 → 0.0.3
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.
- checksums.yaml +4 -4
- data/lib/modular_tree/algorithms.rb +12 -2
- data/lib/modular_tree/filter.rb +9 -6
- data/lib/modular_tree/implementations.rb +51 -1
- data/lib/modular_tree/properties.rb +4 -0
- data/lib/modular_tree/version.rb +1 -1
- data/lib/modular_tree.rb +2 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b145f3b7daeb0bddc2a2415e3a98d6d6232d95afeca8147908bffa2089ff412
|
4
|
+
data.tar.gz: 68271887a655b0196e5f9819f72ee80ca9e853c15568ab48cc1d7e15c4a29d22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9a39254ef102c23dbba9445b5b95b3d925d0954ef28de91107318c24ce9c450dd1fc2612cae18fc2c4033314bcd85b14a7126eb09e01daee076e380b05fe54c
|
7
|
+
data.tar.gz: 3b84c591c7816199835041074b6fb8b9506c5b85b438000045ce4d21627559835edeadf0336ca6635d76cef563082254318a1cf13d15342c431f407f51868615
|
@@ -63,11 +63,21 @@ module Tree
|
|
63
63
|
# Implementation of Enumerable#each extended with filters. The block is
|
64
64
|
# called with value, key, and parent as arguments (it may choose to
|
65
65
|
# ignore key and/or parent). Returns an enumerator of values without a block
|
66
|
-
def each(*filter, this: true, &block) = common_each(*filter, :value, :
|
66
|
+
def each(*filter, this: true, &block) = common_each(*filter, :value, :do_each_preorder, this, &block)
|
67
|
+
|
68
|
+
# Implementation of Enumerable#select extended with a single filter. As
|
69
|
+
# #each, the block is called with value, key, and parent arguments
|
70
|
+
def select(filter = nil, this: true, &block)
|
71
|
+
if block_given?
|
72
|
+
each(block, true, this: this).to_a
|
73
|
+
else
|
74
|
+
each(filter || true, true, this: this)
|
75
|
+
end
|
76
|
+
end
|
67
77
|
|
68
78
|
# Like #each but the block is called with node, key, and parent instead of
|
69
79
|
# value, key, and parent
|
70
|
-
def nodes(*filter, this: true, &block) = common_each(*filter, :node, :
|
80
|
+
def nodes(*filter, this: true, &block) = common_each(*filter, :node, :do_each_preorder, this, &block)
|
71
81
|
|
72
82
|
# Pre-order enumerator of selected nodes. Same as #each without a block
|
73
83
|
def preorder(*filter, this: true) = each(*filter, this: this)
|
data/lib/modular_tree/filter.rb
CHANGED
@@ -6,9 +6,9 @@ module Tree
|
|
6
6
|
# traverse expression decides if the child nodes should be traversed
|
7
7
|
# recursively
|
8
8
|
#
|
9
|
-
# The expressions can be a Proc, Symbol, or an array of classes. In
|
10
|
-
# addition, +select+ can
|
11
|
-
#
|
9
|
+
# The expressions can be a Proc, Symbol, Class, or an array of classes. In
|
10
|
+
# addition, +select+ can be true, and +traverse+ can be true, false, or
|
11
|
+
# nil. These values have special meanings:
|
12
12
|
#
|
13
13
|
# when +select+ is
|
14
14
|
# true Select always. This is the default
|
@@ -17,14 +17,17 @@ module Tree
|
|
17
17
|
# true Traverse always. This is the default
|
18
18
|
# false Traverse only if select didn't match
|
19
19
|
# nil Expects +select+ to return a two-tuple of booleans. Can't be
|
20
|
-
# used when +select+ is true
|
20
|
+
# used when +select+ is true. TODO: Explain
|
21
21
|
#
|
22
22
|
# If the expression is a Proc object, it will be called with the current
|
23
23
|
# node as argument. If the return value is true, the node is
|
24
24
|
# selected/traversed and skipped otherwise. If the expression is a method
|
25
25
|
# name (Symbol), the method will be called on each node with no arguments.
|
26
|
-
# It is not an error if the method doesn't exists
|
27
|
-
# selected/traversed
|
26
|
+
# It is not an error if the method doesn't exists on the a given node but
|
27
|
+
# the node is not selected/traversed
|
28
|
+
#
|
29
|
+
# If the expression is a class or an array of classes, a given node matches
|
30
|
+
# if it is an instance of one of the classes or any subclass
|
28
31
|
#
|
29
32
|
# Filters should not have side-effects because they can be used in
|
30
33
|
# enumerators that doesn't execute the filter unless the enumerator is
|
@@ -69,7 +69,7 @@ module Tree
|
|
69
69
|
|
70
70
|
def node = array
|
71
71
|
def this = array.first
|
72
|
-
def value = array.first
|
72
|
+
def value = array.first # FIXME What is this? It is a problem several places
|
73
73
|
|
74
74
|
attr_accessor :array
|
75
75
|
|
@@ -167,6 +167,33 @@ module Tree
|
|
167
167
|
|
168
168
|
def each_child(&block) = @children.map(&block)
|
169
169
|
def attach(child) = @children << child
|
170
|
+
|
171
|
+
# Can be used with any array implementation
|
172
|
+
def insert(where, child) = insert_append(:insert, where, child)
|
173
|
+
def append(where, child) = insert_append(:append, where, child)
|
174
|
+
|
175
|
+
def replace(where, *children)
|
176
|
+
children = Array(children).flatten
|
177
|
+
case where
|
178
|
+
when Integer
|
179
|
+
subject = @children[where] or raise ArgumentError
|
180
|
+
index = where
|
181
|
+
else
|
182
|
+
subject = where
|
183
|
+
index = @children.index(where) or raise ArgumentError
|
184
|
+
end
|
185
|
+
@children = @children[0...index] + children + @children[index + 1..-1]
|
186
|
+
subject
|
187
|
+
end
|
188
|
+
|
189
|
+
protected
|
190
|
+
def insert_append(which, where, child)
|
191
|
+
if !where.is_a?(Integer)
|
192
|
+
where = @children.index(where) or raise ArgumentError, "Can't find object"
|
193
|
+
end
|
194
|
+
where += 1 if which == :append
|
195
|
+
@children.insert(where, child)
|
196
|
+
end
|
170
197
|
end
|
171
198
|
|
172
199
|
module InternalChildrenHashImplementation
|
@@ -198,5 +225,28 @@ module Tree
|
|
198
225
|
child.send(:parent=, self)
|
199
226
|
end
|
200
227
|
end
|
228
|
+
|
229
|
+
module InternalParentChildArrayImplementation
|
230
|
+
include InternalParentChildImplementation
|
231
|
+
|
232
|
+
def insert(where, child)
|
233
|
+
super
|
234
|
+
child.send(:parent=, self)
|
235
|
+
end
|
236
|
+
|
237
|
+
def append(where, child)
|
238
|
+
super
|
239
|
+
child.send(:parent=, self)
|
240
|
+
end
|
241
|
+
|
242
|
+
# Requires that Child classes already has defined this
|
243
|
+
def replace(where, *children)
|
244
|
+
children = Array(children).flatten
|
245
|
+
subject = super(where, children)
|
246
|
+
subject.send(:parent=, nil)
|
247
|
+
children.each { |child| child.send(:parent=, self) }
|
248
|
+
subject
|
249
|
+
end
|
250
|
+
end
|
201
251
|
end
|
202
252
|
|
data/lib/modular_tree/version.rb
CHANGED
data/lib/modular_tree.rb
CHANGED
@@ -39,9 +39,10 @@ module Tree
|
|
39
39
|
class ArrayTree < AbstractTree # Aka. SetTree aka. Tree
|
40
40
|
include InternalParentImplementation
|
41
41
|
include InternalChildrenArrayImplementation
|
42
|
-
include
|
42
|
+
include InternalParentChildArrayImplementation
|
43
43
|
include UpTreeAlgorithms
|
44
44
|
include DownTreeAlgorithms
|
45
|
+
include DownTreeFilteredAlgorithms
|
45
46
|
|
46
47
|
def self.filter(*args) = DownTreeAlgorithms.filter(*args)
|
47
48
|
end
|