callable_tree 0.3.7 → 0.3.9

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +7 -0
  3. data/.github/workflows/build.yml +3 -5
  4. data/.github/workflows/codeql-analysis.yml +4 -4
  5. data/.rubocop.yml +6 -0
  6. data/.ruby-version +1 -1
  7. data/CHANGELOG.md +12 -0
  8. data/Gemfile.lock +3 -3
  9. data/README.md +460 -276
  10. data/callable_tree.gemspec +1 -0
  11. data/examples/builder/external-verbosify.rb +87 -0
  12. data/examples/builder/hooks.rb +67 -0
  13. data/examples/builder/identity.rb +91 -0
  14. data/examples/builder/internal-broadcastable.rb +11 -11
  15. data/examples/builder/internal-composable.rb +11 -11
  16. data/examples/builder/internal-seekable.rb +9 -15
  17. data/examples/builder/logging.rb +36 -39
  18. data/examples/{external-verbosify.rb → class/external-verbosify.rb} +3 -5
  19. data/examples/class/hooks.rb +70 -0
  20. data/examples/{identity.rb → class/identity.rb} +3 -5
  21. data/examples/{internal-broadcastable.rb → class/internal-broadcastable.rb} +0 -0
  22. data/examples/{internal-composable.rb → class/internal-composable.rb} +0 -0
  23. data/examples/{internal-seekable.rb → class/internal-seekable.rb} +3 -5
  24. data/examples/{logging.rb → class/logging.rb} +47 -47
  25. data/lib/callable_tree/node/builder.rb +13 -0
  26. data/lib/callable_tree/node/hooks/terminator.rb +99 -0
  27. data/lib/callable_tree/node/internal/strategy/broadcast.rb +19 -2
  28. data/lib/callable_tree/node/internal/strategy/compose.rb +15 -3
  29. data/lib/callable_tree/node/internal/strategy/seek.rb +11 -1
  30. data/lib/callable_tree/node/internal/strategy.rb +10 -2
  31. data/lib/callable_tree/node/internal.rb +22 -28
  32. data/lib/callable_tree/node/root.rb +1 -0
  33. data/lib/callable_tree/version.rb +1 -1
  34. data/lib/callable_tree.rb +1 -0
  35. metadata +17 -11
  36. data/examples/builder/hooks-caller.rb +0 -38
  37. data/examples/hooks-caller.rb +0 -39
@@ -55,8 +55,7 @@ module Node
55
55
 
56
56
  def call(input, **_options)
57
57
  input[@type.to_s]
58
- .map { |element| [element['name'], element['emoji']] }
59
- .to_h
58
+ .to_h { |element| [element['name'], element['emoji']] }
60
59
  end
61
60
  end
62
61
  end
@@ -99,8 +98,7 @@ module Node
99
98
  input
100
99
  .get_elements("//#{@type}")
101
100
  .first
102
- .map { |element| [element['name'], element['emoji']] }
103
- .to_h
101
+ .to_h { |element| [element['name'], element['emoji']] }
104
102
  end
105
103
  end
106
104
  end
@@ -117,7 +115,7 @@ tree = CallableTree::Node::Root.new.append(
117
115
  )
118
116
  )
119
117
 
120
- Dir.glob("#{__dir__}/docs/*") do |file|
118
+ Dir.glob("#{__dir__}/../docs/*") do |file|
121
119
  options = { foo: :bar }
122
120
  pp tree.call(file, **options)
123
121
  puts '---'
@@ -38,8 +38,7 @@ module Node
38
38
 
39
39
  def call(input, **_options)
40
40
  input[@type.to_s]
41
- .map { |element| [element['name'], element['emoji']] }
42
- .to_h
41
+ .to_h { |element| [element['name'], element['emoji']] }
43
42
  end
44
43
  end
45
44
  end
@@ -78,8 +77,7 @@ module Node
78
77
  input
79
78
  .get_elements("//#{@type}")
80
79
  .first
81
- .map { |element| [element['name'], element['emoji']] }
82
- .to_h
80
+ .to_h { |element| [element['name'], element['emoji']] }
83
81
  end
84
82
  end
85
83
  end
@@ -96,7 +94,7 @@ tree = CallableTree::Node::Root.new.seekable.append(
96
94
  )
97
95
  )
98
96
 
99
- Dir.glob("#{__dir__}/docs/*") do |file|
97
+ Dir.glob("#{__dir__}/../docs/*") do |file|
100
98
  options = { foo: :bar }
101
99
  pp tree.call(file, **options)
102
100
  puts '---'
@@ -5,36 +5,6 @@ require 'json'
5
5
  require 'rexml/document'
6
6
 
7
7
  module Node
8
- module Logging
9
- INDENT_SIZE = 2
10
- BLANK = ' '
11
-
12
- module Match
13
- LIST_STYLE = '*'
14
-
15
- def match?(_input, **_options)
16
- super.tap do |matched|
17
- prefix = LIST_STYLE.rjust(depth * INDENT_SIZE - INDENT_SIZE + LIST_STYLE.length, BLANK)
18
- puts "#{prefix} #{identity}: [matched: #{matched}]"
19
- end
20
- end
21
- end
22
-
23
- module Call
24
- INPUT_LABEL = 'Input :'
25
- OUTPUT_LABEL = 'Output:'
26
-
27
- def call(input, **_options)
28
- super.tap do |output|
29
- input_prefix = INPUT_LABEL.rjust(depth * INDENT_SIZE + INPUT_LABEL.length, BLANK)
30
- puts "#{input_prefix} #{input}"
31
- output_prefix = OUTPUT_LABEL.rjust(depth * INDENT_SIZE + OUTPUT_LABEL.length, BLANK)
32
- puts "#{output_prefix} #{output}"
33
- end
34
- end
35
- end
36
- end
37
-
38
8
  class Identity
39
9
  attr_reader :klass, :type
40
10
 
@@ -51,7 +21,7 @@ module Node
51
21
  module JSON
52
22
  class Parser
53
23
  include CallableTree::Node::Internal
54
- prepend Logging::Match
24
+ prepend CallableTree::Node::Hooks::Matcher
55
25
 
56
26
  def match?(input, **_options)
57
27
  File.extname(input) == '.json'
@@ -71,8 +41,8 @@ module Node
71
41
 
72
42
  class Scraper
73
43
  include CallableTree::Node::External
74
- prepend Logging::Match
75
- prepend Logging::Call
44
+ prepend CallableTree::Node::Hooks::Matcher
45
+ prepend CallableTree::Node::Hooks::Caller
76
46
 
77
47
  def initialize(type:)
78
48
  @type = type
@@ -88,8 +58,7 @@ module Node
88
58
 
89
59
  def call(input, **_options)
90
60
  input[@type.to_s]
91
- .map { |element| [element['name'], element['emoji']] }
92
- .to_h
61
+ .to_h { |element| [element['name'], element['emoji']] }
93
62
  end
94
63
  end
95
64
  end
@@ -97,7 +66,7 @@ module Node
97
66
  module XML
98
67
  class Parser
99
68
  include CallableTree::Node::Internal
100
- prepend Logging::Match
69
+ prepend CallableTree::Node::Hooks::Matcher
101
70
 
102
71
  def match?(input, **_options)
103
72
  File.extname(input) == '.xml'
@@ -116,8 +85,8 @@ module Node
116
85
 
117
86
  class Scraper
118
87
  include CallableTree::Node::External
119
- prepend Logging::Match
120
- prepend Logging::Call
88
+ prepend CallableTree::Node::Hooks::Matcher
89
+ prepend CallableTree::Node::Hooks::Caller
121
90
 
122
91
  def initialize(type:)
123
92
  @type = type
@@ -135,25 +104,56 @@ module Node
135
104
  input
136
105
  .get_elements("//#{@type}")
137
106
  .first
138
- .map { |element| [element['name'], element['emoji']] }
139
- .to_h
107
+ .to_h { |element| [element['name'], element['emoji']] }
140
108
  end
141
109
  end
142
110
  end
143
111
  end
144
112
 
113
+ module Logging
114
+ INDENT_SIZE = 2
115
+ BLANK = ' '
116
+ LIST_STYLE = '*'
117
+ INPUT_LABEL = 'Input :'
118
+ OUTPUT_LABEL = 'Output:'
119
+
120
+ def self.loggable(node)
121
+ node.after_matcher! do |matched, _node_:, **|
122
+ prefix = LIST_STYLE.rjust((_node_.depth * INDENT_SIZE) - INDENT_SIZE + LIST_STYLE.length, BLANK)
123
+ puts "#{prefix} #{_node_.identity}: [matched: #{matched}]"
124
+ matched
125
+ end
126
+
127
+ if node.external?
128
+ node
129
+ .before_caller! do |input, *, _node_:, **|
130
+ input_prefix = INPUT_LABEL.rjust((_node_.depth * INDENT_SIZE) + INPUT_LABEL.length, BLANK)
131
+ puts "#{input_prefix} #{input}"
132
+ input
133
+ end
134
+ .after_caller! do |output, _node_:, **|
135
+ output_prefix = OUTPUT_LABEL.rjust((_node_.depth * INDENT_SIZE) + OUTPUT_LABEL.length, BLANK)
136
+ puts "#{output_prefix} #{output}"
137
+ output
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ loggable = Logging.method(:loggable)
144
+
145
145
  tree = CallableTree::Node::Root.new.append(
146
- Node::JSON::Parser.new.append(
147
- Node::JSON::Scraper.new(type: :animals).verbosify,
148
- Node::JSON::Scraper.new(type: :fruits).verbosify
146
+ Node::JSON::Parser.new.tap(&loggable).append(
147
+ Node::JSON::Scraper.new(type: :animals).tap(&loggable).verbosify,
148
+ Node::JSON::Scraper.new(type: :fruits).tap(&loggable).verbosify
149
149
  ),
150
- Node::XML::Parser.new.append(
151
- Node::XML::Scraper.new(type: :animals).verbosify,
152
- Node::XML::Scraper.new(type: :fruits).verbosify
150
+ Node::XML::Parser.new.tap(&loggable).append(
151
+ Node::XML::Scraper.new(type: :animals).tap(&loggable).verbosify,
152
+ Node::XML::Scraper.new(type: :fruits).tap(&loggable).verbosify
153
153
  )
154
154
  )
155
155
 
156
- Dir.glob("#{__dir__}/docs/*") do |file|
156
+ Dir.glob("#{__dir__}/../docs/*") do |file|
157
157
  options = { foo: :bar }
158
158
  pp tree.call(file, **options)
159
159
  puts '---'
@@ -24,6 +24,11 @@ module CallableTree
24
24
  self
25
25
  end
26
26
 
27
+ def identifier(&block)
28
+ @identifier = block
29
+ self
30
+ end
31
+
27
32
  def hookable(hookable = true)
28
33
  @hookable = hookable
29
34
  self
@@ -33,6 +38,7 @@ module CallableTree
33
38
  matcher = @matcher
34
39
  caller = @caller
35
40
  terminator = @terminator
41
+ identifier = @identifier
36
42
  hookable = @hookable
37
43
 
38
44
  validate(
@@ -47,6 +53,7 @@ module CallableTree
47
53
  if hookable
48
54
  prepend Hooks::Matcher
49
55
  prepend Hooks::Caller
56
+ prepend Hooks::Terminator
50
57
  end
51
58
 
52
59
  if matcher
@@ -72,6 +79,12 @@ module CallableTree
72
79
  end
73
80
  end
74
81
  end
82
+
83
+ if identifier
84
+ define_method(:identity) do
85
+ identifier.call(_node_: self) { super() }
86
+ end
87
+ end
75
88
  end
76
89
  end
77
90
 
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CallableTree
4
+ module Node
5
+ module Hooks
6
+ module Terminator
7
+ def self.included(_subclass)
8
+ raise ::CallableTree::Error, "#{self} must be prepended"
9
+ end
10
+
11
+ def before_terminator(&block)
12
+ clone.before_terminator!(&block)
13
+ end
14
+
15
+ def before_terminator!(&block)
16
+ before_terminator_callbacks << block
17
+ self
18
+ end
19
+
20
+ def around_terminator(&block)
21
+ clone.around_terminator!(&block)
22
+ end
23
+
24
+ def around_terminator!(&block)
25
+ around_terminator_callbacks << block
26
+ self
27
+ end
28
+
29
+ def after_terminator(&block)
30
+ clone.after_terminator!(&block)
31
+ end
32
+
33
+ def after_terminator!(&block)
34
+ after_terminator_callbacks << block
35
+ self
36
+ end
37
+
38
+ def terminate?(output, *inputs, **options)
39
+ output = before_terminator_callbacks.reduce(output) do |output, callable|
40
+ callable.call(output, *inputs, **options, _node_: self)
41
+ end
42
+
43
+ terminated =
44
+ if around_terminator_callbacks.empty?
45
+ super(output, *inputs, **options)
46
+ else
47
+ around_terminator_callbacks_head, *around_terminator_callbacks_tail = around_terminator_callbacks
48
+ terminator = proc { super(output, *inputs, **options) }
49
+
50
+ terminated =
51
+ around_terminator_callbacks_head
52
+ .call(
53
+ output,
54
+ *inputs,
55
+ **options,
56
+ _node_: self
57
+ ) { terminator.call }
58
+
59
+ around_terminator_callbacks_tail.reduce(terminated) do |terminated, callable|
60
+ callable.call(
61
+ output,
62
+ *inputs,
63
+ **options,
64
+ _node_: self
65
+ ) { terminated }
66
+ end
67
+ end
68
+
69
+ after_terminator_callbacks.reduce(terminated) do |terminated, callable|
70
+ callable.call(terminated, **options, _node_: self)
71
+ end
72
+ end
73
+
74
+ def before_terminator_callbacks
75
+ @before_terminator_callbacks ||= []
76
+ end
77
+
78
+ def around_terminator_callbacks
79
+ @around_terminator_callbacks ||= []
80
+ end
81
+
82
+ def after_terminator_callbacks
83
+ @after_terminator_callbacks ||= []
84
+ end
85
+
86
+ private
87
+
88
+ attr_writer :before_terminator_callbacks, :around_terminator_callbacks, :after_terminator_callbacks
89
+
90
+ def initialize_copy(_node)
91
+ super
92
+ self.before_terminator_callbacks = before_terminator_callbacks.map(&:itself)
93
+ self.around_terminator_callbacks = around_terminator_callbacks.map(&:itself)
94
+ self.after_terminator_callbacks = after_terminator_callbacks.map(&:itself)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -7,9 +7,26 @@ module CallableTree
7
7
  class Broadcast
8
8
  include Strategy
9
9
 
10
+ def initialize(terminable: false)
11
+ self.terminable = terminable
12
+ @terminator =
13
+ if terminable
14
+ proc { |node, output, *inputs, **options| node.terminate?(output, *inputs, **options) }
15
+ else
16
+ proc { false }
17
+ end
18
+ end
19
+
10
20
  def call(nodes, *inputs, **options)
11
- nodes.map do |node|
12
- node.call(*inputs, **options) if node.match?(*inputs, **options)
21
+ nodes.reduce([]) do |outputs, node|
22
+ output = (node.call(*inputs, **options) if node.match?(*inputs, **options))
23
+ outputs << output
24
+
25
+ if @terminator.call(node, output, *inputs, **options)
26
+ break outputs
27
+ else
28
+ outputs
29
+ end
13
30
  end
14
31
  end
15
32
  end
@@ -7,12 +7,24 @@ module CallableTree
7
7
  class Compose
8
8
  include Strategy
9
9
 
10
+ def initialize(terminable: false)
11
+ self.terminable = terminable
12
+ @terminator =
13
+ if terminable
14
+ proc { |node, output, *inputs, **options| node.terminate?(output, *inputs, **options) }
15
+ else
16
+ proc { false }
17
+ end
18
+ end
19
+
10
20
  def call(nodes, *inputs, **options)
11
21
  head, *tail = inputs
12
22
  nodes.reduce(head) do |input, node|
13
- inputs = [input, *tail]
14
- if node.match?(*inputs, **options)
15
- node.call(*inputs, **options)
23
+ if node.match?(input, *tail, **options)
24
+ output = node.call(input, *tail, **options)
25
+ break output if @terminator.call(node, output, input, *tail, **options)
26
+
27
+ output
16
28
  else
17
29
  input
18
30
  end
@@ -7,13 +7,23 @@ module CallableTree
7
7
  class Seek
8
8
  include Strategy
9
9
 
10
+ def initialize(terminable: true)
11
+ self.terminable = terminable
12
+ @terminator =
13
+ if terminable
14
+ proc { |node, output, *inputs, **options| node.terminate?(output, *inputs, **options) }
15
+ else
16
+ proc { false }
17
+ end
18
+ end
19
+
10
20
  def call(nodes, *inputs, **options)
11
21
  nodes
12
22
  .lazy
13
23
  .select { |node| node.match?(*inputs, **options) }
14
24
  .map do |node|
15
25
  output = node.call(*inputs, **options)
16
- terminated = node.terminate?(output, *inputs, **options)
26
+ terminated = @terminator.call(node, output, *inputs, **options)
17
27
  [output, terminated]
18
28
  end
19
29
  .select { |_output, terminated| terminated }
@@ -13,7 +13,7 @@ module CallableTree
13
13
  end
14
14
 
15
15
  def ==(other)
16
- name == other.name
16
+ name == other.name && terminable? == other.terminable?
17
17
  end
18
18
 
19
19
  def eql?(other)
@@ -21,8 +21,16 @@ module CallableTree
21
21
  end
22
22
 
23
23
  def hash
24
- self.class.name.hash
24
+ [self.class.name, terminable].join('-').hash
25
25
  end
26
+
27
+ def terminable?
28
+ terminable
29
+ end
30
+
31
+ private
32
+
33
+ attr_accessor :terminable
26
34
  end
27
35
  end
28
36
  end
@@ -42,7 +42,7 @@ module CallableTree
42
42
  if recursive
43
43
  child_nodes
44
44
  .lazy
45
- .select { |node| node.internal? }
45
+ .select(&:internal?)
46
46
  .map { |node| node.find(recursive: true, &block) }
47
47
  .reject(&:nil?)
48
48
  .first
@@ -89,20 +89,18 @@ module CallableTree
89
89
  strategy.is_a?(Strategy::Seek)
90
90
  end
91
91
 
92
- def seek
93
- if seek?
92
+ def seek(terminable: true)
93
+ if strategy == Strategy::Seek.new(terminable: terminable)
94
94
  self
95
95
  else
96
- clone.tap do |node|
97
- node.strategy = Strategy::Seek.new
98
- end
96
+ clone.seek!(terminable: terminable)
99
97
  end
100
98
  end
101
99
 
102
- def seek!
103
- tap do |node|
104
- node.strategy = Strategy::Seek.new unless seek?
105
- end
100
+ def seek!(terminable: true)
101
+ self.strategy = Strategy::Seek.new(terminable: terminable)
102
+
103
+ self
106
104
  end
107
105
 
108
106
  alias seekable? seek?
@@ -113,20 +111,18 @@ module CallableTree
113
111
  strategy.is_a?(Strategy::Broadcast)
114
112
  end
115
113
 
116
- def broadcast
117
- if broadcast?
114
+ def broadcast(terminable: false)
115
+ if strategy == Strategy::Broadcast.new(terminable: terminable)
118
116
  self
119
117
  else
120
- clone.tap do |node|
121
- node.strategy = Strategy::Broadcast.new
122
- end
118
+ clone.broadcast!(terminable: terminable)
123
119
  end
124
120
  end
125
121
 
126
- def broadcast!
127
- tap do |node|
128
- node.strategy = Strategy::Broadcast.new unless broadcast?
129
- end
122
+ def broadcast!(terminable: false)
123
+ self.strategy = Strategy::Broadcast.new(terminable: terminable)
124
+
125
+ self
130
126
  end
131
127
 
132
128
  alias broadcastable? broadcast?
@@ -137,20 +133,18 @@ module CallableTree
137
133
  strategy.is_a?(Strategy::Compose)
138
134
  end
139
135
 
140
- def compose
141
- if compose?
136
+ def compose(terminable: false)
137
+ if strategy == Strategy::Compose.new(terminable: terminable)
142
138
  self
143
139
  else
144
- clone.tap do |node|
145
- node.strategy = Strategy::Compose.new
146
- end
140
+ clone.compose!(terminable: terminable)
147
141
  end
148
142
  end
149
143
 
150
- def compose!
151
- tap do |node|
152
- node.strategy = Strategy::Compose.new unless compose?
153
- end
144
+ def compose!(terminable: false)
145
+ self.strategy = Strategy::Compose.new(terminable: terminable)
146
+
147
+ self
154
148
  end
155
149
 
156
150
  alias composable? compose?
@@ -6,6 +6,7 @@ module CallableTree
6
6
  include Internal
7
7
  prepend Hooks::Matcher
8
8
  prepend Hooks::Caller
9
+ prepend Hooks::Terminator
9
10
 
10
11
  def self.inherited(subclass)
11
12
  raise ::CallableTree::Error, "#{subclass} cannot inherit #{self}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CallableTree
4
- VERSION = '0.3.7'
4
+ VERSION = '0.3.9'
5
5
  end
data/lib/callable_tree.rb CHANGED
@@ -9,6 +9,7 @@ require_relative 'callable_tree/version'
9
9
  require_relative 'callable_tree/node'
10
10
  require_relative 'callable_tree/node/hooks/matcher'
11
11
  require_relative 'callable_tree/node/hooks/caller'
12
+ require_relative 'callable_tree/node/hooks/terminator'
12
13
  require_relative 'callable_tree/node/internal/strategy'
13
14
  require_relative 'callable_tree/node/internal/strategy/broadcast'
14
15
  require_relative 'callable_tree/node/internal/strategy/seek'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: callable_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - jsmmr
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-09 00:00:00.000000000 Z
11
+ date: 2022-11-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Builds a tree by linking callable nodes. The nodes that match the conditions
14
14
  are called in a chain from the root node to the leaf node. These are like nested
@@ -19,10 +19,12 @@ executables: []
19
19
  extensions: []
20
20
  extra_rdoc_files: []
21
21
  files:
22
+ - ".github/dependabot.yml"
22
23
  - ".github/workflows/build.yml"
23
24
  - ".github/workflows/codeql-analysis.yml"
24
25
  - ".gitignore"
25
26
  - ".rspec"
27
+ - ".rubocop.yml"
26
28
  - ".ruby-version"
27
29
  - CHANGELOG.md
28
30
  - Gemfile
@@ -33,22 +35,24 @@ files:
33
35
  - bin/console
34
36
  - bin/setup
35
37
  - callable_tree.gemspec
36
- - examples/builder/hooks-caller.rb
38
+ - examples/builder/external-verbosify.rb
39
+ - examples/builder/hooks.rb
40
+ - examples/builder/identity.rb
37
41
  - examples/builder/internal-broadcastable.rb
38
42
  - examples/builder/internal-composable.rb
39
43
  - examples/builder/internal-seekable.rb
40
44
  - examples/builder/logging.rb
45
+ - examples/class/external-verbosify.rb
46
+ - examples/class/hooks.rb
47
+ - examples/class/identity.rb
48
+ - examples/class/internal-broadcastable.rb
49
+ - examples/class/internal-composable.rb
50
+ - examples/class/internal-seekable.rb
51
+ - examples/class/logging.rb
41
52
  - examples/docs/animals.json
42
53
  - examples/docs/animals.xml
43
54
  - examples/docs/fruits.json
44
55
  - examples/docs/fruits.xml
45
- - examples/external-verbosify.rb
46
- - examples/hooks-caller.rb
47
- - examples/identity.rb
48
- - examples/internal-broadcastable.rb
49
- - examples/internal-composable.rb
50
- - examples/internal-seekable.rb
51
- - examples/logging.rb
52
56
  - lib/callable_tree.rb
53
57
  - lib/callable_tree/node.rb
54
58
  - lib/callable_tree/node/builder.rb
@@ -57,6 +61,7 @@ files:
57
61
  - lib/callable_tree/node/external/verbose.rb
58
62
  - lib/callable_tree/node/hooks/caller.rb
59
63
  - lib/callable_tree/node/hooks/matcher.rb
64
+ - lib/callable_tree/node/hooks/terminator.rb
60
65
  - lib/callable_tree/node/internal.rb
61
66
  - lib/callable_tree/node/internal/builder.rb
62
67
  - lib/callable_tree/node/internal/strategy.rb
@@ -71,7 +76,8 @@ licenses:
71
76
  metadata:
72
77
  homepage_uri: https://github.com/jsmmr/ruby_callable_tree
73
78
  source_code_uri: https://github.com/jsmmr/ruby_callable_tree
74
- changelog_uri: https://github.com/jsmmr/ruby_callable_tree/blob/v0.3.7/CHANGELOG.md
79
+ changelog_uri: https://github.com/jsmmr/ruby_callable_tree/blob/v0.3.9/CHANGELOG.md
80
+ rubygems_mfa_required: 'true'
75
81
  post_install_message:
76
82
  rdoc_options: []
77
83
  require_paths: