metaractor-sycamore 0.4.2 → 0.4.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/Gemfile +4 -4
- data/Rakefile +13 -14
- data/VERSION +1 -1
- data/lib/sycamore/absence.rb +9 -12
- data/lib/sycamore/exceptions.rb +5 -5
- data/lib/sycamore/extension/nothing.rb +1 -1
- data/lib/sycamore/extension/path.rb +1 -1
- data/lib/sycamore/extension/tree.rb +1 -1
- data/lib/sycamore/extension.rb +2 -2
- data/lib/sycamore/nothing.rb +5 -10
- data/lib/sycamore/path.rb +25 -27
- data/lib/sycamore/path_root.rb +5 -5
- data/lib/sycamore/stree.rb +1 -1
- data/lib/sycamore/tree.rb +146 -146
- data/lib/sycamore/version.rb +13 -7
- data/lib/sycamore.rb +7 -7
- data/support/doctest_helper.rb +2 -2
- data/sycamore.gemspec +20 -21
- 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: ae5565f1e3e26149ac616264c7f80814ec43d0402af467d3bd39a0a95a242007
|
4
|
+
data.tar.gz: 6ac8b42b9cbfd6b1c2bbb32bb5415ca0f099d40c3cced190e264297f215414ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31278db416f78913b21d63f384b5a02e195d3d47ceb6a91a847fd0489b99c7164bfc7c0629e046eabe8ee629a3de7006c684da9fd8f7e32e3cdfd86b3bb4169a
|
7
|
+
data.tar.gz: 1e2e022767207c83f0fd3da132a11e67f9dcc866140ac3751e1624b737a994a0c2e87856363b95ae0d84033b531f35a6d86533537f86df58822abf89714ce223
|
data/Gemfile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
group :debug do
|
6
|
-
gem
|
7
|
-
gem
|
6
|
+
gem "guard-rspec"
|
7
|
+
gem "pry"
|
8
8
|
end
|
9
9
|
|
10
10
|
group :test do
|
11
|
-
gem
|
11
|
+
gem "coveralls", require: false, platform: :mri
|
12
12
|
end
|
data/Rakefile
CHANGED
@@ -1,36 +1,35 @@
|
|
1
|
-
require
|
1
|
+
require "bundler/gem_tasks"
|
2
2
|
|
3
3
|
begin
|
4
|
-
require
|
4
|
+
require "rspec/core/rake_task"
|
5
5
|
RSpec::Core::RakeTask.new(:spec)
|
6
6
|
rescue LoadError
|
7
7
|
puts "Couldn't find RSpec core Rake task"
|
8
8
|
end
|
9
9
|
|
10
10
|
begin
|
11
|
-
require
|
11
|
+
require "yard"
|
12
12
|
YARD::Rake::YardocTask.new do |t|
|
13
|
-
t.options = [
|
14
|
-
t.files
|
15
|
-
t.stats_options = [
|
13
|
+
t.options = ["--verbose"]
|
14
|
+
t.files = ["lib/**/*.rb", "doc/**/*.md"]
|
15
|
+
t.stats_options = ["--list-undoc"]
|
16
16
|
end
|
17
17
|
rescue LoadError
|
18
18
|
puts "Couldn't find YARD"
|
19
19
|
end
|
20
20
|
|
21
21
|
begin
|
22
|
-
require
|
22
|
+
require "yard-doctest"
|
23
23
|
YARD::Doctest::RakeTask.new do |task|
|
24
24
|
task.doctest_opts = %w[]
|
25
|
-
task.pattern =
|
25
|
+
task.pattern = "lib/**/*.rb"
|
26
26
|
end
|
27
27
|
rescue LoadError
|
28
28
|
puts "Couldn't find yard-doctest"
|
29
29
|
end
|
30
30
|
|
31
|
-
task :
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
31
|
+
task default: if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
|
32
|
+
[:spec]
|
33
|
+
else
|
34
|
+
[:spec, "yard:doctest"]
|
35
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.3
|
data/lib/sycamore/absence.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "delegate"
|
2
2
|
|
3
3
|
module Sycamore
|
4
|
-
|
5
4
|
##
|
6
5
|
# An Absence object represents the absence of a specific child {Sycamore::Tree}.
|
7
6
|
#
|
@@ -21,7 +20,6 @@ module Sycamore
|
|
21
20
|
# implementation of the parent tree and the parent node.
|
22
21
|
#
|
23
22
|
class Absence < Delegator
|
24
|
-
|
25
23
|
##
|
26
24
|
# @api private
|
27
25
|
#
|
@@ -30,7 +28,7 @@ module Sycamore
|
|
30
28
|
end
|
31
29
|
|
32
30
|
class << self
|
33
|
-
|
31
|
+
alias_method :at, :new
|
34
32
|
end
|
35
33
|
|
36
34
|
########################################################################
|
@@ -46,7 +44,7 @@ module Sycamore
|
|
46
44
|
@tree or Nothing
|
47
45
|
end
|
48
46
|
|
49
|
-
|
47
|
+
alias_method :__getobj__, :presence
|
50
48
|
|
51
49
|
##
|
52
50
|
# @api private
|
@@ -96,17 +94,17 @@ module Sycamore
|
|
96
94
|
if absent?
|
97
95
|
# TODO: This is duplication of Tree#child_at! How can we remove it, without introducing a module for this single method or inherit from Tree?
|
98
96
|
case path.length
|
99
|
-
|
100
|
-
|
101
|
-
|
97
|
+
when 0 then raise ArgumentError, "wrong number of arguments (given 0, expected 1+)"
|
98
|
+
when 1 then child_of(*path)
|
99
|
+
else child_of(path[0]).child_at(*path[1..])
|
102
100
|
end
|
103
101
|
else
|
104
102
|
presence.child_at(*path)
|
105
103
|
end
|
106
104
|
end
|
107
105
|
|
108
|
-
|
109
|
-
|
106
|
+
alias_method :[], :child_at
|
107
|
+
alias_method :dig, :child_at
|
110
108
|
|
111
109
|
##
|
112
110
|
# A developer-friendly string representation of the absent tree.
|
@@ -114,7 +112,7 @@ module Sycamore
|
|
114
112
|
# @return [String]
|
115
113
|
#
|
116
114
|
def inspect
|
117
|
-
"#{absent? ?
|
115
|
+
"#{absent? ? "absent" : "present"} child of node #{@parent_node.inspect} in #{@parent_tree.inspect}"
|
118
116
|
end
|
119
117
|
|
120
118
|
##
|
@@ -174,6 +172,5 @@ module Sycamore
|
|
174
172
|
end
|
175
173
|
end
|
176
174
|
end
|
177
|
-
|
178
175
|
end
|
179
176
|
end
|
data/lib/sycamore/exceptions.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
module Sycamore
|
2
2
|
# raised when a value is not a valid node
|
3
|
-
class InvalidNode < ArgumentError
|
3
|
+
class InvalidNode < ArgumentError; end
|
4
4
|
|
5
5
|
# raised when trying to call a additive command method of the {Nothing} tree
|
6
|
-
class NothingMutation < StandardError
|
6
|
+
class NothingMutation < StandardError; end
|
7
7
|
|
8
8
|
# raised when calling {Tree#node} or {Tree#node!} on a Tree with multiple nodes
|
9
|
-
class NonUniqueNodeSet < StandardError
|
9
|
+
class NonUniqueNodeSet < StandardError; end
|
10
10
|
|
11
11
|
# raised when calling {Tree#node!} on a Tree without nodes
|
12
|
-
class EmptyNodeSet < StandardError
|
12
|
+
class EmptyNodeSet < StandardError; end
|
13
13
|
|
14
14
|
# raised when trying to fetch the child of a leaf
|
15
|
-
class ChildError < KeyError
|
15
|
+
class ChildError < KeyError; end
|
16
16
|
end
|
data/lib/sycamore/extension.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "sycamore/extension/tree"
|
2
|
+
require "sycamore/extension/nothing"
|
data/lib/sycamore/nothing.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "singleton"
|
2
2
|
|
3
3
|
module Sycamore
|
4
|
-
|
5
4
|
##
|
6
5
|
# The Nothing Tree singleton class.
|
7
6
|
#
|
@@ -43,7 +42,7 @@ module Sycamore
|
|
43
42
|
# TODO: YARD should be informed about this method definitions.
|
44
43
|
command_methods.each do |command_method|
|
45
44
|
define_method command_method do |*args|
|
46
|
-
raise NothingMutation,
|
45
|
+
raise NothingMutation, "attempt to change the Nothing tree"
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
@@ -66,7 +65,7 @@ module Sycamore
|
|
66
65
|
# @return [String]
|
67
66
|
#
|
68
67
|
def to_s
|
69
|
-
|
68
|
+
"Tree[Nothing]"
|
70
69
|
end
|
71
70
|
|
72
71
|
##
|
@@ -75,7 +74,7 @@ module Sycamore
|
|
75
74
|
# @return [String]
|
76
75
|
#
|
77
76
|
def inspect
|
78
|
-
|
77
|
+
"#<Sycamore::Nothing>"
|
79
78
|
end
|
80
79
|
|
81
80
|
def freeze
|
@@ -95,7 +94,6 @@ module Sycamore
|
|
95
94
|
(other.is_a?(Tree) or other.is_a?(Absence)) and other.empty?
|
96
95
|
end
|
97
96
|
|
98
|
-
|
99
97
|
########################################################################
|
100
98
|
# Falsiness
|
101
99
|
#
|
@@ -119,7 +117,6 @@ module Sycamore
|
|
119
117
|
# true
|
120
118
|
# end
|
121
119
|
|
122
|
-
|
123
120
|
########################################################################
|
124
121
|
# Some helpers
|
125
122
|
#
|
@@ -139,19 +136,17 @@ module Sycamore
|
|
139
136
|
include Singleton
|
140
137
|
|
141
138
|
def inspect
|
142
|
-
|
139
|
+
"n/a"
|
143
140
|
end
|
144
141
|
end
|
145
142
|
|
146
143
|
##
|
147
144
|
# @api private
|
148
145
|
NestedString = NestedStringPresentation.instance.freeze
|
149
|
-
|
150
146
|
end
|
151
147
|
|
152
148
|
############################################################################
|
153
149
|
# The Nothing Tree Singleton object
|
154
150
|
#
|
155
151
|
Nothing = NothingTree.instance.freeze
|
156
|
-
|
157
152
|
end
|
data/lib/sycamore/path.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "forwardable"
|
2
2
|
|
3
3
|
module Sycamore
|
4
|
-
|
5
4
|
##
|
6
5
|
# A compact, immutable representation of Tree paths, i.e. node sequences.
|
7
6
|
#
|
@@ -62,7 +61,7 @@ module Sycamore
|
|
62
61
|
#
|
63
62
|
def self.of(*args)
|
64
63
|
if (parent = args.first).is_a? Path
|
65
|
-
parent.branch(*args[1
|
64
|
+
parent.branch(*args[1..])
|
66
65
|
else
|
67
66
|
root.branch(*args)
|
68
67
|
end
|
@@ -71,7 +70,7 @@ module Sycamore
|
|
71
70
|
class << self
|
72
71
|
private :new # disable Path.new
|
73
72
|
|
74
|
-
|
73
|
+
alias_method :[], :of
|
75
74
|
end
|
76
75
|
|
77
76
|
########################################################################
|
@@ -96,7 +95,7 @@ module Sycamore
|
|
96
95
|
# Sycamore::Path[:foo, :bar, :baz, :qux] # => true
|
97
96
|
#
|
98
97
|
def branch(*nodes)
|
99
|
-
return branch(*nodes.first) if nodes.size == 1
|
98
|
+
return branch(*nodes.first) if nodes.size == 1 && nodes.first.is_a?(Enumerable)
|
100
99
|
|
101
100
|
parent = self
|
102
101
|
nodes.each do |node|
|
@@ -108,8 +107,8 @@ module Sycamore
|
|
108
107
|
parent
|
109
108
|
end
|
110
109
|
|
111
|
-
|
112
|
-
|
110
|
+
alias_method :+, :branch
|
111
|
+
alias_method :/, :branch
|
113
112
|
|
114
113
|
##
|
115
114
|
# @return [Path] the n-th last parent path
|
@@ -126,9 +125,9 @@ module Sycamore
|
|
126
125
|
distance.is_a? Integer
|
127
126
|
|
128
127
|
case distance
|
129
|
-
|
130
|
-
|
131
|
-
|
128
|
+
when 1 then @parent
|
129
|
+
when 0 then self
|
130
|
+
else parent.up(distance - 1)
|
132
131
|
end
|
133
132
|
end
|
134
133
|
|
@@ -148,7 +147,7 @@ module Sycamore
|
|
148
147
|
i
|
149
148
|
end
|
150
149
|
|
151
|
-
|
150
|
+
alias_method :size, :length
|
152
151
|
|
153
152
|
##
|
154
153
|
# Iterates over all nodes on this path.
|
@@ -160,7 +159,7 @@ module Sycamore
|
|
160
159
|
# @return [Enumerator<node>]
|
161
160
|
#
|
162
161
|
def each_node(&block)
|
163
|
-
return enum_for(__callee__) unless
|
162
|
+
return enum_for(__callee__) unless block
|
164
163
|
|
165
164
|
if @parent
|
166
165
|
@parent.each_node(&block)
|
@@ -168,7 +167,7 @@ module Sycamore
|
|
168
167
|
end
|
169
168
|
end
|
170
169
|
|
171
|
-
|
170
|
+
alias_method :each, :each_node
|
172
171
|
|
173
172
|
##
|
174
173
|
# If a given structure contains this path.
|
@@ -184,18 +183,18 @@ module Sycamore
|
|
184
183
|
def present_in?(struct)
|
185
184
|
each do |node|
|
186
185
|
case
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
186
|
+
when struct.is_a?(Enumerable)
|
187
|
+
return false unless struct.include? node
|
188
|
+
struct = (Tree.like?(struct) ? struct[node] : Nothing)
|
189
|
+
else
|
190
|
+
return false unless struct.eql? node
|
191
|
+
struct = Nothing
|
193
192
|
end
|
194
193
|
end
|
195
194
|
true
|
196
195
|
end
|
197
196
|
|
198
|
-
|
197
|
+
alias_method :in?, :present_in?
|
199
198
|
|
200
199
|
########################################################################
|
201
200
|
# @group Equality
|
@@ -214,8 +213,8 @@ module Sycamore
|
|
214
213
|
#
|
215
214
|
def eql?(other)
|
216
215
|
other.is_a?(self.class) and
|
217
|
-
|
218
|
-
i = other.each
|
216
|
+
length == other.length and begin
|
217
|
+
i = other.each; all? { |node| node.eql? i.next }
|
219
218
|
end
|
220
219
|
end
|
221
220
|
|
@@ -224,8 +223,8 @@ module Sycamore
|
|
224
223
|
# @param other [Object]
|
225
224
|
#
|
226
225
|
def ==(other)
|
227
|
-
other.is_a?(Enumerable) and
|
228
|
-
i = other.each
|
226
|
+
other.is_a?(Enumerable) and length == other.length and begin
|
227
|
+
i = other.each; all? { |node| node == i.next }
|
229
228
|
end
|
230
229
|
end
|
231
230
|
|
@@ -244,7 +243,7 @@ module Sycamore
|
|
244
243
|
# Sycamore::Path[1,2,3].join # => '/1/2/3'
|
245
244
|
# Sycamore::Path[1,2,3].join('|') # => '|1|2|3'
|
246
245
|
#
|
247
|
-
def join(separator =
|
246
|
+
def join(separator = "/")
|
248
247
|
@parent.join(separator) + separator + node.to_s
|
249
248
|
end
|
250
249
|
|
@@ -259,8 +258,7 @@ module Sycamore
|
|
259
258
|
# @return [String] a more verbose string representation of this path
|
260
259
|
#
|
261
260
|
def inspect
|
262
|
-
"#<Sycamore::Path[#{each_node.map(&:inspect).join(
|
261
|
+
"#<Sycamore::Path[#{each_node.map(&:inspect).join(",")}]>"
|
263
262
|
end
|
264
263
|
end
|
265
|
-
|
266
264
|
end
|
data/lib/sycamore/path_root.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "singleton"
|
2
2
|
|
3
3
|
module Sycamore
|
4
4
|
class Path
|
@@ -25,16 +25,16 @@ module Sycamore
|
|
25
25
|
0
|
26
26
|
end
|
27
27
|
|
28
|
-
def join(delimiter =
|
29
|
-
|
28
|
+
def join(delimiter = "/")
|
29
|
+
""
|
30
30
|
end
|
31
31
|
|
32
32
|
def to_s
|
33
|
-
|
33
|
+
"#<Path:Root>"
|
34
34
|
end
|
35
35
|
|
36
36
|
def inspect
|
37
|
-
|
37
|
+
"#<Sycamore::Path::Root>"
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
data/lib/sycamore/stree.rb
CHANGED
data/lib/sycamore/tree.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
module Sycamore
|
2
|
-
|
3
2
|
##
|
4
3
|
# A tree data structure as a recursively nested set of {#nodes nodes} of immutable values.
|
5
4
|
#
|
6
5
|
# See {file:README.md} for a general introduction.
|
7
6
|
#
|
8
7
|
class Tree
|
9
|
-
|
10
8
|
include Enumerable
|
11
9
|
|
12
10
|
# the internal hash representation of this tree
|
@@ -19,11 +17,11 @@ module Sycamore
|
|
19
17
|
|
20
18
|
# the names of all command methods, which add elements to a Tree
|
21
19
|
ADDITIVE_COMMAND_METHODS = %i[add << replace add_node_with_empty_child
|
22
|
-
|
20
|
+
clear_child_of_node] << :[]=
|
23
21
|
|
24
22
|
# the names of all command methods, which delete elements from a Tree
|
25
23
|
DESTRUCTIVE_COMMAND_METHODS = %i[delete >> clear compact replace
|
26
|
-
|
24
|
+
clear_child_of_node] << :[]=
|
27
25
|
|
28
26
|
# the names of all additive command methods, which only add elements from a Tree
|
29
27
|
PURE_ADDITIVE_COMMAND_METHODS = ADDITIVE_COMMAND_METHODS - DESTRUCTIVE_COMMAND_METHODS
|
@@ -38,21 +36,21 @@ module Sycamore
|
|
38
36
|
# the names of all query methods, which return a boolean
|
39
37
|
PREDICATE_METHODS =
|
40
38
|
%i[nothing? absent? existent? present? blank? empty?
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
include? include_node? member? key? has_key? include_path? path? >= > < <=
|
40
|
+
leaf? leaves? internal? external? flat? nested?
|
41
|
+
sleaf? sleaves? strict_leaf? strict_leaves?
|
42
|
+
eql? matches? === ==]
|
45
43
|
|
46
44
|
# the names of all methods, which side-effect-freeze return only a value
|
47
45
|
QUERY_METHODS = PREDICATE_METHODS +
|
48
46
|
%i[new_child dup hash to_native_object to_h to_s inspect
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
node node! nodes keys child_of child_at dig fetch fetch_path search
|
48
|
+
size total_size tsize height
|
49
|
+
each each_path paths each_node each_key each_pair] << :[]
|
52
50
|
|
53
51
|
%i[COMMAND_METHODS QUERY_METHODS PREDICATE_METHODS
|
54
|
-
|
55
|
-
|
52
|
+
ADDITIVE_COMMAND_METHODS DESTRUCTIVE_COMMAND_METHODS
|
53
|
+
PURE_ADDITIVE_COMMAND_METHODS PURE_DESTRUCTIVE_COMMAND_METHODS]
|
56
54
|
.each do |method_set|
|
57
55
|
define_singleton_method(method_set.downcase) { const_get method_set }
|
58
56
|
end
|
@@ -68,7 +66,7 @@ module Sycamore
|
|
68
66
|
end
|
69
67
|
|
70
68
|
protected def data
|
71
|
-
@data ||=
|
69
|
+
@data ||= {}
|
72
70
|
end
|
73
71
|
|
74
72
|
protected def clear_data
|
@@ -89,13 +87,13 @@ module Sycamore
|
|
89
87
|
#
|
90
88
|
def self.with(*args)
|
91
89
|
tree = new
|
92
|
-
tree.add(
|
90
|
+
tree.add((args.size == 1) ? args.first : args) unless args.empty?
|
93
91
|
tree
|
94
92
|
end
|
95
93
|
|
96
94
|
class << self
|
97
|
-
|
98
|
-
|
95
|
+
alias_method :from, :with
|
96
|
+
alias_method :[], :with
|
99
97
|
end
|
100
98
|
|
101
99
|
##
|
@@ -115,7 +113,6 @@ module Sycamore
|
|
115
113
|
self.class.new(*args)
|
116
114
|
end
|
117
115
|
|
118
|
-
|
119
116
|
########################################################################
|
120
117
|
# @group Absence and Nothing predicates
|
121
118
|
########################################################################
|
@@ -144,7 +141,7 @@ module Sycamore
|
|
144
141
|
# @return [Boolean]
|
145
142
|
#
|
146
143
|
def existent?
|
147
|
-
|
144
|
+
!absent?
|
148
145
|
end
|
149
146
|
|
150
147
|
##
|
@@ -157,10 +154,9 @@ module Sycamore
|
|
157
154
|
# @return [Boolean]
|
158
155
|
#
|
159
156
|
def present?
|
160
|
-
|
157
|
+
!blank?
|
161
158
|
end
|
162
159
|
|
163
|
-
|
164
160
|
########################################################################
|
165
161
|
# @group Element access
|
166
162
|
########################################################################
|
@@ -208,21 +204,24 @@ module Sycamore
|
|
208
204
|
# tree.to_h # => {:foo=>{:bar=>[:baz, 1], :qux=>2}}
|
209
205
|
#
|
210
206
|
def add(nodes_or_tree)
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
207
|
+
if nodes_or_tree.equal?(Nothing) # do nothing
|
208
|
+
elsif nodes_or_tree.is_a?(Tree)
|
209
|
+
add_tree(nodes_or_tree)
|
210
|
+
elsif Tree.like?(nodes_or_tree)
|
211
|
+
add_tree(valid_tree!(nodes_or_tree))
|
212
|
+
elsif nodes_or_tree.is_a?(Path)
|
213
|
+
add_path(nodes_or_tree)
|
214
|
+
elsif nodes_or_tree.is_a?(Enumerable)
|
215
|
+
nodes_or_tree.all? { |node| valid_node_element! node }
|
216
|
+
nodes_or_tree.each { |node| add(node) }
|
217
|
+
else
|
218
|
+
add_node(nodes_or_tree)
|
220
219
|
end
|
221
220
|
|
222
221
|
self
|
223
222
|
end
|
224
223
|
|
225
|
-
|
224
|
+
alias_method :<<, :add
|
226
225
|
|
227
226
|
protected def add_node(node)
|
228
227
|
data[node] ||= Nothing
|
@@ -319,21 +318,23 @@ module Sycamore
|
|
319
318
|
# tree.to_h # => {foo: :qux}
|
320
319
|
#
|
321
320
|
def delete(nodes_or_tree)
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
321
|
+
if nodes_or_tree.is_a?(Tree)
|
322
|
+
delete_tree(nodes_or_tree)
|
323
|
+
elsif Tree.like?(nodes_or_tree)
|
324
|
+
delete_tree(valid_tree!(nodes_or_tree))
|
325
|
+
elsif nodes_or_tree.is_a?(Path)
|
326
|
+
delete_path(nodes_or_tree)
|
327
|
+
elsif nodes_or_tree.is_a?(Enumerable)
|
328
|
+
nodes_or_tree.all? { |node| valid_node_element! node }
|
329
|
+
nodes_or_tree.each { |node| delete node }
|
330
|
+
else
|
331
|
+
delete_node valid_node!(nodes_or_tree)
|
331
332
|
end
|
332
333
|
|
333
334
|
self
|
334
335
|
end
|
335
336
|
|
336
|
-
|
337
|
+
alias_method :>>, :delete
|
337
338
|
|
338
339
|
protected def delete_node(node)
|
339
340
|
data.delete(node)
|
@@ -344,19 +345,19 @@ module Sycamore
|
|
344
345
|
protected def delete_tree(tree)
|
345
346
|
tree.each do |node_to_delete, child_to_delete|
|
346
347
|
next unless include? node_to_delete
|
347
|
-
if Nothing.like?(child_to_delete)
|
348
|
-
(child_to_delete.respond_to?(:empty?)
|
348
|
+
if Nothing.like?(child_to_delete) ||
|
349
|
+
(child_to_delete.respond_to?(:empty?) && child_to_delete.empty?)
|
349
350
|
delete_node node_to_delete
|
350
351
|
else
|
351
352
|
fetch(node_to_delete, Nothing).tap do |child|
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
353
|
+
if child.empty?
|
354
|
+
next
|
355
|
+
elsif Tree.like?(child_to_delete)
|
356
|
+
child.delete_tree(child_to_delete)
|
357
|
+
elsif child_to_delete.is_a?(Enumerable)
|
358
|
+
child_to_delete.each { |node| child.delete_node node }
|
359
|
+
else
|
360
|
+
child.delete_node child_to_delete
|
360
361
|
end
|
361
362
|
delete_node(node_to_delete) if child.empty?
|
362
363
|
end
|
@@ -368,13 +369,13 @@ module Sycamore
|
|
368
369
|
|
369
370
|
protected def delete_path(path)
|
370
371
|
case path.length
|
371
|
-
|
372
|
-
|
372
|
+
when 0 then return self
|
373
|
+
when 1 then return delete_node(path.node)
|
373
374
|
end
|
374
375
|
|
375
376
|
parent = fetch_path(path.parent) { return self }
|
376
377
|
parent.delete_node(path.node)
|
377
|
-
delete_path(path.parent) if parent.empty?
|
378
|
+
delete_path(path.parent) if parent.empty? && !path.parent.root?
|
378
379
|
|
379
380
|
self
|
380
381
|
end
|
@@ -472,7 +473,7 @@ module Sycamore
|
|
472
473
|
#
|
473
474
|
def []=(*args)
|
474
475
|
path, nodes_or_tree = args[0..-2], args[-1]
|
475
|
-
raise ArgumentError,
|
476
|
+
raise ArgumentError, "wrong number of arguments (given 1, expected 2)" if path.empty?
|
476
477
|
|
477
478
|
if Nothing.like? nodes_or_tree
|
478
479
|
if path.size == 1
|
@@ -516,17 +517,19 @@ module Sycamore
|
|
516
517
|
# tree.to_h # => {foo: :bar}
|
517
518
|
#
|
518
519
|
def compact
|
519
|
-
data.each do |node, child|
|
520
|
-
|
521
|
-
|
522
|
-
|
520
|
+
data.each do |node, child|
|
521
|
+
if child.nothing?
|
522
|
+
next
|
523
|
+
elsif child.empty?
|
524
|
+
clear_child_of_node(node)
|
525
|
+
else
|
526
|
+
child.compact
|
523
527
|
end
|
524
528
|
end
|
525
529
|
|
526
530
|
self
|
527
531
|
end
|
528
532
|
|
529
|
-
|
530
533
|
#####################
|
531
534
|
# query methods #
|
532
535
|
#####################
|
@@ -545,8 +548,7 @@ module Sycamore
|
|
545
548
|
data.keys
|
546
549
|
end
|
547
550
|
|
548
|
-
|
549
|
-
|
551
|
+
alias_method :keys, :nodes # Hash compatibility
|
550
552
|
|
551
553
|
##
|
552
554
|
# The only node of this tree or an exception, if more {#nodes nodes} present.
|
@@ -587,7 +589,7 @@ module Sycamore
|
|
587
589
|
# @see Tree#node
|
588
590
|
#
|
589
591
|
def node!
|
590
|
-
raise EmptyNodeSet,
|
592
|
+
raise EmptyNodeSet, "no node present" if empty?
|
591
593
|
node
|
592
594
|
end
|
593
595
|
|
@@ -640,21 +642,21 @@ module Sycamore
|
|
640
642
|
def child_at(*path)
|
641
643
|
first = path.first
|
642
644
|
case path.length
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
else
|
649
|
-
child_of(*path)
|
650
|
-
end
|
645
|
+
when 0
|
646
|
+
raise ArgumentError, "wrong number of arguments (given 0, expected 1+)"
|
647
|
+
when 1
|
648
|
+
if first.is_a? Enumerable
|
649
|
+
child_at(*first)
|
651
650
|
else
|
652
|
-
child_of(
|
651
|
+
child_of(*path)
|
652
|
+
end
|
653
|
+
else
|
654
|
+
child_of(first).child_at(*path[1..])
|
653
655
|
end
|
654
656
|
end
|
655
657
|
|
656
|
-
|
657
|
-
|
658
|
+
alias_method :[], :child_at
|
659
|
+
alias_method :dig, :child_at # Hash compatibility
|
658
660
|
|
659
661
|
##
|
660
662
|
# The child tree of a node.
|
@@ -693,10 +695,12 @@ module Sycamore
|
|
693
695
|
|
694
696
|
child = data.fetch(node, *default, &block)
|
695
697
|
if child.equal? Nothing
|
696
|
-
child =
|
697
|
-
|
698
|
-
|
699
|
-
|
698
|
+
child = if block
|
699
|
+
yield
|
700
|
+
elsif !default.empty?
|
701
|
+
default.first
|
702
|
+
else
|
703
|
+
raise ChildError, "node #{node.inspect} has no child tree"
|
700
704
|
end
|
701
705
|
end
|
702
706
|
|
@@ -727,10 +731,10 @@ module Sycamore
|
|
727
731
|
# tree.fetch_path([:foo, :bar, :baz], :default) # => :default
|
728
732
|
#
|
729
733
|
def fetch_path(path, *default, &block)
|
730
|
-
default_case =
|
734
|
+
default_case = block || !default.empty?
|
731
735
|
path.inject(self) do |tree, node|
|
732
736
|
if default_case
|
733
|
-
tree.fetch(node) { return
|
737
|
+
tree.fetch(node) { return block ? yield : default.first }
|
734
738
|
else
|
735
739
|
tree.fetch(node)
|
736
740
|
end
|
@@ -759,14 +763,14 @@ module Sycamore
|
|
759
763
|
# > b
|
760
764
|
#
|
761
765
|
def each_node(&block)
|
762
|
-
return enum_for(__callee__) unless
|
766
|
+
return enum_for(__callee__) unless block
|
763
767
|
|
764
768
|
data.each_key(&block)
|
765
769
|
|
766
770
|
self
|
767
771
|
end
|
768
772
|
|
769
|
-
|
773
|
+
alias_method :each_key, :each_node # Hash compatibility
|
770
774
|
|
771
775
|
##
|
772
776
|
# Iterates over all {#nodes nodes} and their child trees.
|
@@ -788,14 +792,14 @@ module Sycamore
|
|
788
792
|
# > b => #<Tree: Nothing>
|
789
793
|
#
|
790
794
|
def each_pair(&block)
|
791
|
-
return enum_for(__callee__) unless
|
795
|
+
return enum_for(__callee__) unless block
|
792
796
|
|
793
797
|
data.each_pair(&block)
|
794
798
|
|
795
799
|
self
|
796
800
|
end
|
797
801
|
|
798
|
-
|
802
|
+
alias_method :each, :each_pair
|
799
803
|
|
800
804
|
##
|
801
805
|
# Iterates over the {Path paths} to all leaves of this tree.
|
@@ -818,7 +822,7 @@ module Sycamore
|
|
818
822
|
# > #<Path: /b/foo/baz>
|
819
823
|
#
|
820
824
|
def each_path(with_ancestor: Path::ROOT, &block)
|
821
|
-
return enum_for(__callee__) unless
|
825
|
+
return enum_for(__callee__) unless block
|
822
826
|
|
823
827
|
each do |node, child|
|
824
828
|
if child.empty?
|
@@ -831,7 +835,7 @@ module Sycamore
|
|
831
835
|
self
|
832
836
|
end
|
833
837
|
|
834
|
-
|
838
|
+
alias_method :paths, :each_path
|
835
839
|
|
836
840
|
##
|
837
841
|
# Checks if a path of nodes exists in this tree.
|
@@ -848,9 +852,9 @@ module Sycamore
|
|
848
852
|
#
|
849
853
|
def include_path?(*args)
|
850
854
|
case args.count
|
851
|
-
|
852
|
-
|
853
|
-
|
855
|
+
when 0 then raise ArgumentError, "wrong number of arguments (given 0, expected 1+)"
|
856
|
+
when 1 then path = args.first
|
857
|
+
else return include_path?(args)
|
854
858
|
end
|
855
859
|
path = [path] unless path.is_a? Enumerable
|
856
860
|
|
@@ -861,7 +865,7 @@ module Sycamore
|
|
861
865
|
end
|
862
866
|
end
|
863
867
|
|
864
|
-
|
868
|
+
alias_method :path?, :include_path?
|
865
869
|
|
866
870
|
##
|
867
871
|
# Checks if a node exists in the {#nodes nodes} set of this tree.
|
@@ -880,9 +884,9 @@ module Sycamore
|
|
880
884
|
data.include?(node)
|
881
885
|
end
|
882
886
|
|
883
|
-
|
884
|
-
|
885
|
-
|
887
|
+
alias_method :member?, :include_node? # Hash compatibility
|
888
|
+
alias_method :has_key?, :include_node? # Hash compatibility
|
889
|
+
alias_method :key?, :include_node? # Hash compatibility
|
886
890
|
|
887
891
|
##
|
888
892
|
# Checks if some nodes or a full tree-like structure is included in this tree.
|
@@ -899,24 +903,23 @@ module Sycamore
|
|
899
903
|
# tree.include?("a", "b" => 200) # => true
|
900
904
|
#
|
901
905
|
def include?(*elements)
|
902
|
-
raise ArgumentError,
|
906
|
+
raise ArgumentError, "wrong number of arguments (given 0, expected 1+)" if
|
903
907
|
elements.size == 0
|
904
908
|
return elements.all? { |element| include? element } if
|
905
909
|
elements.size > 1
|
906
910
|
|
907
911
|
elements = elements.first
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
include_node? elements
|
912
|
+
if Tree.like?(elements)
|
913
|
+
elements.all? do |node, child|
|
914
|
+
include_node?(node) and (child.nil? or child.equal?(Nothing) or
|
915
|
+
child_of(node).include?(child))
|
916
|
+
end
|
917
|
+
elsif elements.is_a?(Path)
|
918
|
+
include_path? elements
|
919
|
+
elsif elements.is_a?(Enumerable)
|
920
|
+
elements.all? { |element| include_node? element }
|
921
|
+
else
|
922
|
+
include_node? elements
|
920
923
|
end
|
921
924
|
end
|
922
925
|
|
@@ -941,7 +944,7 @@ module Sycamore
|
|
941
944
|
protected def _search(query, current_path: Path::ROOT, results: [])
|
942
945
|
results << current_path if include?(query)
|
943
946
|
each do |node, child|
|
944
|
-
child._search(query, current_path: current_path/node, results: results)
|
947
|
+
child._search(query, current_path: current_path / node, results: results)
|
945
948
|
end
|
946
949
|
results
|
947
950
|
end
|
@@ -982,7 +985,7 @@ module Sycamore
|
|
982
985
|
total
|
983
986
|
end
|
984
987
|
|
985
|
-
|
988
|
+
alias_method :tsize, :total_size
|
986
989
|
|
987
990
|
##
|
988
991
|
# The length of the longest path of this tree.
|
@@ -1011,7 +1014,7 @@ module Sycamore
|
|
1011
1014
|
data.empty?
|
1012
1015
|
end
|
1013
1016
|
|
1014
|
-
|
1017
|
+
alias_method :blank?, :empty?
|
1015
1018
|
|
1016
1019
|
##
|
1017
1020
|
# Checks if the given node has no children.
|
@@ -1047,7 +1050,7 @@ module Sycamore
|
|
1047
1050
|
include_node?(node) && child_at(node).absent?
|
1048
1051
|
end
|
1049
1052
|
|
1050
|
-
|
1053
|
+
alias_method :sleaf?, :strict_leaf?
|
1051
1054
|
|
1052
1055
|
##
|
1053
1056
|
# Checks if all given nodes or that of the tree have no children, even not an empty child tree.
|
@@ -1076,7 +1079,7 @@ module Sycamore
|
|
1076
1079
|
nodes.all? { |node| strict_leaf?(node) }
|
1077
1080
|
end
|
1078
1081
|
|
1079
|
-
|
1082
|
+
alias_method :sleaves?, :strict_leaves?
|
1080
1083
|
|
1081
1084
|
##
|
1082
1085
|
# Checks if all given nodes or that of the tree have no children.
|
@@ -1105,8 +1108,8 @@ module Sycamore
|
|
1105
1108
|
nodes.all? { |node| leaf?(node) }
|
1106
1109
|
end
|
1107
1110
|
|
1108
|
-
|
1109
|
-
|
1111
|
+
alias_method :leaves?, :external?
|
1112
|
+
alias_method :flat?, :external?
|
1110
1113
|
|
1111
1114
|
##
|
1112
1115
|
# Checks if all given nodes or that of the tree have children.
|
@@ -1134,14 +1137,13 @@ module Sycamore
|
|
1134
1137
|
# One would expect it to be the negation of #external? without arguments.
|
1135
1138
|
#
|
1136
1139
|
def internal?(*nodes)
|
1137
|
-
return false if
|
1140
|
+
return false if empty?
|
1138
1141
|
nodes = self.nodes if nodes.empty?
|
1139
1142
|
|
1140
|
-
nodes.all? { |node|
|
1143
|
+
nodes.all? { |node| !leaf?(node) and include_node?(node) }
|
1141
1144
|
end
|
1142
1145
|
|
1143
|
-
|
1144
|
-
|
1146
|
+
alias_method :nested?, :internal?
|
1145
1147
|
|
1146
1148
|
########################################################################
|
1147
1149
|
# @group Comparison
|
@@ -1246,7 +1248,7 @@ module Sycamore
|
|
1246
1248
|
# tree1 >= tree1 # => true
|
1247
1249
|
#
|
1248
1250
|
def >=(other)
|
1249
|
-
(other.is_a?(Tree) or other.is_a?(Absence)) and
|
1251
|
+
(other.is_a?(Tree) or other.is_a?(Absence)) and include?(other)
|
1250
1252
|
end
|
1251
1253
|
|
1252
1254
|
##
|
@@ -1263,7 +1265,7 @@ module Sycamore
|
|
1263
1265
|
# tree1 > tree1 # => false
|
1264
1266
|
#
|
1265
1267
|
def >(other)
|
1266
|
-
(other.is_a?(Tree) or other.is_a?(Absence)) and
|
1268
|
+
(other.is_a?(Tree) or other.is_a?(Absence)) and include?(other) and self != other
|
1267
1269
|
end
|
1268
1270
|
|
1269
1271
|
##
|
@@ -1281,17 +1283,19 @@ module Sycamore
|
|
1281
1283
|
# Problem: Requires a solution which doesn't use +Hash#include?+.
|
1282
1284
|
#
|
1283
1285
|
def matches?(other)
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1286
|
+
if Tree.like?(other)
|
1287
|
+
matches_tree?(other)
|
1288
|
+
elsif other.is_a?(Enumerable)
|
1289
|
+
matches_enumerable?(other)
|
1290
|
+
else
|
1291
|
+
matches_atom?(other)
|
1288
1292
|
end
|
1289
1293
|
end
|
1290
1294
|
|
1291
|
-
|
1295
|
+
alias_method :===, :matches?
|
1292
1296
|
|
1293
1297
|
private def matches_atom?(other)
|
1294
|
-
|
1298
|
+
!other.nil? and (size == 1 and nodes.first == other and leaf? other)
|
1295
1299
|
end
|
1296
1300
|
|
1297
1301
|
private def matches_enumerable?(other)
|
@@ -1304,15 +1308,15 @@ module Sycamore
|
|
1304
1308
|
all? { |node, child|
|
1305
1309
|
if child.nothing?
|
1306
1310
|
other.include?(node) and begin other_child = other.fetch(node, nil)
|
1307
|
-
|
1308
|
-
|
1311
|
+
!other_child or
|
1312
|
+
(other_child.respond_to?(:empty?) and other_child.empty?)
|
1309
1313
|
end
|
1310
1314
|
else
|
1311
1315
|
child.matches? other[node]
|
1312
|
-
end
|
1316
|
+
end
|
1317
|
+
}
|
1313
1318
|
end
|
1314
1319
|
|
1315
|
-
|
1316
1320
|
########################################################################
|
1317
1321
|
# @group Conversion
|
1318
1322
|
########################################################################
|
@@ -1325,13 +1329,12 @@ module Sycamore
|
|
1325
1329
|
# @api private
|
1326
1330
|
#
|
1327
1331
|
def to_native_object(sleaf_child_as: nil, special_nil: false)
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
to_h(sleaf_child_as: sleaf_child_as, special_nil: special_nil)
|
1332
|
+
if empty?
|
1333
|
+
[]
|
1334
|
+
elsif strict_leaves?
|
1335
|
+
(size == 1 && (!special_nil || !nodes.first.nil?)) ? nodes.first : nodes
|
1336
|
+
else
|
1337
|
+
to_h(sleaf_child_as: sleaf_child_as, special_nil: special_nil)
|
1335
1338
|
end
|
1336
1339
|
end
|
1337
1340
|
|
@@ -1392,12 +1395,11 @@ module Sycamore
|
|
1392
1395
|
#
|
1393
1396
|
private def valid_node_element!(node)
|
1394
1397
|
raise InvalidNode, "#{node} is not a valid tree node" if
|
1395
|
-
node.is_a?(Enumerable)
|
1398
|
+
node.is_a?(Enumerable) && !node.is_a?(Path) && !Tree.like?(node)
|
1396
1399
|
|
1397
1400
|
node
|
1398
1401
|
end
|
1399
1402
|
|
1400
|
-
|
1401
1403
|
# @api private
|
1402
1404
|
#
|
1403
1405
|
private def valid_node!(node)
|
@@ -1420,15 +1422,15 @@ module Sycamore
|
|
1420
1422
|
#
|
1421
1423
|
def self.tree_like?(object)
|
1422
1424
|
case object
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1425
|
+
when Hash, Tree, Absence # ... ?!
|
1426
|
+
true
|
1427
|
+
else
|
1428
|
+
(object.respond_to? :tree_like? and object.tree_like?) # or ...
|
1427
1429
|
end
|
1428
1430
|
end
|
1429
1431
|
|
1430
1432
|
class << self
|
1431
|
-
|
1433
|
+
alias_method :like?, :tree_like?
|
1432
1434
|
end
|
1433
1435
|
|
1434
1436
|
########################################################################
|
@@ -1441,8 +1443,7 @@ module Sycamore
|
|
1441
1443
|
# @return [Tree]
|
1442
1444
|
#
|
1443
1445
|
def dup
|
1444
|
-
|
1445
|
-
duplicate
|
1446
|
+
self.class.new.add(self)
|
1446
1447
|
end
|
1447
1448
|
|
1448
1449
|
##
|
@@ -1464,6 +1465,5 @@ module Sycamore
|
|
1464
1465
|
each { |_, child| child.freeze }
|
1465
1466
|
super
|
1466
1467
|
end
|
1467
|
-
|
1468
1468
|
end # Tree
|
1469
1469
|
end # Sycamore
|
data/lib/sycamore/version.rb
CHANGED
@@ -2,27 +2,33 @@ module Sycamore
|
|
2
2
|
# version representation
|
3
3
|
module VERSION
|
4
4
|
# the file containing the project version number
|
5
|
-
FILE = File.expand_path(
|
6
|
-
MAJOR, MINOR, TINY, EXTRA = File.read(FILE).chomp.split(
|
5
|
+
FILE = File.expand_path("../../../VERSION", __FILE__)
|
6
|
+
MAJOR, MINOR, TINY, EXTRA = File.read(FILE).chomp.split(".")
|
7
7
|
# the normalized version string
|
8
|
-
STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join(
|
8
|
+
STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join(".").freeze
|
9
9
|
|
10
10
|
##
|
11
11
|
# @return [String]
|
12
|
-
def self.to_s
|
12
|
+
def self.to_s
|
13
|
+
STRING
|
14
|
+
end
|
13
15
|
|
14
16
|
##
|
15
17
|
# @return [String]
|
16
|
-
def self.to_str
|
18
|
+
def self.to_str
|
19
|
+
STRING
|
20
|
+
end
|
17
21
|
|
18
22
|
##
|
19
23
|
# @return [Array(Integer, Integer, Integer)]
|
20
|
-
def self.to_a
|
24
|
+
def self.to_a
|
25
|
+
[MAJOR, MINOR, TINY]
|
26
|
+
end
|
21
27
|
|
22
28
|
##
|
23
29
|
# @return [Boolean]
|
24
30
|
def self.==(other)
|
25
|
-
other ==
|
31
|
+
other == to_s
|
26
32
|
end
|
27
33
|
end
|
28
34
|
end
|
data/lib/sycamore.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
1
|
+
require "sycamore/version"
|
2
|
+
require "sycamore/exceptions"
|
3
|
+
require "sycamore/path"
|
4
|
+
require "sycamore/path_root"
|
5
|
+
require "sycamore/tree"
|
6
|
+
require "sycamore/nothing"
|
7
|
+
require "sycamore/absence"
|
8
8
|
|
9
9
|
##
|
10
10
|
# see README.md
|
data/support/doctest_helper.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
$LOAD_PATH <<
|
2
|
-
require
|
1
|
+
$LOAD_PATH << "lib"
|
2
|
+
require "sycamore/extension"
|
data/sycamore.gemspec
CHANGED
@@ -1,29 +1,28 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
3
|
+
require "sycamore/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.authors
|
10
|
-
spec.email
|
6
|
+
spec.name = "metaractor-sycamore"
|
7
|
+
spec.version = Sycamore::VERSION
|
8
|
+
spec.authors = ["Marcel Otto", "Ryan Schlesinger"]
|
9
|
+
spec.email = ["ryan@ryanschlesinger.com"]
|
11
10
|
|
12
|
-
spec.summary
|
13
|
-
spec.description
|
14
|
-
spec.homepage
|
15
|
-
spec.license
|
11
|
+
spec.summary = "An unordered tree data structure for Ruby."
|
12
|
+
spec.description = "Sycamore is an unordered tree data structure."
|
13
|
+
spec.homepage = "https://github.com/metaractor/sycamore"
|
14
|
+
spec.license = "MIT"
|
16
15
|
|
17
|
-
spec.files
|
18
|
-
spec.bindir
|
19
|
-
spec.executables
|
20
|
-
spec.require_paths = [
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
21
20
|
|
22
|
-
spec.required_ruby_version =
|
21
|
+
spec.required_ruby_version = ">= 2.7"
|
23
22
|
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
23
|
+
spec.add_development_dependency "bundler", "~> 2"
|
24
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.11"
|
26
|
+
spec.add_development_dependency "yard", "~> 0.9"
|
27
|
+
spec.add_development_dependency "yard-doctest", "0.1.7"
|
29
28
|
end
|