eqq 0.0.1 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE.txt +1 -1
- data/README.md +122 -5
- data/lib/eqq.rb +39 -217
- data/lib/eqq/buildable.rb +292 -0
- data/lib/eqq/version.rb +2 -1
- data/sig/eqq.rbs +112 -0
- metadata +15 -220
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0645f6178f68b0a105efa1bcf389bd3c0b1f056cd94a6c6684b0d18bc9284f8
|
4
|
+
data.tar.gz: a93f3a7df8098fbb1e7bdb61b5ad36c29a67e4471e563c63bb562b7896cfa60d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5d02720dfa28fc5aefed2907008e14e76dc00fd087eb83eb6c89bbf8c976b0258410d554592fc1368938bfcda8e96efc99ae2a811f285dfba33b210bf795ba5
|
7
|
+
data.tar.gz: e8077c6bd4ab3c5e363abeaa5154dca3bf8154140a73f75d238883cefe92855fb8da843ba46037c12ffb9bc710b9449b1d121a6e2119dc774520bd237f71d564
|
data/MIT-LICENSE.txt
CHANGED
@@ -7,7 +7,7 @@ of this software and associated documentation files (the "Software"), to deal
|
|
7
7
|
in the Software without restriction, including without limitation the rights
|
8
8
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
9
|
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following
|
10
|
+
furnished to do so, subject to the following patterns:
|
11
11
|
|
12
12
|
The above copyright notice and this permission notice shall be included in all
|
13
13
|
copies or substantial portions of the Software.
|
data/README.md
CHANGED
@@ -3,18 +3,16 @@
|
|
3
3
|
![Build Status](https://github.com/kachick/eqq/actions/workflows/test_behaviors.yml/badge.svg?branch=main)
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/eqq.png)](http://badge.fury.io/rb/eqq)
|
5
5
|
|
6
|
-
Pattern objects builder
|
7
|
-
|
8
|
-
`eqq` means `#===`
|
6
|
+
Pattern objects builder
|
9
7
|
|
10
8
|
## Usage
|
11
9
|
|
12
|
-
Require Ruby 2.
|
10
|
+
Require Ruby 2.6 or later
|
13
11
|
|
14
12
|
Add below code into your Gemfile
|
15
13
|
|
16
14
|
```ruby
|
17
|
-
gem 'eqq', '>= 0.0.
|
15
|
+
gem 'eqq', '>= 0.0.6', '< 0.1.0'
|
18
16
|
```
|
19
17
|
|
20
18
|
### Overview
|
@@ -29,10 +27,129 @@ require 'eqq'
|
|
29
27
|
pattern = Eqq.define do
|
30
28
|
OR(AND(Float, 20..50), Integer)
|
31
29
|
end
|
30
|
+
|
31
|
+
p pattern #=> "OR(AND(Float, 20..50), Integer)"
|
32
32
|
[4.2, 42, 42.0, 420].grep(pattern) #=> [42, 42.0, 420]
|
33
|
+
|
34
|
+
inverted = Eqq.NOT(pattern)
|
35
|
+
p inverted #=> "NOT(OR(AND(Float, 20..50), Integer))"
|
36
|
+
[4.2, 42, 42.0, 420].grep(inverted) #=> [4.2]
|
37
|
+
|
38
|
+
Eqq.SEND(:all?, pattern) === [4.2, 42, 42.0, 420] #=> false
|
39
|
+
Eqq.SEND(:any?, pattern) === [4.2, 42, 42.0, 420] #=> true
|
40
|
+
|
41
|
+
ret_in_case = (
|
42
|
+
case 42
|
43
|
+
when pattern
|
44
|
+
'Should be matched here! :)'
|
45
|
+
when inverted
|
46
|
+
'Should not be matched here! :<'
|
47
|
+
else
|
48
|
+
'Should not be matched here too! :<'
|
49
|
+
end
|
50
|
+
)
|
51
|
+
|
52
|
+
p ret_in_case #=> Should be matched here! :)
|
53
|
+
|
54
|
+
ret_in_case = (
|
55
|
+
case 4.2
|
56
|
+
when pattern
|
57
|
+
'Should not be matched here! :<'
|
58
|
+
when inverted
|
59
|
+
'Should be matched here! :)'
|
60
|
+
else
|
61
|
+
'Should not be matched here too! :<'
|
62
|
+
end
|
63
|
+
)
|
64
|
+
|
65
|
+
p ret_in_case #=> Should be matched here! :)
|
66
|
+
|
67
|
+
class MyClass
|
68
|
+
include Eqq::Buildable
|
69
|
+
|
70
|
+
def example
|
71
|
+
[4.2, 42, 42.0, 420].grep(OR(AND(Float, 20..50), Integer))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
MyClass.new.example #=> [42, 42.0, 420]
|
33
75
|
```
|
34
76
|
|
77
|
+
### Explanation
|
78
|
+
|
79
|
+
All products can be called as `pattern === other`.
|
80
|
+
|
81
|
+
This signature will fit in most Ruby code.
|
82
|
+
|
83
|
+
* `case ~ when` syntax
|
84
|
+
* Enumerable#grep
|
85
|
+
* Enumerable#grep_v
|
86
|
+
* Enumerable#all?
|
87
|
+
* Enumerable#any?
|
88
|
+
* Enumerable#none?
|
89
|
+
* Enumerable#one?
|
90
|
+
* Enumerable#slice_after
|
91
|
+
* Enumerable#slice_before
|
92
|
+
|
93
|
+
They can take this interface as the `pattern`.
|
94
|
+
|
95
|
+
And you already saw. All of patterns can be mixed with other patterns as a parts.
|
96
|
+
Reuse as you wish!
|
97
|
+
|
98
|
+
### Builders
|
99
|
+
|
100
|
+
* OR(*patterns) - Product returns `true` when matched even one pattern
|
101
|
+
* AND(*patterns) - Product returns `true` when matched all patterns
|
102
|
+
* NOT(pattern) - Product returns `true` when not matched the pattern
|
103
|
+
* CAN(*method_names) - Product returns `true` when it has all of the methods (checked with `respond_to?`)
|
104
|
+
* RESCUE(exception_class/module, pattern) - Product returns `true` when the pattern raises the exception
|
105
|
+
* QUIET(*patterns) - Product returns `true` when all patterns did not raise any exception
|
106
|
+
* EQ(object) - Product returns `true` when matched with `#==`
|
107
|
+
* SAME(object) - Product returns `true` when matched with `#equal?`
|
108
|
+
* SEND(name, pattern) - Basically provided for Enumerable
|
109
|
+
* BOOLEAN() - Product returns `true` when matched to `true` or `false`
|
110
|
+
* ANYTHING() - Product returns `true`, always `true`
|
111
|
+
* NEVER() - Product returns `false`, always `false`
|
112
|
+
* XOR(pattern1, pattern2) - Product returns `true` when matched one of the pattern, when matched both returns `false`
|
113
|
+
* NAND(*patterns) - Product is an inverted `AND`
|
114
|
+
* NOR(*patterns) - Product is an inverted `OR`
|
115
|
+
|
116
|
+
### Best fit for RSpec's `satisfy` matcher too
|
117
|
+
|
118
|
+
All builders actually generate a `Proc (lambda)` instance.
|
119
|
+
The signature will fit for RSpec's built-in [`satisfy` matcher](https://relishapp.com/rspec/rspec-expectations/v/3-10/docs/built-in-matchers/satisfy-matcher) too.
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
RSpec.describe RSpec::Matchers::BuiltIn::Satisfy do
|
123
|
+
let(:product) { Eqq.AND(Integer, 24..42) }
|
124
|
+
|
125
|
+
it 'perfectly works' do
|
126
|
+
expect(23).not_to satisfy(&product)
|
127
|
+
expect(24).to satisfy(&product)
|
128
|
+
expect(24.0).not_to satisfy(&product)
|
129
|
+
expect(42).to satisfy(&product)
|
130
|
+
expect(42.0).not_to satisfy(&product)
|
131
|
+
expect(43).not_to satisfy(&product)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
### Use builders without receiver specifying
|
137
|
+
|
138
|
+
When you felt annoy to write `Eqq` in many place, some ways exist.
|
139
|
+
|
140
|
+
* `Eqq.define(&block)` - In the block scope, all builder methods can be used without receiver
|
141
|
+
* `extend Eqq::Buildable` - In the class/module, all builders can be used as class methods
|
142
|
+
* `include Eqq::Buildable` - In the class/module, all builders can be used as instance methods
|
143
|
+
|
144
|
+
### Signature
|
145
|
+
|
146
|
+
* This gem provides [ruby/rbs](https://github.com/ruby/rbs) signature file
|
147
|
+
|
35
148
|
## Links
|
36
149
|
|
37
150
|
* [Repository](https://github.com/kachick/eqq)
|
38
151
|
* [API documents](https://kachick.github.io/eqq)
|
152
|
+
|
153
|
+
## NOTE
|
154
|
+
|
155
|
+
* [`eqq` is the implementation name of `#===` in CRuby](https://github.com/ruby/ruby/blob/2a685da1fcd928530509e99f5edb4117bc377994/range.c#L1859)
|
data/lib/eqq.rb
CHANGED
@@ -2,238 +2,60 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright (c) 2011 Kenichi Kamiya
|
5
|
-
# Forked from https://github.com/kachick/
|
5
|
+
# Forked from https://github.com/kachick/validation at 2021
|
6
6
|
|
7
|
-
|
8
|
-
def self.conditionable?(object)
|
9
|
-
case object
|
10
|
-
when Proc, Method
|
11
|
-
object.arity == 1
|
12
|
-
else
|
13
|
-
begin
|
14
|
-
object.respond_to?(:===)
|
15
|
-
rescue NoMethodError
|
16
|
-
false
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.define(&block)
|
22
|
-
module_exec(&block)
|
23
|
-
end
|
24
|
-
|
25
|
-
module_function
|
26
|
-
|
27
|
-
# A condition builder.
|
28
|
-
# @param condition1 [Proc, Method, #===]
|
29
|
-
# @param condition2 [Proc, Method, #===]
|
30
|
-
# @param conditions [Array<Proc, Method, #===>]
|
31
|
-
# @return [Proc]
|
32
|
-
# this lambda return true if match all conditions
|
33
|
-
def AND(condition1, condition2, *conditions)
|
34
|
-
->v {
|
35
|
-
[condition1, condition2, *conditions].all? { |condition| condition === v }
|
36
|
-
}
|
37
|
-
end
|
38
|
-
|
39
|
-
# A condition builder.
|
40
|
-
# @param condition1 [Proc, Method, #===]
|
41
|
-
# @param condition2 [Proc, Method, #===]
|
42
|
-
# @param conditions [Array<Proc, Method, #===>]
|
43
|
-
# @return [Proc]
|
44
|
-
def NAND(condition1, condition2, *conditions)
|
45
|
-
NOT(AND(condition1, condition2, *conditions))
|
46
|
-
end
|
47
|
-
|
48
|
-
# A condition builder.
|
49
|
-
# @param condition1 [Proc, Method, #===]
|
50
|
-
# @param condition2 [Proc, Method, #===]
|
51
|
-
# @param conditions [Array<Proc, Method, #===>]
|
52
|
-
# @return [Proc]
|
53
|
-
# this lambda return true if match a any condition
|
54
|
-
def OR(condition1, condition2, *conditions)
|
55
|
-
->v {
|
56
|
-
[condition1, condition2, *conditions].any? { |condition| condition === v }
|
57
|
-
}
|
58
|
-
end
|
59
|
-
|
60
|
-
# A condition builder.
|
61
|
-
# @param condition1 [Proc, Method, #===]
|
62
|
-
# @param condition2 [Proc, Method, #===]
|
63
|
-
# @param conditions [Array<Proc, Method, #===>]
|
64
|
-
# @return [Proc]
|
65
|
-
def NOR(condition1, condition2, *conditions)
|
66
|
-
NOT(OR(condition1, condition2, *conditions))
|
67
|
-
end
|
68
|
-
|
69
|
-
# A condition builder.
|
70
|
-
# @param condition1 [Proc, Method, #===]
|
71
|
-
# @param condition2 [Proc, Method, #===]
|
72
|
-
# @param conditions [Array<Proc, Method, #===>]
|
73
|
-
# @return [Proc]
|
74
|
-
def XOR(condition1, condition2, *conditions)
|
75
|
-
->v {
|
76
|
-
[condition1, condition2, *conditions].one? { |condition| condition === v }
|
77
|
-
}
|
78
|
-
end
|
79
|
-
|
80
|
-
# A condition builder.
|
81
|
-
# @param condition1 [Proc, Method, #===]
|
82
|
-
# @param condition2 [Proc, Method, #===]
|
83
|
-
# @param conditions [Array<Proc, Method, #===>]
|
84
|
-
# @return [Proc]
|
85
|
-
def XNOR(condition1, condition2, *conditions)
|
86
|
-
NOT(XOR(condition1, condition2, *conditions))
|
87
|
-
end
|
88
|
-
|
89
|
-
# A condition builder.
|
90
|
-
# @param condition [Proc, Method, #===]
|
91
|
-
# @return [Proc] A condition invert the original condition.
|
92
|
-
def NOT(condition)
|
93
|
-
unless Eqq.conditionable?(condition)
|
94
|
-
raise TypeError, 'wrong object for condition'
|
95
|
-
end
|
96
|
-
|
97
|
-
->v { !(condition === v) }
|
98
|
-
end
|
99
|
-
|
100
|
-
# A condition builder.
|
101
|
-
# @param obj [#==]
|
102
|
-
# @return [Proc]
|
103
|
-
# this lambda return true if a argument match under #== method
|
104
|
-
def EQ(obj)
|
105
|
-
->v { obj == v }
|
106
|
-
end
|
107
|
-
|
108
|
-
# A condition builder.
|
109
|
-
# @param obj [#equal?]
|
110
|
-
# @return [Proc]
|
111
|
-
# this lambda return true if a argument match under #equal? method
|
112
|
-
def SAME(obj)
|
113
|
-
->v { obj.equal?(v) }
|
114
|
-
end
|
115
|
-
|
116
|
-
# A condition builder.
|
117
|
-
# @param message1 [Symbol, String]
|
118
|
-
# @param messages [Array<Symbol, String>]
|
119
|
-
# @return [Proc]
|
120
|
-
# this lambda return true if a argument respond to all messages
|
121
|
-
def CAN(message1, *messages)
|
122
|
-
messages = [message1, *messages].map(&:to_sym)
|
7
|
+
require_relative 'eqq/version'
|
123
8
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
end
|
9
|
+
# Pattern objects builder
|
10
|
+
module Eqq
|
11
|
+
# Base error of this library
|
12
|
+
class Error < StandardError; end
|
128
13
|
|
129
|
-
#
|
130
|
-
|
131
|
-
# @param conditions [Array<Proc, Method, #===>]
|
132
|
-
# @return [Proc]
|
133
|
-
# this lambda return true
|
134
|
-
# if face no exception when a argument checking under all conditions
|
135
|
-
def QUIET(condition1, *conditions)
|
136
|
-
conditions = [condition1, *conditions]
|
137
|
-
unless conditions.all? { |c| Eqq.conditionable?(c) }
|
138
|
-
raise TypeError, 'wrong object for condition'
|
139
|
-
end
|
14
|
+
# Raised when found some products are invalid as a pattern object
|
15
|
+
class InvalidProductError < Error; end
|
140
16
|
|
141
|
-
|
142
|
-
|
17
|
+
class << self
|
18
|
+
def pattern?(object)
|
19
|
+
case object
|
20
|
+
when Proc, Method
|
21
|
+
object.arity == 1
|
22
|
+
else
|
143
23
|
begin
|
144
|
-
|
145
|
-
rescue
|
24
|
+
object.respond_to?(:===)
|
25
|
+
rescue NoMethodError
|
146
26
|
false
|
147
|
-
else
|
148
|
-
true
|
149
27
|
end
|
150
|
-
}
|
151
|
-
}
|
152
|
-
end
|
153
|
-
|
154
|
-
# A condition builder.
|
155
|
-
# @param exception [Exception]
|
156
|
-
# @param exceptions [Array<Exception>]
|
157
|
-
# @return [Proc]
|
158
|
-
# this lambda return true
|
159
|
-
# if catch any kindly exceptions when a argument checking in a block parameter
|
160
|
-
def RESCUE(exception, *exceptions, &condition)
|
161
|
-
exceptions = [exception, *exceptions]
|
162
|
-
raise ArgumentError unless Eqq.conditionable?(condition)
|
163
|
-
raise ArgumentError unless exceptions.all?(Exception)
|
164
|
-
|
165
|
-
->v {
|
166
|
-
begin
|
167
|
-
condition.call(v)
|
168
|
-
false
|
169
|
-
rescue *exceptions
|
170
|
-
true
|
171
|
-
rescue Exception
|
172
|
-
false
|
173
28
|
end
|
174
|
-
|
175
|
-
end
|
176
|
-
|
177
|
-
# A condition builder.
|
178
|
-
# @param exception [Exception]
|
179
|
-
# @return [Proc]
|
180
|
-
# this lambda return true
|
181
|
-
# if catch a specific exception when a argument checking in a block parameter
|
182
|
-
def CATCH(exception, &condition)
|
183
|
-
raise ArgumentError unless Eqq.conditionable?(condition)
|
184
|
-
raise ArgumentError unless exceptions.all?(Exception)
|
29
|
+
end
|
185
30
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
err.instance_of?(exception)
|
191
|
-
else
|
192
|
-
false
|
193
|
-
end
|
194
|
-
}
|
195
|
-
end
|
31
|
+
# @deprecated Use {pattern?} instead. This will be dropped since `0.1.0`
|
32
|
+
def valid?(object)
|
33
|
+
pattern?(object)
|
34
|
+
end
|
196
35
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
# @return [Proc]
|
202
|
-
# this lambda return true
|
203
|
-
# if all included objects match all conditions
|
204
|
-
def ALL(condition1, condition2, *conditions)
|
205
|
-
condition = Eqq.AND(condition1, condition2, *conditions)
|
36
|
+
# @api private
|
37
|
+
def satisfy?(object)
|
38
|
+
(Proc === object) && object.lambda? && (object.arity == 1)
|
39
|
+
end
|
206
40
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
when list.respond_to?(:all?)
|
213
|
-
list
|
214
|
-
when list.respond_to?(:each)
|
215
|
-
list.each
|
216
|
-
else
|
217
|
-
return false
|
218
|
-
end
|
219
|
-
)
|
41
|
+
# @return [#===]
|
42
|
+
# @raise [InvalidProductError] if the return value is invalid as a pattern object
|
43
|
+
def define(&block)
|
44
|
+
pattern = DSLScope.new.instance_exec(&block)
|
45
|
+
raise InvalidProductError unless satisfy?(pattern)
|
220
46
|
|
221
|
-
|
222
|
-
|
47
|
+
pattern
|
48
|
+
end
|
223
49
|
end
|
50
|
+
end
|
224
51
|
|
225
|
-
|
226
|
-
# BasicObject.=== always passing
|
227
|
-
BasicObject
|
228
|
-
end
|
52
|
+
require_relative 'eqq/buildable'
|
229
53
|
|
230
|
-
|
54
|
+
module Eqq
|
55
|
+
extend Buildable
|
231
56
|
|
232
|
-
|
233
|
-
|
234
|
-
def BOOLEAN
|
235
|
-
BOOLEAN
|
57
|
+
class DSLScope
|
58
|
+
include Buildable
|
236
59
|
end
|
60
|
+
private_constant :DSLScope
|
237
61
|
end
|
238
|
-
|
239
|
-
require_relative 'eqq/version'
|
@@ -0,0 +1,292 @@
|
|
1
|
+
# coding: us-ascii
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Eqq
|
5
|
+
# Actually having definitions for the pattern builders
|
6
|
+
module Buildable
|
7
|
+
class << self
|
8
|
+
# When the inspection is failed some unexpected reasons, it will fallback to this value
|
9
|
+
# This value is not fixed as a spec, might be changed in future
|
10
|
+
INSPECTION_FALLBACK = 'UninspectableObject'
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
# @return [String]
|
14
|
+
def safe_inspect_for(object)
|
15
|
+
String.try_convert(object.inspect) || INSPECTION_FALLBACK
|
16
|
+
rescue Exception
|
17
|
+
# This implementation used `RSpec::Support::ObjectFormatter::UninspectableObjectInspector` as a reference, thank you!
|
18
|
+
# ref: https://github.com/kachick/times_kachick/issues/97
|
19
|
+
singleton_class = class << object; self; end
|
20
|
+
begin
|
21
|
+
klass = singleton_class.ancestors.detect { |ancestor| !ancestor.equal?(singleton_class) }
|
22
|
+
native_object_id = '%#016x' % (object.__id__ << 1)
|
23
|
+
"#<#{klass}:#{native_object_id}>"
|
24
|
+
rescue Exception
|
25
|
+
INSPECTION_FALLBACK
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
# @return [void]
|
31
|
+
def define_inspect_on(product, name:, arguments:)
|
32
|
+
inspect = "#{name}(#{arguments.map { |argument| safe_inspect_for(argument) }.join(', ')})".freeze
|
33
|
+
product.define_singleton_method(:inspect) do
|
34
|
+
inspect
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# @api private
|
39
|
+
# @return [void]
|
40
|
+
def validate_patterns(*patterns)
|
41
|
+
invalids = patterns.reject { |pattern| Eqq.pattern?(pattern) }
|
42
|
+
invalid_inspections = invalids.map { |invalid| safe_inspect_for(invalid) }.join(', ')
|
43
|
+
raise ArgumentError, "given `#{invalid_inspections}` are invalid as pattern objects" unless invalids.empty?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Product returns `true` when matched all patterns
|
48
|
+
#
|
49
|
+
# @param pattern1 [Proc, Method, #===]
|
50
|
+
# @param pattern2 [Proc, Method, #===]
|
51
|
+
# @param patterns [Array<Proc, Method, #===>]
|
52
|
+
# @return [Proc]
|
53
|
+
def AND(pattern1, pattern2, *patterns)
|
54
|
+
patterns = [pattern1, pattern2, *patterns].freeze
|
55
|
+
Buildable.validate_patterns(*patterns)
|
56
|
+
|
57
|
+
product = ->v {
|
58
|
+
patterns.all? { |pattern| pattern === v }
|
59
|
+
}
|
60
|
+
|
61
|
+
Buildable.define_inspect_on(product, name: 'AND', arguments: patterns)
|
62
|
+
|
63
|
+
product
|
64
|
+
end
|
65
|
+
|
66
|
+
# Product is an inverted {#AND}
|
67
|
+
#
|
68
|
+
# @param pattern1 [Proc, Method, #===]
|
69
|
+
# @param pattern2 [Proc, Method, #===]
|
70
|
+
# @param patterns [Array<Proc, Method, #===>]
|
71
|
+
# @return [Proc]
|
72
|
+
def NAND(pattern1, pattern2, *patterns)
|
73
|
+
NOT(AND(pattern1, pattern2, *patterns))
|
74
|
+
end
|
75
|
+
|
76
|
+
# Product returns `true` when matched even one pattern
|
77
|
+
#
|
78
|
+
# @param pattern1 [Proc, Method, #===]
|
79
|
+
# @param pattern2 [Proc, Method, #===]
|
80
|
+
# @param patterns [Array<Proc, Method, #===>]
|
81
|
+
# @return [Proc]
|
82
|
+
def OR(pattern1, pattern2, *patterns)
|
83
|
+
patterns = [pattern1, pattern2, *patterns].freeze
|
84
|
+
Buildable.validate_patterns(*patterns)
|
85
|
+
|
86
|
+
product = ->v {
|
87
|
+
patterns.any? { |pattern| pattern === v }
|
88
|
+
}
|
89
|
+
Buildable.define_inspect_on(product, name: 'OR', arguments: patterns)
|
90
|
+
|
91
|
+
product
|
92
|
+
end
|
93
|
+
|
94
|
+
# Product is an inverted {#OR}
|
95
|
+
#
|
96
|
+
# @param pattern1 [Proc, Method, #===]
|
97
|
+
# @param pattern2 [Proc, Method, #===]
|
98
|
+
# @param patterns [Array<Proc, Method, #===>]
|
99
|
+
# @return [Proc]
|
100
|
+
def NOR(pattern1, pattern2, *patterns)
|
101
|
+
NOT(OR(pattern1, pattern2, *patterns))
|
102
|
+
end
|
103
|
+
|
104
|
+
# Product returns `true` when matched one of the pattern, when matched both returns `false`
|
105
|
+
#
|
106
|
+
# @param pattern1 [Proc, Method, #===]
|
107
|
+
# @param pattern2 [Proc, Method, #===]
|
108
|
+
# @return [Proc]
|
109
|
+
def XOR(pattern1, pattern2)
|
110
|
+
patterns = [pattern1, pattern2].freeze
|
111
|
+
Buildable.validate_patterns(*patterns)
|
112
|
+
|
113
|
+
product = ->v {
|
114
|
+
patterns.one? { |pattern| pattern === v }
|
115
|
+
}
|
116
|
+
Buildable.define_inspect_on(product, name: 'XOR', arguments: patterns)
|
117
|
+
|
118
|
+
product
|
119
|
+
end
|
120
|
+
|
121
|
+
# Product returns `true` when not matched the pattern
|
122
|
+
#
|
123
|
+
# @param pattern [Proc, Method, #===]
|
124
|
+
# @return [Proc]
|
125
|
+
def NOT(pattern)
|
126
|
+
Buildable.validate_patterns(pattern)
|
127
|
+
|
128
|
+
product = ->v { !(pattern === v) }
|
129
|
+
|
130
|
+
Buildable.define_inspect_on(product, name: 'NOT', arguments: [pattern])
|
131
|
+
|
132
|
+
product
|
133
|
+
end
|
134
|
+
|
135
|
+
# Product returns `true` when matched with `#==`
|
136
|
+
#
|
137
|
+
# @param obj [#==]
|
138
|
+
# @return [Proc]
|
139
|
+
def EQ(obj)
|
140
|
+
product = ->v { obj == v }
|
141
|
+
Buildable.define_inspect_on(product, name: 'EQ', arguments: [obj])
|
142
|
+
product
|
143
|
+
end
|
144
|
+
|
145
|
+
# Product returns `true` when matched with `#equal?`
|
146
|
+
#
|
147
|
+
# @param obj [#equal?]
|
148
|
+
# @return [Proc]
|
149
|
+
def SAME(obj)
|
150
|
+
product = ->v { obj.equal?(v) }
|
151
|
+
Buildable.define_inspect_on(product, name: 'SAME', arguments: [obj])
|
152
|
+
product
|
153
|
+
end
|
154
|
+
|
155
|
+
# Product returns `true` when it has all of the methods (checked with `respond_to?`)
|
156
|
+
#
|
157
|
+
# @param message1 [Symbol, String, #to_sym]
|
158
|
+
# @param messages [Array<Symbol, String, #to_sym>]
|
159
|
+
# @return [Proc]
|
160
|
+
def CAN(message1, *messages)
|
161
|
+
messages = (
|
162
|
+
begin
|
163
|
+
[message1, *messages].map(&:to_sym).freeze
|
164
|
+
rescue NoMethodError
|
165
|
+
raise ArgumentError
|
166
|
+
end
|
167
|
+
)
|
168
|
+
|
169
|
+
product = ->v {
|
170
|
+
messages.all? { |message|
|
171
|
+
begin
|
172
|
+
v.respond_to?(message)
|
173
|
+
rescue NoMethodError
|
174
|
+
false
|
175
|
+
end
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
Buildable.define_inspect_on(product, name: 'CAN', arguments: messages)
|
180
|
+
|
181
|
+
product
|
182
|
+
end
|
183
|
+
|
184
|
+
# Product returns `true` when all patterns did not raise any exception
|
185
|
+
#
|
186
|
+
# @param pattern1 [Proc, Method, #===]
|
187
|
+
# @param patterns [Array<Proc, Method, #===>]
|
188
|
+
# @return [Proc]
|
189
|
+
def QUIET(pattern1, *patterns)
|
190
|
+
patterns = [pattern1, *patterns].freeze
|
191
|
+
Buildable.validate_patterns(*patterns)
|
192
|
+
|
193
|
+
product = ->v {
|
194
|
+
patterns.all? { |pattern|
|
195
|
+
begin
|
196
|
+
pattern === v
|
197
|
+
rescue Exception
|
198
|
+
false
|
199
|
+
else
|
200
|
+
true
|
201
|
+
end
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
Buildable.define_inspect_on(product, name: 'QUIET', arguments: patterns)
|
206
|
+
|
207
|
+
product
|
208
|
+
end
|
209
|
+
|
210
|
+
# Product returns `true` when the pattern raises the exception
|
211
|
+
#
|
212
|
+
# @param mod [Module]
|
213
|
+
# @param pattern [Proc, Method, #===]
|
214
|
+
# @return [Proc]
|
215
|
+
def RESCUE(mod, pattern)
|
216
|
+
Buildable.validate_patterns(pattern)
|
217
|
+
raise ArgumentError unless Module === mod
|
218
|
+
|
219
|
+
product = ->v {
|
220
|
+
begin
|
221
|
+
pattern === v
|
222
|
+
false
|
223
|
+
rescue mod
|
224
|
+
true
|
225
|
+
rescue Exception
|
226
|
+
false
|
227
|
+
end
|
228
|
+
}
|
229
|
+
|
230
|
+
Buildable.define_inspect_on(product, name: 'RESCUE', arguments: [mod, pattern])
|
231
|
+
|
232
|
+
product
|
233
|
+
end
|
234
|
+
|
235
|
+
# Basically provided for Enumerable
|
236
|
+
#
|
237
|
+
# @param name [Symbol, String, #to_sym]
|
238
|
+
# @param pattern [Proc, Method, #===]
|
239
|
+
# @return [Proc]
|
240
|
+
def SEND(name, pattern)
|
241
|
+
name = (
|
242
|
+
begin
|
243
|
+
name.to_sym
|
244
|
+
rescue NoMethodError
|
245
|
+
raise ArgumentError
|
246
|
+
end
|
247
|
+
)
|
248
|
+
Buildable.validate_patterns(pattern)
|
249
|
+
|
250
|
+
product = ->v {
|
251
|
+
v.__send__(name, pattern)
|
252
|
+
}
|
253
|
+
|
254
|
+
Buildable.define_inspect_on(product, name: 'SEND', arguments: [name, pattern])
|
255
|
+
|
256
|
+
product
|
257
|
+
end
|
258
|
+
|
259
|
+
ANYTHING = ->_v { true }
|
260
|
+
define_inspect_on(ANYTHING, name: 'ANYTHING', arguments: [])
|
261
|
+
private_constant :ANYTHING
|
262
|
+
|
263
|
+
# Product returns `true`, always `true`
|
264
|
+
#
|
265
|
+
# @return [Proc]
|
266
|
+
def ANYTHING
|
267
|
+
ANYTHING
|
268
|
+
end
|
269
|
+
|
270
|
+
NEVER = ->_v { false }
|
271
|
+
define_inspect_on(NEVER, name: 'NEVER', arguments: [])
|
272
|
+
private_constant :NEVER
|
273
|
+
|
274
|
+
# Product returns `false`, always `false`
|
275
|
+
#
|
276
|
+
# @return [Proc]
|
277
|
+
def NEVER
|
278
|
+
NEVER
|
279
|
+
end
|
280
|
+
|
281
|
+
BOOLEAN = ->v { true.equal?(v) || false.equal?(v) }
|
282
|
+
define_inspect_on(BOOLEAN, name: 'BOOLEAN', arguments: [])
|
283
|
+
private_constant :BOOLEAN
|
284
|
+
|
285
|
+
# Product returns `true` when matched to `true` or `false`
|
286
|
+
#
|
287
|
+
# @return [Proc]
|
288
|
+
def BOOLEAN
|
289
|
+
BOOLEAN
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
data/lib/eqq/version.rb
CHANGED
data/sig/eqq.rbs
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# Pattern objects builder
|
2
|
+
module Eqq
|
3
|
+
interface _Patternable
|
4
|
+
def ===: (untyped object) -> bool
|
5
|
+
end
|
6
|
+
|
7
|
+
interface _ToSym
|
8
|
+
def to_sym: -> Symbol
|
9
|
+
end
|
10
|
+
|
11
|
+
interface _Inspectable
|
12
|
+
def inspect: () -> String
|
13
|
+
end
|
14
|
+
|
15
|
+
module Buildable
|
16
|
+
type patternable_lambda = ^(untyped object) -> bool
|
17
|
+
type product = patternable_lambda & _Inspectable
|
18
|
+
|
19
|
+
# A private constant. Should not be used in your code.
|
20
|
+
ANYTHING: product
|
21
|
+
|
22
|
+
# A private constant. Should not be used in your code.
|
23
|
+
NEVER: product
|
24
|
+
|
25
|
+
# A private constant. Should not be used in your code.
|
26
|
+
BOOLEAN: product
|
27
|
+
|
28
|
+
# A private API. Should not be used in your code.
|
29
|
+
def self.safe_inspect_for: (untyped object)-> String
|
30
|
+
|
31
|
+
# A private API. Should not be used in your code.
|
32
|
+
def self.define_inspect_on: (patternable_lambda product, name: String, arguments: Array[untyped])-> void
|
33
|
+
|
34
|
+
# A private API. Should not be used in your code.
|
35
|
+
def self.validate_patterns: (*untyped) -> void
|
36
|
+
|
37
|
+
# Product returns `true` when matched even one pattern
|
38
|
+
def OR: (_Patternable, _Patternable, *_Patternable) -> product
|
39
|
+
|
40
|
+
# Product returns `true` when matched all patterns
|
41
|
+
def AND: (_Patternable, _Patternable, *_Patternable) -> product
|
42
|
+
|
43
|
+
# Product is an inverted `AND`
|
44
|
+
def NAND: (_Patternable, _Patternable, *_Patternable) -> product
|
45
|
+
|
46
|
+
# Product is an inverted `OR`
|
47
|
+
def NOR: (_Patternable, _Patternable, *_Patternable) -> product
|
48
|
+
|
49
|
+
# Product returns `true` when matched one of the pattern, when matched both returns `false`
|
50
|
+
def XOR: (_Patternable, _Patternable) -> product
|
51
|
+
|
52
|
+
# Product returns `true` when not matched the pattern
|
53
|
+
def NOT: (_Patternable) -> product
|
54
|
+
|
55
|
+
# Product returns `true` when matched with `#==`
|
56
|
+
def EQ: (untyped object) -> product
|
57
|
+
|
58
|
+
# Product returns `true` when matched with `#equal?`
|
59
|
+
def SAME: (untyped object) -> product
|
60
|
+
|
61
|
+
# Product returns `true` when it has all of the methods (checked with `respond_to?`)
|
62
|
+
def CAN: (_ToSym, *_ToSym) -> product
|
63
|
+
|
64
|
+
# Product returns `true` when the pattern raises the exception
|
65
|
+
def RESCUE: (Module, _Patternable) -> product
|
66
|
+
|
67
|
+
# Product returns `true` when all patterns did not raise any exception
|
68
|
+
def QUIET: (_Patternable, *_Patternable) -> product
|
69
|
+
|
70
|
+
# Basically provided for Enumerable
|
71
|
+
def SEND: (Symbol | String name, _Patternable) -> product
|
72
|
+
|
73
|
+
# Product returns `true`, always `true`
|
74
|
+
def ANYTHING: () -> product
|
75
|
+
|
76
|
+
# Product returns `false`, always `false`
|
77
|
+
def NEVER: () -> product
|
78
|
+
|
79
|
+
# Product returns `true` when matched to `true` or `false`
|
80
|
+
def BOOLEAN: () -> product
|
81
|
+
end
|
82
|
+
|
83
|
+
extend Buildable
|
84
|
+
|
85
|
+
# Base error of this library
|
86
|
+
class Error < StandardError
|
87
|
+
end
|
88
|
+
|
89
|
+
# Raised when found some products are invalid as a pattern object
|
90
|
+
class InvalidProductError < Error
|
91
|
+
end
|
92
|
+
|
93
|
+
# A private API. Should not be used in your code.
|
94
|
+
class DSLScope
|
95
|
+
include Buildable
|
96
|
+
end
|
97
|
+
|
98
|
+
VERSION: String
|
99
|
+
|
100
|
+
# Returns `true` when given object has patternable signature
|
101
|
+
def self.pattern?: (untyped object) -> bool
|
102
|
+
|
103
|
+
# Alias of `pattern?`. But deperecated. Do not use in your code anymore.
|
104
|
+
def self.valid?: (untyped object) -> bool
|
105
|
+
|
106
|
+
# Returns `true` when given object has correct signature as a product of builders
|
107
|
+
# Basically this is a private API. Should not be used in your code.
|
108
|
+
def self.satisfy?: (untyped object) -> bool
|
109
|
+
|
110
|
+
# In the block scope, all builder methods can be used without receiver
|
111
|
+
def self.define: { () -> _Patternable } -> _Patternable
|
112
|
+
end
|
metadata
CHANGED
@@ -1,230 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eqq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenichi Kamiya
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-06-
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '4.0'
|
23
|
-
type: :development
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 3.4.1
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '4.0'
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: irb
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - ">="
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: 1.3.5
|
40
|
-
- - "<"
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: '2.0'
|
43
|
-
type: :development
|
44
|
-
prerelease: false
|
45
|
-
version_requirements: !ruby/object:Gem::Requirement
|
46
|
-
requirements:
|
47
|
-
- - ">="
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: 1.3.5
|
50
|
-
- - "<"
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: '2.0'
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: irb-power_assert
|
55
|
-
requirement: !ruby/object:Gem::Requirement
|
56
|
-
requirements:
|
57
|
-
- - '='
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: 0.0.2
|
60
|
-
type: :development
|
61
|
-
prerelease: false
|
62
|
-
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
requirements:
|
64
|
-
- - '='
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: 0.0.2
|
67
|
-
- !ruby/object:Gem::Dependency
|
68
|
-
name: warning
|
69
|
-
requirement: !ruby/object:Gem::Requirement
|
70
|
-
requirements:
|
71
|
-
- - ">="
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
version: 1.2.0
|
74
|
-
- - "<"
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
version: '2.0'
|
77
|
-
type: :development
|
78
|
-
prerelease: false
|
79
|
-
version_requirements: !ruby/object:Gem::Requirement
|
80
|
-
requirements:
|
81
|
-
- - ">="
|
82
|
-
- !ruby/object:Gem::Version
|
83
|
-
version: 1.2.0
|
84
|
-
- - "<"
|
85
|
-
- !ruby/object:Gem::Version
|
86
|
-
version: '2.0'
|
87
|
-
- !ruby/object:Gem::Dependency
|
88
|
-
name: rake
|
89
|
-
requirement: !ruby/object:Gem::Requirement
|
90
|
-
requirements:
|
91
|
-
- - ">="
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: 13.0.3
|
94
|
-
- - "<"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '20.0'
|
97
|
-
type: :development
|
98
|
-
prerelease: false
|
99
|
-
version_requirements: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: 13.0.3
|
104
|
-
- - "<"
|
105
|
-
- !ruby/object:Gem::Version
|
106
|
-
version: '20.0'
|
107
|
-
- !ruby/object:Gem::Dependency
|
108
|
-
name: yard
|
109
|
-
requirement: !ruby/object:Gem::Requirement
|
110
|
-
requirements:
|
111
|
-
- - ">="
|
112
|
-
- !ruby/object:Gem::Version
|
113
|
-
version: 0.9.26
|
114
|
-
- - "<"
|
115
|
-
- !ruby/object:Gem::Version
|
116
|
-
version: '2'
|
117
|
-
type: :development
|
118
|
-
prerelease: false
|
119
|
-
version_requirements: !ruby/object:Gem::Requirement
|
120
|
-
requirements:
|
121
|
-
- - ">="
|
122
|
-
- !ruby/object:Gem::Version
|
123
|
-
version: 0.9.26
|
124
|
-
- - "<"
|
125
|
-
- !ruby/object:Gem::Version
|
126
|
-
version: '2'
|
127
|
-
- !ruby/object:Gem::Dependency
|
128
|
-
name: rubocop
|
129
|
-
requirement: !ruby/object:Gem::Requirement
|
130
|
-
requirements:
|
131
|
-
- - ">="
|
132
|
-
- !ruby/object:Gem::Version
|
133
|
-
version: 1.15.0
|
134
|
-
- - "<"
|
135
|
-
- !ruby/object:Gem::Version
|
136
|
-
version: 1.16.0
|
137
|
-
type: :development
|
138
|
-
prerelease: false
|
139
|
-
version_requirements: !ruby/object:Gem::Requirement
|
140
|
-
requirements:
|
141
|
-
- - ">="
|
142
|
-
- !ruby/object:Gem::Version
|
143
|
-
version: 1.15.0
|
144
|
-
- - "<"
|
145
|
-
- !ruby/object:Gem::Version
|
146
|
-
version: 1.16.0
|
147
|
-
- !ruby/object:Gem::Dependency
|
148
|
-
name: rubocop-rake
|
149
|
-
requirement: !ruby/object:Gem::Requirement
|
150
|
-
requirements:
|
151
|
-
- - ">="
|
152
|
-
- !ruby/object:Gem::Version
|
153
|
-
version: 0.5.1
|
154
|
-
- - "<"
|
155
|
-
- !ruby/object:Gem::Version
|
156
|
-
version: 0.6.0
|
157
|
-
type: :development
|
158
|
-
prerelease: false
|
159
|
-
version_requirements: !ruby/object:Gem::Requirement
|
160
|
-
requirements:
|
161
|
-
- - ">="
|
162
|
-
- !ruby/object:Gem::Version
|
163
|
-
version: 0.5.1
|
164
|
-
- - "<"
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: 0.6.0
|
167
|
-
- !ruby/object:Gem::Dependency
|
168
|
-
name: rubocop-performance
|
169
|
-
requirement: !ruby/object:Gem::Requirement
|
170
|
-
requirements:
|
171
|
-
- - ">="
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
version: 1.11.3
|
174
|
-
- - "<"
|
175
|
-
- !ruby/object:Gem::Version
|
176
|
-
version: 1.12.0
|
177
|
-
type: :development
|
178
|
-
prerelease: false
|
179
|
-
version_requirements: !ruby/object:Gem::Requirement
|
180
|
-
requirements:
|
181
|
-
- - ">="
|
182
|
-
- !ruby/object:Gem::Version
|
183
|
-
version: 1.11.3
|
184
|
-
- - "<"
|
185
|
-
- !ruby/object:Gem::Version
|
186
|
-
version: 1.12.0
|
187
|
-
- !ruby/object:Gem::Dependency
|
188
|
-
name: rubocop-rubycw
|
189
|
-
requirement: !ruby/object:Gem::Requirement
|
190
|
-
requirements:
|
191
|
-
- - ">="
|
192
|
-
- !ruby/object:Gem::Version
|
193
|
-
version: 0.1.6
|
194
|
-
- - "<"
|
195
|
-
- !ruby/object:Gem::Version
|
196
|
-
version: 0.2.0
|
197
|
-
type: :development
|
198
|
-
prerelease: false
|
199
|
-
version_requirements: !ruby/object:Gem::Requirement
|
200
|
-
requirements:
|
201
|
-
- - ">="
|
202
|
-
- !ruby/object:Gem::Version
|
203
|
-
version: 0.1.6
|
204
|
-
- - "<"
|
205
|
-
- !ruby/object:Gem::Version
|
206
|
-
version: 0.2.0
|
207
|
-
- !ruby/object:Gem::Dependency
|
208
|
-
name: rubocop-md
|
209
|
-
requirement: !ruby/object:Gem::Requirement
|
210
|
-
requirements:
|
211
|
-
- - ">="
|
212
|
-
- !ruby/object:Gem::Version
|
213
|
-
version: 1.0.1
|
214
|
-
- - "<"
|
215
|
-
- !ruby/object:Gem::Version
|
216
|
-
version: 2.0.0
|
217
|
-
type: :development
|
218
|
-
prerelease: false
|
219
|
-
version_requirements: !ruby/object:Gem::Requirement
|
220
|
-
requirements:
|
221
|
-
- - ">="
|
222
|
-
- !ruby/object:Gem::Version
|
223
|
-
version: 1.0.1
|
224
|
-
- - "<"
|
225
|
-
- !ruby/object:Gem::Version
|
226
|
-
version: 2.0.0
|
227
|
-
description: " [4.2, 42, 42.0, 420].grep(Eqq.AND(Integer, 20..50)) #=> [42]\n"
|
11
|
+
date: 2021-06-06 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: |2
|
14
|
+
Pattern objects builder.
|
15
|
+
|
16
|
+
All products can be used as `pattern === something`.
|
17
|
+
|
18
|
+
All products can be mixed with other products as a parts.
|
19
|
+
|
20
|
+
Reuse as you wish!
|
228
21
|
email:
|
229
22
|
- kachick1+ruby@gmail.com
|
230
23
|
executables: []
|
@@ -234,7 +27,9 @@ files:
|
|
234
27
|
- MIT-LICENSE.txt
|
235
28
|
- README.md
|
236
29
|
- lib/eqq.rb
|
30
|
+
- lib/eqq/buildable.rb
|
237
31
|
- lib/eqq/version.rb
|
32
|
+
- sig/eqq.rbs
|
238
33
|
homepage: https://github.com/kachick/eqq
|
239
34
|
licenses:
|
240
35
|
- MIT
|
@@ -251,7 +46,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
251
46
|
requirements:
|
252
47
|
- - ">="
|
253
48
|
- !ruby/object:Gem::Version
|
254
|
-
version: 2.
|
49
|
+
version: 2.6.0
|
255
50
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
256
51
|
requirements:
|
257
52
|
- - ">="
|
@@ -261,5 +56,5 @@ requirements: []
|
|
261
56
|
rubygems_version: 3.2.15
|
262
57
|
signing_key:
|
263
58
|
specification_version: 4
|
264
|
-
summary: Pattern objects builder
|
59
|
+
summary: Pattern objects builder
|
265
60
|
test_files: []
|