fzip 0.1.0 → 0.2.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.
- checksums.yaml +8 -8
- data/.gitignore +1 -0
- data/fzip.gemspec +1 -1
- data/lib/fzip/adapter.rb +8 -0
- data/lib/fzip/version.rb +1 -1
- data/lib/fzip/zipper.rb +65 -9
- data/spec/fzip_spec.rb +1 -3
- data/spec/next_spec.rb +49 -0
- data/spec/remove_spec.rb +77 -0
- data/spec/spec_helper.rb +3 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZDhiOWFhY2M0MTBiNGZiZjRjZThiYmE4OTg4ZTc3OGZlODkzZjA0ZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MzE5MWUwYjVjNTU0YmFjZmE1MjNkZjdiMDBiZWI2MDc3OWE2MWVjZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODBiYmZjNTE2NzAzNmQwY2JkMGU0Njk3MTAyYTMxOTY0ZTJkYzQ1MWE2YWEx
|
10
|
+
NjQzZjU1ZTE0Mjg2ZjE2MGY5Yjc0Yjk3YzhjNjEyNWQ2MmRhZGI3NmMxYWU5
|
11
|
+
NDI2ODBmZjUzYjI3NDczZjczYzg1NmQxM2U4OTkzZjJmZjNhMDY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YjM4NzdhNjFkNThkYWUwNTMxMjVlMDBhMmM3N2NkMTRhN2YxYjM3M2MyMDAy
|
14
|
+
N2M0NTVhMDdkZDdlNjNkZDEwMGJkOTY2MTZhMWJhYzkyYmVlMGRlNjg0OTE3
|
15
|
+
ZTY5YzQxZmQwYWYyZGM5YTc4ZDM2ZjgyZjg3YjM2YzA4MmU1NWY=
|
data/.gitignore
CHANGED
data/fzip.gemspec
CHANGED
@@ -2,7 +2,7 @@ require File.expand_path('../lib/fzip/version', __FILE__)
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
4
|
gem.name = 'fzip'
|
5
|
-
gem.version =
|
5
|
+
gem.version = Fzip::VERSION
|
6
6
|
gem.authors = [ 'Arne Brasseur' ]
|
7
7
|
gem.email = [ 'arne@arnebrasseur.net' ]
|
8
8
|
gem.description = 'Functional zipper class'
|
data/lib/fzip/adapter.rb
CHANGED
@@ -1,11 +1,19 @@
|
|
1
1
|
module FZip
|
2
2
|
class Adapter
|
3
|
+
# Can the node have children
|
4
|
+
#
|
5
|
+
# Returns true if the node can have even if it currently doesn't.
|
3
6
|
def branch?(node)
|
4
7
|
end
|
5
8
|
|
9
|
+
# The children of a node
|
10
|
+
#
|
11
|
+
# Return an array, or an object that responds to first, drop and +
|
6
12
|
def children(node)
|
7
13
|
end
|
8
14
|
|
15
|
+
# Given a node and an array of children, returns a new branch node of the
|
16
|
+
# same type with the supplied children.
|
9
17
|
def make_node(node, children)
|
10
18
|
end
|
11
19
|
end
|
data/lib/fzip/version.rb
CHANGED
data/lib/fzip/zipper.rb
CHANGED
@@ -1,14 +1,22 @@
|
|
1
1
|
module Fzip
|
2
2
|
class Zipper
|
3
|
-
attr_reader :adapter
|
3
|
+
attr_reader :adapter
|
4
|
+
attr_reader :parent
|
5
|
+
attr_reader :path
|
6
|
+
attr_reader :node
|
7
|
+
attr_reader :lefts
|
8
|
+
attr_reader :rights
|
9
|
+
attr_reader :at_end
|
4
10
|
|
5
11
|
def initialize(adapter, node, lefts = nil, path = nil, parent = nil, rights = nil, changed = false, at_end = false)
|
6
12
|
@adapter = adapter
|
13
|
+
|
7
14
|
@node = node
|
8
15
|
@lefts = lefts
|
9
|
-
@path = path
|
10
|
-
@parent = parent
|
11
16
|
@rights = rights
|
17
|
+
|
18
|
+
@path = path # Array[Node]
|
19
|
+
@parent = parent # Zipper
|
12
20
|
@changed = changed
|
13
21
|
@at_end = at_end
|
14
22
|
end
|
@@ -48,7 +56,7 @@ module Fzip
|
|
48
56
|
end
|
49
57
|
|
50
58
|
def down
|
51
|
-
if branch? && children
|
59
|
+
if branch? && children.any?
|
52
60
|
new(
|
53
61
|
node: children.first,
|
54
62
|
lefts: [],
|
@@ -64,7 +72,7 @@ module Fzip
|
|
64
72
|
return parent unless changed?
|
65
73
|
parent_path = path.drop(1)
|
66
74
|
new(
|
67
|
-
node: make_node(node, lefts + [node] + rights),
|
75
|
+
node: make_node(parent.node, lefts + [node] + rights),
|
68
76
|
lefts: parent.lefts,
|
69
77
|
path: parent_path.empty? ? nil : parent_path,
|
70
78
|
parent: parent.parent,
|
@@ -88,7 +96,14 @@ module Fzip
|
|
88
96
|
end
|
89
97
|
end
|
90
98
|
|
91
|
-
|
99
|
+
def rightmost
|
100
|
+
return self unless path && rights && !rights.empty?
|
101
|
+
new(
|
102
|
+
node: rights.last,
|
103
|
+
lefts: (lefts + [node] + rights)[0..-2],
|
104
|
+
rights: []
|
105
|
+
)
|
106
|
+
end
|
92
107
|
|
93
108
|
def left
|
94
109
|
if path && lefts && !lefts.empty?
|
@@ -100,7 +115,14 @@ module Fzip
|
|
100
115
|
end
|
101
116
|
end
|
102
117
|
|
103
|
-
|
118
|
+
def leftmost
|
119
|
+
return self unless path && lefts && !lefts.empty?
|
120
|
+
new(
|
121
|
+
node: lefts.first,
|
122
|
+
lefts: [],
|
123
|
+
rights: (lefts + [node] + rights).drop(1)
|
124
|
+
)
|
125
|
+
end
|
104
126
|
|
105
127
|
def insert_left(item)
|
106
128
|
raise "insert at top" unless path
|
@@ -152,9 +174,38 @@ module Fzip
|
|
152
174
|
backtrack.(self)
|
153
175
|
end
|
154
176
|
|
155
|
-
|
177
|
+
def prev
|
178
|
+
return up unless loc = left
|
179
|
+
loop do
|
180
|
+
if child = loc.branch? && loc.down
|
181
|
+
loc = child.rightmost
|
182
|
+
else
|
183
|
+
return loc
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
156
187
|
|
157
|
-
#
|
188
|
+
# Removes the node at loc, returning the loc that would have preceded
|
189
|
+
# it in a depth-first walk.
|
190
|
+
def remove
|
191
|
+
raise "Remove at top" unless path
|
192
|
+
if lefts.empty?
|
193
|
+
parent.new(
|
194
|
+
node: make_node(parent.node, rights),
|
195
|
+
changed: true
|
196
|
+
)
|
197
|
+
else
|
198
|
+
loc = new(
|
199
|
+
node: lefts.first,
|
200
|
+
lefts: lefts.drop(1),
|
201
|
+
changed: true
|
202
|
+
)
|
203
|
+
loop do
|
204
|
+
return loc unless child = loc.branch? && loc.down
|
205
|
+
loc = child.rightmost
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
158
209
|
|
159
210
|
def each
|
160
211
|
return to_enum unless block_given?
|
@@ -165,3 +216,8 @@ module Fzip
|
|
165
216
|
end
|
166
217
|
end
|
167
218
|
end
|
219
|
+
|
220
|
+
# Notes on the port from zip.clj :
|
221
|
+
# Gave these variables a different name
|
222
|
+
# pnodes => path
|
223
|
+
# ppath => parent
|
data/spec/fzip_spec.rb
CHANGED
data/spec/next_spec.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fzip::Zipper, 'next' do
|
4
|
+
let(:tree) {
|
5
|
+
[
|
6
|
+
['x', '+', 'y'],
|
7
|
+
['a', '*', 'b']
|
8
|
+
]
|
9
|
+
}
|
10
|
+
let(:zipper) { Fzip.array(tree) }
|
11
|
+
|
12
|
+
let(:sequence) {
|
13
|
+
[
|
14
|
+
tree,
|
15
|
+
['x', '+', 'y'],
|
16
|
+
'x',
|
17
|
+
'+',
|
18
|
+
'y',
|
19
|
+
['a', '*', 'b'],
|
20
|
+
'a',
|
21
|
+
'*',
|
22
|
+
'b'
|
23
|
+
]
|
24
|
+
}
|
25
|
+
|
26
|
+
it 'should go depth first' do
|
27
|
+
sequence.each.with_index do |n, idx|
|
28
|
+
nth = (0...idx).inject(zipper) {|z| z.next}
|
29
|
+
expect(nth.node).to eq n
|
30
|
+
|
31
|
+
p nth.node
|
32
|
+
sequence.first(idx+1).reverse.each.with_index do |p, pidx|
|
33
|
+
puts " => #{p.inspect}"
|
34
|
+
pth = (0...pidx).inject(nth) {|n| n.prev}
|
35
|
+
expect(pth.node).to eq p
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should go to the end' do
|
41
|
+
z = zipper
|
42
|
+
9.times do
|
43
|
+
expect(z.end?).to be_false
|
44
|
+
z = z.next
|
45
|
+
end
|
46
|
+
expect(z.end?).to be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/spec/remove_spec.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fzip::Zipper, 'remove' do
|
4
|
+
let(:tree) {
|
5
|
+
[
|
6
|
+
['x', '+', 'y'],
|
7
|
+
['a', '*', 'b']
|
8
|
+
]
|
9
|
+
}
|
10
|
+
|
11
|
+
let(:zipper) { Fzip.array(tree) }
|
12
|
+
|
13
|
+
context 'when removing the top node' do
|
14
|
+
it 'should raise an exception' do
|
15
|
+
expect { zipper.remove }.to raise_error
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when removing a node that has a left sibling' do
|
20
|
+
let(:zipper) { super().down.down.right }
|
21
|
+
|
22
|
+
it 'should remove the node' do
|
23
|
+
expect(zipper.remove.root).to eq [
|
24
|
+
['x', 'y'],
|
25
|
+
['a', '*', 'b']
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should return the zipper pointing to the left sibling' do
|
30
|
+
expect(zipper.remove.node).to eq 'x'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'without left siblings' do
|
35
|
+
let(:zipper) { super().down.down }
|
36
|
+
|
37
|
+
it 'should remove the node' do
|
38
|
+
expect(zipper.remove.root).to eq [
|
39
|
+
[ '+', 'y'],
|
40
|
+
['a', '*', 'b']
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should point to the parent' do
|
45
|
+
expect(zipper.remove.node).to eq [ '+', 'y' ]
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'without right siblings' do
|
49
|
+
let(:tree) {
|
50
|
+
[
|
51
|
+
[ 'z' ]
|
52
|
+
]
|
53
|
+
}
|
54
|
+
|
55
|
+
it 'should remove the node' do
|
56
|
+
expect(zipper.remove.root).to eq [ [] ]
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should point to the parent node' do
|
60
|
+
expect(zipper.remove.node).to eq []
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'with left cousins' do
|
66
|
+
let(:zipper) { super().down.right }
|
67
|
+
|
68
|
+
it 'should remove the node' do
|
69
|
+
expect(zipper.remove.root).to eq [ ['x', '+', 'y'] ]
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should point to the rightmost left cousin' do
|
73
|
+
expect(zipper.remove.root).to eq [ ['x', '+', 'y'] ]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fzip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arne Brasseur
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
prerelease: false
|
@@ -57,6 +57,9 @@ files:
|
|
57
57
|
- lib/fzip/version.rb
|
58
58
|
- lib/fzip/zipper.rb
|
59
59
|
- spec/fzip_spec.rb
|
60
|
+
- spec/next_spec.rb
|
61
|
+
- spec/remove_spec.rb
|
62
|
+
- spec/spec_helper.rb
|
60
63
|
homepage: https://github.com/plexus/fzip
|
61
64
|
licenses:
|
62
65
|
- MIT
|
@@ -83,3 +86,6 @@ specification_version: 4
|
|
83
86
|
summary: Functional zipper class
|
84
87
|
test_files:
|
85
88
|
- spec/fzip_spec.rb
|
89
|
+
- spec/next_spec.rb
|
90
|
+
- spec/remove_spec.rb
|
91
|
+
- spec/spec_helper.rb
|