callable_tree 0.2.3 → 0.3.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 +4 -4
- data/.github/workflows/build.yml +2 -2
- data/.github/workflows/codeql-analysis.yml +70 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +3 -3
- data/README.md +29 -29
- data/examples/external-verbosify.rb +11 -9
- data/examples/hooks-call.rb +6 -4
- data/examples/identity.rb +11 -9
- data/examples/internal-broadcast.rb +6 -4
- data/examples/internal-compose.rb +2 -0
- data/examples/internal-seek.rb +11 -9
- data/examples/logging.rb +21 -19
- data/lib/callable_tree/node/external/verbose.rb +3 -2
- data/lib/callable_tree/node/hooks/call.rb +7 -5
- data/lib/callable_tree/node/internal/strategy/broadcast.rb +2 -2
- data/lib/callable_tree/node/internal/strategy/compose.rb +6 -4
- data/lib/callable_tree/node/internal/strategy/seek.rb +4 -4
- data/lib/callable_tree/node/internal.rb +10 -4
- data/lib/callable_tree/node.rb +3 -3
- data/lib/callable_tree/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7daab378247c364839a830fd43b028fd0933cef6026a1df1a614fb4a59c7a66
|
4
|
+
data.tar.gz: 66ac7c3de2198ef3acd80bddadeccc0f3ccd34e5a3d3de7d959bd43fb0801436
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b15c987aeeab91a5250f48e6d429d4176478f74dc7866a0209b0cf7f82909f58fa8f96dbae30c5d37151e63f8dab6c1e8028b2faf15b3919d9afe9ed43eb4fd
|
7
|
+
data.tar.gz: eb1017e10c4f94635058523979c2aeea5edd7d6899a932f2481ae72bd93b74657cd73dc2c1a12935b069e34910f9dba260ef8b62cb70e8a4f4b6dc73915ba0e5
|
data/.github/workflows/build.yml
CHANGED
@@ -5,13 +5,13 @@ jobs:
|
|
5
5
|
runs-on: ubuntu-latest
|
6
6
|
strategy:
|
7
7
|
matrix:
|
8
|
-
ruby: ['2.4', '2.5', '2.6', '2.7', '3.0']
|
8
|
+
ruby: ['2.4', '2.5', '2.6', '2.7', '3.0', '3.1']
|
9
9
|
steps:
|
10
10
|
- uses: actions/checkout@v2
|
11
11
|
- uses: ruby/setup-ruby@v1
|
12
12
|
with:
|
13
13
|
ruby-version: ${{ matrix.ruby }}
|
14
|
-
- run: gem install bundler:2.
|
14
|
+
- run: gem install bundler:2.3.3
|
15
15
|
- uses: actions/cache@v2
|
16
16
|
with:
|
17
17
|
path: vendor/bundle
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# For most projects, this workflow file will not need changing; you simply need
|
2
|
+
# to commit it to your repository.
|
3
|
+
#
|
4
|
+
# You may wish to alter this file to override the set of languages analyzed,
|
5
|
+
# or to provide custom queries or build logic.
|
6
|
+
#
|
7
|
+
# ******** NOTE ********
|
8
|
+
# We have attempted to detect the languages in your repository. Please check
|
9
|
+
# the `language` matrix defined below to confirm you have the correct set of
|
10
|
+
# supported CodeQL languages.
|
11
|
+
#
|
12
|
+
name: "CodeQL"
|
13
|
+
|
14
|
+
on:
|
15
|
+
push:
|
16
|
+
branches: [ main, develop ]
|
17
|
+
pull_request:
|
18
|
+
# The branches below must be a subset of the branches above
|
19
|
+
branches: [ main, develop ]
|
20
|
+
schedule:
|
21
|
+
- cron: '35 15 * * 0'
|
22
|
+
|
23
|
+
jobs:
|
24
|
+
analyze:
|
25
|
+
name: Analyze
|
26
|
+
runs-on: ubuntu-latest
|
27
|
+
permissions:
|
28
|
+
actions: read
|
29
|
+
contents: read
|
30
|
+
security-events: write
|
31
|
+
|
32
|
+
strategy:
|
33
|
+
fail-fast: false
|
34
|
+
matrix:
|
35
|
+
language: [ 'ruby' ]
|
36
|
+
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
37
|
+
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
38
|
+
|
39
|
+
steps:
|
40
|
+
- name: Checkout repository
|
41
|
+
uses: actions/checkout@v2
|
42
|
+
|
43
|
+
# Initializes the CodeQL tools for scanning.
|
44
|
+
- name: Initialize CodeQL
|
45
|
+
uses: github/codeql-action/init@v1
|
46
|
+
with:
|
47
|
+
languages: ${{ matrix.language }}
|
48
|
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
49
|
+
# By default, queries listed here will override any specified in a config file.
|
50
|
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
51
|
+
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
52
|
+
|
53
|
+
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
54
|
+
# If this step fails, then you should remove it and run the build manually (see below)
|
55
|
+
- name: Autobuild
|
56
|
+
uses: github/codeql-action/autobuild@v1
|
57
|
+
|
58
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
59
|
+
# 📚 https://git.io/JvXDl
|
60
|
+
|
61
|
+
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
62
|
+
# and modify them (or add more) to build your code if your project
|
63
|
+
# uses a compiled language
|
64
|
+
|
65
|
+
#- run: |
|
66
|
+
# make bootstrap
|
67
|
+
# make release
|
68
|
+
|
69
|
+
- name: Perform CodeQL Analysis
|
70
|
+
uses: github/codeql-action/analyze@v1
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0
|
1
|
+
3.1.0
|
data/CHANGELOG.md
CHANGED
@@ -1,21 +1,34 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.0] - 2021-12-27
|
4
|
+
|
5
|
+
- Change `CallableTree::Node#match?` to accept inputs to the node as variable length arguments.
|
6
|
+
- Change `CallableTree::Node#call` to accept inputs to the node as variable length arguments.
|
7
|
+
- Change `CallableTree::Node#terminate?` to accept inputs to the node as variable length arguments, after the `output` argument.
|
8
|
+
- Add `CallableTree::Node::Internal#[]` to return the child node using `index`.
|
9
|
+
- Change `CallableTree::Node::Internal#children` to return a new array including child nodes of the node.
|
10
|
+
- Add `CallableTree::Node::Internal#children!` to return destructively changeable array including child nodes of the node.
|
11
|
+
|
3
12
|
## [0.2.3] - 2021-11-07
|
13
|
+
|
4
14
|
- Add `CallableTree::Node::Internal#shake` to recursively execute `CallableTree::Node::Internal#reject`, including child nodes. The child nodes that are empty because their children have been rejected will also be rejected.
|
5
15
|
- Add `CallableTree::Node::Internal#shake!` that make destructive change.
|
6
16
|
- Add `CallableTree::Node#outline` that may be useful for writing the specs.
|
7
17
|
|
8
18
|
## [0.2.2] - 2021-10-24
|
19
|
+
|
9
20
|
- Add `CallableTree::Node::Internal#reject` to return a new node instance without rejected child nodes.
|
10
21
|
- Add `CallableTree::Node::Internal#reject!` to destructively reject child nodes.
|
11
22
|
|
12
23
|
## [0.2.1] - 2021-07-24
|
24
|
+
|
13
25
|
- Add `CallableTree::Node#root?`.
|
14
26
|
- Add `CallableTree::Node::Internal#seek!` that make destructive change.
|
15
27
|
- Add `CallableTree::Node::Internal#broadcast!` that make destructive change.
|
16
28
|
- Add `CallableTree::Node::Internal#compose!` that make destructive change.
|
17
29
|
|
18
30
|
## [0.2.0] - 2021-06-15
|
31
|
+
|
19
32
|
- Change `CallableTree::Node::Internal#append` to return a new instance.
|
20
33
|
To keep the same behavior as the older version, use `CallableTree::Node::External#append!` that make destructive change.
|
21
34
|
- Remove `CallableTree::Node::Internal#<<`. Use `CallableTree::Node::External#append!` instead.
|
@@ -23,6 +36,7 @@
|
|
23
36
|
To keep the same behavior as the older version, use `CallableTree::Node::External#verbosify!` that make destructive change.
|
24
37
|
|
25
38
|
## [0.1.3] - 2021-06-12
|
39
|
+
|
26
40
|
- Minor improvements
|
27
41
|
|
28
42
|
## [0.1.2] - 2021-05-29
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
callable_tree (0.
|
4
|
+
callable_tree (0.3.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
diff-lcs (1.
|
9
|
+
diff-lcs (1.5.0)
|
10
10
|
rake (13.0.6)
|
11
11
|
rspec (3.10.0)
|
12
12
|
rspec-core (~> 3.10.0)
|
@@ -32,4 +32,4 @@ DEPENDENCIES
|
|
32
32
|
rspec (~> 3.0)
|
33
33
|
|
34
34
|
BUNDLED WITH
|
35
|
-
2.
|
35
|
+
2.3.3
|
data/README.md
CHANGED
@@ -42,11 +42,11 @@ module Node
|
|
42
42
|
class Parser
|
43
43
|
include CallableTree::Node::Internal
|
44
44
|
|
45
|
-
def match?(input, **
|
45
|
+
def match?(input, **_options)
|
46
46
|
File.extname(input) == '.json'
|
47
47
|
end
|
48
48
|
|
49
|
-
# If there is need to convert the input
|
49
|
+
# If there is need to convert the input values for
|
50
50
|
# child nodes, override the `call` method.
|
51
51
|
def call(input, **options)
|
52
52
|
File.open(input) do |file|
|
@@ -58,7 +58,7 @@ module Node
|
|
58
58
|
# If a returned value of the `call` method is `nil`,
|
59
59
|
# but there is no need to call the sibling nodes,
|
60
60
|
# override the `terminate?` method to return `true`.
|
61
|
-
def terminate?(
|
61
|
+
def terminate?(_output, *_inputs, **_options)
|
62
62
|
true
|
63
63
|
end
|
64
64
|
end
|
@@ -70,11 +70,11 @@ module Node
|
|
70
70
|
@type = type
|
71
71
|
end
|
72
72
|
|
73
|
-
def match?(input, **
|
73
|
+
def match?(input, **_options)
|
74
74
|
!!input[@type.to_s]
|
75
75
|
end
|
76
76
|
|
77
|
-
def call(input, **
|
77
|
+
def call(input, **_options)
|
78
78
|
input[@type.to_s]
|
79
79
|
.map { |element| [element['name'], element['emoji']] }
|
80
80
|
.to_h
|
@@ -86,11 +86,11 @@ module Node
|
|
86
86
|
class Parser
|
87
87
|
include CallableTree::Node::Internal
|
88
88
|
|
89
|
-
def match?(input, **
|
89
|
+
def match?(input, **_options)
|
90
90
|
File.extname(input) == '.xml'
|
91
91
|
end
|
92
92
|
|
93
|
-
# If there is need to convert the input
|
93
|
+
# If there is need to convert the input values for
|
94
94
|
# child nodes, override the `call` method.
|
95
95
|
def call(input, **options)
|
96
96
|
File.open(input) do |file|
|
@@ -101,7 +101,7 @@ module Node
|
|
101
101
|
# If a returned value of the `call` method is `nil`,
|
102
102
|
# but there is no need to call the sibling nodes,
|
103
103
|
# override the `terminate?` method to return `true`.
|
104
|
-
def terminate?(
|
104
|
+
def terminate?(_output, *_inputs, **_options)
|
105
105
|
true
|
106
106
|
end
|
107
107
|
end
|
@@ -113,11 +113,11 @@ module Node
|
|
113
113
|
@type = type
|
114
114
|
end
|
115
115
|
|
116
|
-
def match?(input, **
|
116
|
+
def match?(input, **_options)
|
117
117
|
!input.get_elements("//#{@type}").empty?
|
118
118
|
end
|
119
119
|
|
120
|
-
def call(input, **
|
120
|
+
def call(input, **_options)
|
121
121
|
input
|
122
122
|
.get_elements("//#{@type}")
|
123
123
|
.first
|
@@ -140,7 +140,7 @@ tree = CallableTree::Node::Root.new.append(
|
|
140
140
|
)#.seek
|
141
141
|
)#.seek
|
142
142
|
|
143
|
-
Dir.glob(__dir__
|
143
|
+
Dir.glob("#{__dir__}/docs/*") do |file|
|
144
144
|
options = { foo: :bar }
|
145
145
|
pp tree.call(file, **options)
|
146
146
|
puts '---'
|
@@ -182,12 +182,12 @@ end
|
|
182
182
|
|
183
183
|
tree = CallableTree::Node::Root.new.append(
|
184
184
|
Node::LessThan.new(5).append(
|
185
|
-
|
186
|
-
|
185
|
+
->(input) { input * 2 }, # anonymous external node
|
186
|
+
->(input) { input + 1 } # anonymous external node
|
187
187
|
).broadcast,
|
188
188
|
Node::LessThan.new(10).append(
|
189
|
-
|
190
|
-
|
189
|
+
->(input) { input * 3 }, # anonymous external node
|
190
|
+
->(input) { input - 1 } # anonymous external node
|
191
191
|
).broadcast
|
192
192
|
).broadcast
|
193
193
|
|
@@ -434,28 +434,28 @@ This is an example of logging.
|
|
434
434
|
module Node
|
435
435
|
module Logging
|
436
436
|
INDENT_SIZE = 2
|
437
|
-
BLANK = ' '
|
437
|
+
BLANK = ' '
|
438
438
|
|
439
439
|
module Match
|
440
|
-
LIST_STYLE = '*'
|
440
|
+
LIST_STYLE = '*'
|
441
441
|
|
442
|
-
def match?(_input, **)
|
442
|
+
def match?(_input, **_options)
|
443
443
|
super.tap do |matched|
|
444
|
-
prefix = LIST_STYLE.rjust(
|
445
|
-
puts "#{prefix} #{
|
444
|
+
prefix = LIST_STYLE.rjust(depth * INDENT_SIZE - INDENT_SIZE + LIST_STYLE.length, BLANK)
|
445
|
+
puts "#{prefix} #{identity}: [matched: #{matched}]"
|
446
446
|
end
|
447
447
|
end
|
448
448
|
end
|
449
449
|
|
450
450
|
module Call
|
451
|
-
INPUT_LABEL = 'Input :'
|
452
|
-
OUTPUT_LABEL = 'Output:'
|
451
|
+
INPUT_LABEL = 'Input :'
|
452
|
+
OUTPUT_LABEL = 'Output:'
|
453
453
|
|
454
|
-
def call(input, **)
|
454
|
+
def call(input, **_options)
|
455
455
|
super.tap do |output|
|
456
|
-
input_prefix = INPUT_LABEL.rjust(
|
456
|
+
input_prefix = INPUT_LABEL.rjust(depth * INDENT_SIZE + INPUT_LABEL.length, BLANK)
|
457
457
|
puts "#{input_prefix} #{input}"
|
458
|
-
output_prefix = OUTPUT_LABEL.rjust(
|
458
|
+
output_prefix = OUTPUT_LABEL.rjust(depth * INDENT_SIZE + OUTPUT_LABEL.length, BLANK)
|
459
459
|
puts "#{output_prefix} #{output}"
|
460
460
|
end
|
461
461
|
end
|
@@ -579,24 +579,24 @@ module Node
|
|
579
579
|
end
|
580
580
|
|
581
581
|
Node::HooksSample.new
|
582
|
-
.before_call do |input, **
|
582
|
+
.before_call do |input, **_options|
|
583
583
|
puts "before_call input: #{input}";
|
584
584
|
input + 1
|
585
585
|
end
|
586
586
|
.append(
|
587
587
|
# anonymous external node
|
588
|
-
lambda do |input, **
|
588
|
+
lambda do |input, **_options|
|
589
589
|
puts "external input: #{input}"
|
590
590
|
input * 2
|
591
591
|
end
|
592
592
|
)
|
593
|
-
.around_call do |input, **
|
593
|
+
.around_call do |input, **_options, &block|
|
594
594
|
puts "around_call input: #{input}"
|
595
595
|
output = block.call
|
596
596
|
puts "around_call output: #{output}"
|
597
597
|
output * input
|
598
598
|
end
|
599
|
-
.after_call do |output, **
|
599
|
+
.after_call do |output, **_options|
|
600
600
|
puts "after_call output: #{output}"
|
601
601
|
output * 2
|
602
602
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'callable_tree'
|
2
4
|
require 'json'
|
3
5
|
require 'rexml/document'
|
@@ -7,7 +9,7 @@ module Node
|
|
7
9
|
class Parser
|
8
10
|
include CallableTree::Node::Internal
|
9
11
|
|
10
|
-
def match?(input, **
|
12
|
+
def match?(input, **_options)
|
11
13
|
File.extname(input) == '.json'
|
12
14
|
end
|
13
15
|
|
@@ -18,7 +20,7 @@ module Node
|
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
|
-
def terminate?(_output, **)
|
23
|
+
def terminate?(_output, *_inputs, **_options)
|
22
24
|
true
|
23
25
|
end
|
24
26
|
end
|
@@ -30,11 +32,11 @@ module Node
|
|
30
32
|
@type = type
|
31
33
|
end
|
32
34
|
|
33
|
-
def match?(input, **
|
35
|
+
def match?(input, **_options)
|
34
36
|
!!input[@type.to_s]
|
35
37
|
end
|
36
38
|
|
37
|
-
def call(input, **
|
39
|
+
def call(input, **_options)
|
38
40
|
input[@type.to_s]
|
39
41
|
.map { |element| [element['name'], element['emoji']] }
|
40
42
|
.to_h
|
@@ -46,7 +48,7 @@ module Node
|
|
46
48
|
class Parser
|
47
49
|
include CallableTree::Node::Internal
|
48
50
|
|
49
|
-
def match?(input, **
|
51
|
+
def match?(input, **_options)
|
50
52
|
File.extname(input) == '.xml'
|
51
53
|
end
|
52
54
|
|
@@ -56,7 +58,7 @@ module Node
|
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
|
-
def terminate?(_output, **)
|
61
|
+
def terminate?(_output, *_inputs, **_options)
|
60
62
|
true
|
61
63
|
end
|
62
64
|
end
|
@@ -68,11 +70,11 @@ module Node
|
|
68
70
|
@type = type
|
69
71
|
end
|
70
72
|
|
71
|
-
def match?(input, **
|
73
|
+
def match?(input, **_options)
|
72
74
|
!input.get_elements("//#{@type}").empty?
|
73
75
|
end
|
74
76
|
|
75
|
-
def call(input, **
|
77
|
+
def call(input, **_options)
|
76
78
|
input
|
77
79
|
.get_elements("//#{@type}")
|
78
80
|
.first
|
@@ -94,7 +96,7 @@ tree = CallableTree::Node::Root.new.append(
|
|
94
96
|
)
|
95
97
|
)
|
96
98
|
|
97
|
-
Dir.glob(__dir__
|
99
|
+
Dir.glob("#{__dir__}/docs/*") do |file|
|
98
100
|
options = { foo: :bar }
|
99
101
|
pp tree.call(file, **options)
|
100
102
|
puts '---'
|
data/examples/hooks-call.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'callable_tree'
|
2
4
|
|
3
5
|
module Node
|
@@ -8,24 +10,24 @@ module Node
|
|
8
10
|
end
|
9
11
|
|
10
12
|
Node::HooksSample.new
|
11
|
-
.before_call do |input, **
|
13
|
+
.before_call do |input, **_options|
|
12
14
|
puts "before_call input: #{input}";
|
13
15
|
input + 1
|
14
16
|
end
|
15
17
|
.append(
|
16
18
|
# anonymous external node
|
17
|
-
lambda do |input, **
|
19
|
+
lambda do |input, **_options|
|
18
20
|
puts "external input: #{input}"
|
19
21
|
input * 2
|
20
22
|
end
|
21
23
|
)
|
22
|
-
.around_call do |input, **
|
24
|
+
.around_call do |input, **_options, &block|
|
23
25
|
puts "around_call input: #{input}"
|
24
26
|
output = block.call
|
25
27
|
puts "around_call output: #{output}"
|
26
28
|
output * input
|
27
29
|
end
|
28
|
-
.after_call do |output, **
|
30
|
+
.after_call do |output, **_options|
|
29
31
|
puts "after_call output: #{output}"
|
30
32
|
output * 2
|
31
33
|
end
|
data/examples/identity.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'callable_tree'
|
2
4
|
require 'json'
|
3
5
|
require 'rexml/document'
|
@@ -20,7 +22,7 @@ module Node
|
|
20
22
|
class Parser
|
21
23
|
include CallableTree::Node::Internal
|
22
24
|
|
23
|
-
def match?(input, **
|
25
|
+
def match?(input, **_options)
|
24
26
|
File.extname(input) == '.json'
|
25
27
|
end
|
26
28
|
|
@@ -31,7 +33,7 @@ module Node
|
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
def terminate?(_output, **)
|
36
|
+
def terminate?(_output, *_inputs, **_options)
|
35
37
|
true
|
36
38
|
end
|
37
39
|
end
|
@@ -47,11 +49,11 @@ module Node
|
|
47
49
|
Identity.new(klass: super, type: @type)
|
48
50
|
end
|
49
51
|
|
50
|
-
def match?(input, **
|
52
|
+
def match?(input, **_options)
|
51
53
|
!!input[@type.to_s]
|
52
54
|
end
|
53
55
|
|
54
|
-
def call(input, **
|
56
|
+
def call(input, **_options)
|
55
57
|
input[@type.to_s]
|
56
58
|
.map { |element| [element['name'], element['emoji']] }
|
57
59
|
.to_h
|
@@ -63,7 +65,7 @@ module Node
|
|
63
65
|
class Parser
|
64
66
|
include CallableTree::Node::Internal
|
65
67
|
|
66
|
-
def match?(input, **
|
68
|
+
def match?(input, **_options)
|
67
69
|
File.extname(input) == '.xml'
|
68
70
|
end
|
69
71
|
|
@@ -73,7 +75,7 @@ module Node
|
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
76
|
-
def terminate?(_output, **)
|
78
|
+
def terminate?(_output, *_inputs, **_options)
|
77
79
|
true
|
78
80
|
end
|
79
81
|
end
|
@@ -89,11 +91,11 @@ module Node
|
|
89
91
|
Identity.new(klass: super, type: @type)
|
90
92
|
end
|
91
93
|
|
92
|
-
def match?(input, **
|
94
|
+
def match?(input, **_options)
|
93
95
|
!input.get_elements("//#{@type}").empty?
|
94
96
|
end
|
95
97
|
|
96
|
-
def call(input, **
|
98
|
+
def call(input, **_options)
|
97
99
|
input
|
98
100
|
.get_elements("//#{@type}")
|
99
101
|
.first
|
@@ -115,7 +117,7 @@ tree = CallableTree::Node::Root.new.append(
|
|
115
117
|
)
|
116
118
|
)
|
117
119
|
|
118
|
-
Dir.glob(__dir__
|
120
|
+
Dir.glob("#{__dir__}/docs/*") do |file|
|
119
121
|
options = { foo: :bar }
|
120
122
|
pp tree.call(file, **options)
|
121
123
|
puts '---'
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'callable_tree'
|
2
4
|
|
3
5
|
module Node
|
@@ -16,12 +18,12 @@ end
|
|
16
18
|
|
17
19
|
tree = CallableTree::Node::Root.new.append(
|
18
20
|
Node::LessThan.new(5).append(
|
19
|
-
|
20
|
-
|
21
|
+
->(input) { input * 2 }, # anonymous external node
|
22
|
+
->(input) { input + 1 } # anonymous external node
|
21
23
|
).broadcast,
|
22
24
|
Node::LessThan.new(10).append(
|
23
|
-
|
24
|
-
|
25
|
+
->(input) { input * 3 }, # anonymous external node
|
26
|
+
->(input) { input - 1 } # anonymous external node
|
25
27
|
).broadcast
|
26
28
|
).broadcast
|
27
29
|
|
data/examples/internal-seek.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'callable_tree'
|
2
4
|
require 'json'
|
3
5
|
require 'rexml/document'
|
@@ -7,7 +9,7 @@ module Node
|
|
7
9
|
class Parser
|
8
10
|
include CallableTree::Node::Internal
|
9
11
|
|
10
|
-
def match?(input, **
|
12
|
+
def match?(input, **_options)
|
11
13
|
File.extname(input) == '.json'
|
12
14
|
end
|
13
15
|
|
@@ -18,7 +20,7 @@ module Node
|
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
|
-
def terminate?(_output, **)
|
23
|
+
def terminate?(_output, *_inputs, **_options)
|
22
24
|
true
|
23
25
|
end
|
24
26
|
end
|
@@ -30,11 +32,11 @@ module Node
|
|
30
32
|
@type = type
|
31
33
|
end
|
32
34
|
|
33
|
-
def match?(input, **
|
35
|
+
def match?(input, **_options)
|
34
36
|
!!input[@type.to_s]
|
35
37
|
end
|
36
38
|
|
37
|
-
def call(input, **
|
39
|
+
def call(input, **_options)
|
38
40
|
input[@type.to_s]
|
39
41
|
.map { |element| [element['name'], element['emoji']] }
|
40
42
|
.to_h
|
@@ -46,7 +48,7 @@ module Node
|
|
46
48
|
class Parser
|
47
49
|
include CallableTree::Node::Internal
|
48
50
|
|
49
|
-
def match?(input, **
|
51
|
+
def match?(input, **_options)
|
50
52
|
File.extname(input) == '.xml'
|
51
53
|
end
|
52
54
|
|
@@ -56,7 +58,7 @@ module Node
|
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
|
-
def terminate?(_output, **)
|
61
|
+
def terminate?(_output, *_inputs, **_options)
|
60
62
|
true
|
61
63
|
end
|
62
64
|
end
|
@@ -68,11 +70,11 @@ module Node
|
|
68
70
|
@type = type
|
69
71
|
end
|
70
72
|
|
71
|
-
def match?(input, **
|
73
|
+
def match?(input, **_options)
|
72
74
|
!input.get_elements("//#{@type}").empty?
|
73
75
|
end
|
74
76
|
|
75
|
-
def call(input, **
|
77
|
+
def call(input, **_options)
|
76
78
|
input
|
77
79
|
.get_elements("//#{@type}")
|
78
80
|
.first
|
@@ -94,7 +96,7 @@ tree = CallableTree::Node::Root.new.append(
|
|
94
96
|
)
|
95
97
|
)
|
96
98
|
|
97
|
-
Dir.glob(__dir__
|
99
|
+
Dir.glob("#{__dir__}/docs/*") do |file|
|
98
100
|
options = { foo: :bar }
|
99
101
|
pp tree.call(file, **options)
|
100
102
|
puts '---'
|
data/examples/logging.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'callable_tree'
|
2
4
|
require 'json'
|
3
5
|
require 'rexml/document'
|
@@ -5,28 +7,28 @@ require 'rexml/document'
|
|
5
7
|
module Node
|
6
8
|
module Logging
|
7
9
|
INDENT_SIZE = 2
|
8
|
-
BLANK = ' '
|
10
|
+
BLANK = ' '
|
9
11
|
|
10
12
|
module Match
|
11
|
-
LIST_STYLE = '*'
|
13
|
+
LIST_STYLE = '*'
|
12
14
|
|
13
|
-
def match?(_input, **)
|
15
|
+
def match?(_input, **_options)
|
14
16
|
super.tap do |matched|
|
15
|
-
prefix = LIST_STYLE.rjust(
|
16
|
-
puts "#{prefix} #{
|
17
|
+
prefix = LIST_STYLE.rjust(depth * INDENT_SIZE - INDENT_SIZE + LIST_STYLE.length, BLANK)
|
18
|
+
puts "#{prefix} #{identity}: [matched: #{matched}]"
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
23
|
module Call
|
22
|
-
INPUT_LABEL = 'Input :'
|
23
|
-
OUTPUT_LABEL = 'Output:'
|
24
|
+
INPUT_LABEL = 'Input :'
|
25
|
+
OUTPUT_LABEL = 'Output:'
|
24
26
|
|
25
|
-
def call(input, **)
|
27
|
+
def call(input, **_options)
|
26
28
|
super.tap do |output|
|
27
|
-
input_prefix = INPUT_LABEL.rjust(
|
29
|
+
input_prefix = INPUT_LABEL.rjust(depth * INDENT_SIZE + INPUT_LABEL.length, BLANK)
|
28
30
|
puts "#{input_prefix} #{input}"
|
29
|
-
output_prefix = OUTPUT_LABEL.rjust(
|
31
|
+
output_prefix = OUTPUT_LABEL.rjust(depth * INDENT_SIZE + OUTPUT_LABEL.length, BLANK)
|
30
32
|
puts "#{output_prefix} #{output}"
|
31
33
|
end
|
32
34
|
end
|
@@ -51,7 +53,7 @@ module Node
|
|
51
53
|
include CallableTree::Node::Internal
|
52
54
|
prepend Logging::Match
|
53
55
|
|
54
|
-
def match?(input, **
|
56
|
+
def match?(input, **_options)
|
55
57
|
File.extname(input) == '.json'
|
56
58
|
end
|
57
59
|
|
@@ -62,7 +64,7 @@ module Node
|
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
65
|
-
def terminate?(_output, **)
|
67
|
+
def terminate?(_output, *_inputs, **_options)
|
66
68
|
true
|
67
69
|
end
|
68
70
|
end
|
@@ -80,11 +82,11 @@ module Node
|
|
80
82
|
Identity.new(klass: super, type: @type)
|
81
83
|
end
|
82
84
|
|
83
|
-
def match?(input, **
|
85
|
+
def match?(input, **_options)
|
84
86
|
!!input[@type.to_s]
|
85
87
|
end
|
86
88
|
|
87
|
-
def call(input, **
|
89
|
+
def call(input, **_options)
|
88
90
|
input[@type.to_s]
|
89
91
|
.map { |element| [element['name'], element['emoji']] }
|
90
92
|
.to_h
|
@@ -97,7 +99,7 @@ module Node
|
|
97
99
|
include CallableTree::Node::Internal
|
98
100
|
prepend Logging::Match
|
99
101
|
|
100
|
-
def match?(input, **
|
102
|
+
def match?(input, **_options)
|
101
103
|
File.extname(input) == '.xml'
|
102
104
|
end
|
103
105
|
|
@@ -107,7 +109,7 @@ module Node
|
|
107
109
|
end
|
108
110
|
end
|
109
111
|
|
110
|
-
def terminate?(_output, **)
|
112
|
+
def terminate?(_output, *_inputs, **_options)
|
111
113
|
true
|
112
114
|
end
|
113
115
|
end
|
@@ -125,11 +127,11 @@ module Node
|
|
125
127
|
Identity.new(klass: super, type: @type)
|
126
128
|
end
|
127
129
|
|
128
|
-
def match?(input, **
|
130
|
+
def match?(input, **_options)
|
129
131
|
!input.get_elements("//#{@type}").empty?
|
130
132
|
end
|
131
133
|
|
132
|
-
def call(input, **
|
134
|
+
def call(input, **_options)
|
133
135
|
input
|
134
136
|
.get_elements("//#{@type}")
|
135
137
|
.first
|
@@ -151,7 +153,7 @@ tree = CallableTree::Node::Root.new.append(
|
|
151
153
|
)
|
152
154
|
)
|
153
155
|
|
154
|
-
Dir.glob(__dir__
|
156
|
+
Dir.glob("#{__dir__}/docs/*") do |file|
|
155
157
|
options = { foo: :bar }
|
156
158
|
pp tree.call(file, **options)
|
157
159
|
puts '---'
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module CallableTree
|
4
4
|
module Node
|
5
5
|
module External
|
6
|
+
# TODO: Add :inputs
|
6
7
|
Output = Struct.new(:value, :options, :routes)
|
7
8
|
|
8
9
|
module Verbose
|
@@ -10,8 +11,8 @@ module CallableTree
|
|
10
11
|
true
|
11
12
|
end
|
12
13
|
|
13
|
-
def call(
|
14
|
-
output = super(
|
14
|
+
def call(*inputs, **options)
|
15
|
+
output = super(*inputs, **options)
|
15
16
|
routes = self.routes
|
16
17
|
|
17
18
|
Output.new(output, options, routes)
|
@@ -23,15 +23,17 @@ module CallableTree
|
|
23
23
|
self
|
24
24
|
end
|
25
25
|
|
26
|
-
def call(
|
27
|
-
|
28
|
-
|
26
|
+
def call(*inputs, **options)
|
27
|
+
input_head, *input_tail = inputs
|
28
|
+
|
29
|
+
input_head = before_callbacks.reduce(input_head) do |input_head, callable|
|
30
|
+
callable.call(input_head, *input_tail, self, **options)
|
29
31
|
end
|
30
32
|
|
31
|
-
output = super(
|
33
|
+
output = super(input_head, *input_tail, **options)
|
32
34
|
|
33
35
|
output = around_callbacks.reduce(output) do |output, callable|
|
34
|
-
callable.call(
|
36
|
+
callable.call(input_head, *input_tail, self, **options) { output }
|
35
37
|
end
|
36
38
|
|
37
39
|
after_callbacks.reduce(output) do |output, callable|
|
@@ -5,9 +5,9 @@ module CallableTree
|
|
5
5
|
module Internal
|
6
6
|
module Strategy
|
7
7
|
class Broadcast
|
8
|
-
def call(nodes,
|
8
|
+
def call(nodes, *inputs, **options)
|
9
9
|
nodes.map do |node|
|
10
|
-
node.call(
|
10
|
+
node.call(*inputs, **options) if node.match?(*inputs, **options)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -5,10 +5,12 @@ module CallableTree
|
|
5
5
|
module Internal
|
6
6
|
module Strategy
|
7
7
|
class Compose
|
8
|
-
def call(nodes,
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def call(nodes, *inputs, **options)
|
9
|
+
head, *tail = inputs
|
10
|
+
nodes.reduce(head) do |input, node|
|
11
|
+
inputs = [input, *tail]
|
12
|
+
if node.match?(*inputs, **options)
|
13
|
+
node.call(*inputs, **options)
|
12
14
|
else
|
13
15
|
input
|
14
16
|
end
|
@@ -5,13 +5,13 @@ module CallableTree
|
|
5
5
|
module Internal
|
6
6
|
module Strategy
|
7
7
|
class Seek
|
8
|
-
def call(nodes,
|
8
|
+
def call(nodes, *inputs, **options)
|
9
9
|
nodes
|
10
10
|
.lazy
|
11
|
-
.select { |node| node.match?(
|
11
|
+
.select { |node| node.match?(*inputs, **options) }
|
12
12
|
.map do |node|
|
13
|
-
output = node.call(
|
14
|
-
terminated = node.terminate?(output, **options)
|
13
|
+
output = node.call(*inputs, **options)
|
14
|
+
terminated = node.terminate?(output, *inputs, **options)
|
15
15
|
[output, terminated]
|
16
16
|
end
|
17
17
|
.select { |_output, terminated| terminated }
|
@@ -3,10 +3,16 @@
|
|
3
3
|
module CallableTree
|
4
4
|
module Node
|
5
5
|
module Internal
|
6
|
+
extend ::Forwardable
|
6
7
|
include Node
|
7
8
|
|
9
|
+
def_delegators :child_nodes, :[], :at
|
10
|
+
|
8
11
|
def children
|
9
|
-
|
12
|
+
[*child_nodes]
|
13
|
+
end
|
14
|
+
|
15
|
+
def children!
|
10
16
|
child_nodes
|
11
17
|
end
|
12
18
|
|
@@ -49,12 +55,12 @@ module CallableTree
|
|
49
55
|
end
|
50
56
|
end
|
51
57
|
|
52
|
-
def match?(
|
58
|
+
def match?(*, **)
|
53
59
|
!child_nodes.empty?
|
54
60
|
end
|
55
61
|
|
56
|
-
def call(
|
57
|
-
strategy.call(child_nodes,
|
62
|
+
def call(*inputs, **options)
|
63
|
+
strategy.call(child_nodes, *inputs, **options)
|
58
64
|
end
|
59
65
|
|
60
66
|
def seek
|
data/lib/callable_tree/node.rb
CHANGED
@@ -34,15 +34,15 @@ module CallableTree
|
|
34
34
|
raise ::CallableTree::Error, 'Not implemented'
|
35
35
|
end
|
36
36
|
|
37
|
-
def match?(
|
37
|
+
def match?(*_inputs, **_options)
|
38
38
|
true
|
39
39
|
end
|
40
40
|
|
41
|
-
def call(
|
41
|
+
def call(*_inputs, **_options)
|
42
42
|
raise ::CallableTree::Error, 'Not implemented'
|
43
43
|
end
|
44
44
|
|
45
|
-
def terminate?(output
|
45
|
+
def terminate?(output, *_inputs, **_options)
|
46
46
|
!output.nil?
|
47
47
|
end
|
48
48
|
|
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.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jsmmr
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-27 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
|
@@ -20,6 +20,7 @@ extensions: []
|
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
22
|
- ".github/workflows/build.yml"
|
23
|
+
- ".github/workflows/codeql-analysis.yml"
|
23
24
|
- ".gitignore"
|
24
25
|
- ".rspec"
|
25
26
|
- ".ruby-version"
|
@@ -60,7 +61,7 @@ licenses:
|
|
60
61
|
metadata:
|
61
62
|
homepage_uri: https://github.com/jsmmr/ruby_callable_tree
|
62
63
|
source_code_uri: https://github.com/jsmmr/ruby_callable_tree
|
63
|
-
changelog_uri: https://github.com/jsmmr/ruby_callable_tree/blob/v0.
|
64
|
+
changelog_uri: https://github.com/jsmmr/ruby_callable_tree/blob/v0.3.0/CHANGELOG.md
|
64
65
|
post_install_message:
|
65
66
|
rdoc_options: []
|
66
67
|
require_paths:
|
@@ -76,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
77
|
- !ruby/object:Gem::Version
|
77
78
|
version: '0'
|
78
79
|
requirements: []
|
79
|
-
rubygems_version: 3.
|
80
|
+
rubygems_version: 3.3.3
|
80
81
|
signing_key:
|
81
82
|
specification_version: 4
|
82
83
|
summary: Builds a tree by linking callable nodes. The nodes that match the conditions
|