regexer 1.0.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 +7 -0
- data/lib/regexer/exceptions/invalid_value_error.rb +12 -0
- data/lib/regexer/exceptions/no_block_given_error.rb +12 -0
- data/lib/regexer/models/pattern.rb +28 -0
- data/lib/regexer/pattern_builder.rb +201 -0
- data/lib/regexer/utils/handlers/base_handler.rb +18 -0
- data/lib/regexer/utils/handlers/quantifier_options_handlers/base.rb +24 -0
- data/lib/regexer/utils/handlers/quantifier_options_handlers/exactly_option_handler.rb +25 -0
- data/lib/regexer/utils/handlers/quantifier_options_handlers/min_max_option_handler.rb +31 -0
- data/lib/regexer/utils/handlers/quantifier_options_handlers/minimum_option_handler.rb +25 -0
- data/lib/regexer/utils/handlers/quantifier_options_handlers/no_option_handler.rb +24 -0
- data/lib/regexer/utils/handlers/single_entity_checker_value_handlers/base.rb +24 -0
- data/lib/regexer/utils/handlers/single_entity_checker_value_handlers/number_handler.rb +24 -0
- data/lib/regexer/utils/handlers/single_entity_checker_value_handlers/pattern_object_handler.rb +34 -0
- data/lib/regexer/utils/handlers/single_entity_checker_value_handlers/string_handler.rb +24 -0
- data/lib/regexer/utils/pattern_sanitizer.rb +20 -0
- data/lib/regexer/utils/quantifier_value_generator.rb +27 -0
- data/lib/regexer/utils/single_entity_checker.rb +23 -0
- data/lib/regexer/utils/string_helper.rb +15 -0
- data/lib/regexer/validators/any_character_in_validator.rb +36 -0
- data/lib/regexer/validators/ascii_character_validator.rb +27 -0
- data/lib/regexer/validators/consecutive_instances_of_options_value_validator.rb +26 -0
- data/lib/regexer/validators/contains_value_validator.rb +36 -0
- data/lib/regexer/validators/from_to_validator.rb +33 -0
- data/lib/regexer/validators/letter_validator.rb +27 -0
- data/lib/regexer/validators/number_validator.rb +27 -0
- data/lib/regexer/version.rb +5 -0
- data/lib/regexer.rb +9 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 92070599c885225a8466e24f2bf46d3b5aea40c2ec205e8da99af425bf00d4e3
|
4
|
+
data.tar.gz: 42ce090a8b56be47aa2ca63caf8ec4c85868ff7229c7fec327b02086413b2327
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8040c4d4a11602ccdf7ad2059f0474d57890af8613ba678c911dd6f2699cff6a74b18b64fbe56ef3a8b86656f849b1520ff06c4fdc4f7b8a7686dd408d008c4a
|
7
|
+
data.tar.gz: 142da4ce9ad77977a7379e514be5206647b08eb727f0422fa31af97827a29d552ddd0ed687f6a79cdababf0be6f4e00481bbd336dbde4c8c79f0ad507a935653
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Regexer
|
4
|
+
module Models
|
5
|
+
# The main model for the patterns being build by pattern builder
|
6
|
+
class Pattern
|
7
|
+
attr_reader :raw_pattern
|
8
|
+
|
9
|
+
def initialize(pattern, regex_escaped: true, single_entity: true)
|
10
|
+
@raw_pattern = pattern
|
11
|
+
@regex_escaped = regex_escaped
|
12
|
+
@single_entity = single_entity
|
13
|
+
end
|
14
|
+
|
15
|
+
def regex_escaped?
|
16
|
+
@regex_escaped
|
17
|
+
end
|
18
|
+
|
19
|
+
def single_entity?
|
20
|
+
@single_entity
|
21
|
+
end
|
22
|
+
|
23
|
+
def regex
|
24
|
+
/#{raw_pattern}/
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require "regexer/validators/from_to_validator"
|
2
|
+
require "regexer/validators/contains_value_validator"
|
3
|
+
require "regexer/validators/any_character_in_validator"
|
4
|
+
require "regexer/exceptions/no_block_given_error"
|
5
|
+
require "regexer/models/pattern"
|
6
|
+
require "regexer/utils/single_entity_checker"
|
7
|
+
require "regexer/utils/quantifier_value_generator"
|
8
|
+
require "regexer/utils/pattern_sanitizer"
|
9
|
+
require "regexer/utils/string_helper"
|
10
|
+
require "pry"
|
11
|
+
|
12
|
+
module Regexer
|
13
|
+
# A Class that contains core methods for building regex patterns
|
14
|
+
class PatternBuilder
|
15
|
+
def initialize(&block)
|
16
|
+
@final_pattern = ""
|
17
|
+
instance_exec(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def result
|
21
|
+
Regexer::Models::Pattern.new(@final_pattern, single_entity: false)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# STRUCTS
|
27
|
+
ConsecutiveOptions = Struct.new(:exactly, :minimum, :maximum)
|
28
|
+
|
29
|
+
# SPECIAL FUNCTION CHARACTERS
|
30
|
+
# MOSTLY IMPLEMENTATION OF SPECIAL CHARACTERS IN REGEX
|
31
|
+
def starts_with(value)
|
32
|
+
pattern = contains(value)&.raw_pattern
|
33
|
+
|
34
|
+
pattern_object = Regexer::Models::Pattern.new(String.new(pattern).insert(0, "^"), single_entity: false)
|
35
|
+
Regexer::Utils::StringHelper.update_string_pattern(@final_pattern, pattern, pattern_object.raw_pattern)
|
36
|
+
pattern_object
|
37
|
+
end
|
38
|
+
|
39
|
+
def ends_with(value)
|
40
|
+
pattern = contains(value)&.raw_pattern
|
41
|
+
|
42
|
+
pattern_object = Regexer::Models::Pattern.new(String.new(pattern).insert(-1, "$"), single_entity: false)
|
43
|
+
Regexer::Utils::StringHelper.update_string_pattern(@final_pattern, pattern, pattern_object.raw_pattern)
|
44
|
+
pattern_object
|
45
|
+
end
|
46
|
+
|
47
|
+
# REGEX QUANTIFIERS
|
48
|
+
def has_consecutive_instances_of(value, exactly: nil, minimum: nil, maximum: nil)
|
49
|
+
pattern = contains(value)&.raw_pattern
|
50
|
+
|
51
|
+
quantifier_pattern = Regexer::Utils::QuantifierValueGenerator
|
52
|
+
.generate(ConsecutiveOptions.new(exactly, minimum, maximum))
|
53
|
+
pattern_object = Regexer::Models::Pattern.new(
|
54
|
+
String.new(pattern).insert(-1, quantifier_pattern),
|
55
|
+
single_entity: false
|
56
|
+
)
|
57
|
+
|
58
|
+
Regexer::Utils::StringHelper.update_string_pattern(@final_pattern, pattern, pattern_object.raw_pattern)
|
59
|
+
pattern_object
|
60
|
+
end
|
61
|
+
|
62
|
+
def has_none_or_consecutive_instances_of(value)
|
63
|
+
pattern = contains(value)&.raw_pattern
|
64
|
+
|
65
|
+
pattern_object = Regexer::Models::Pattern.new(String.new(pattern).insert(-1, "*"), single_entity: false)
|
66
|
+
Regexer::Utils::StringHelper.update_string_pattern(@final_pattern, pattern, pattern_object.raw_pattern)
|
67
|
+
pattern_object
|
68
|
+
end
|
69
|
+
|
70
|
+
def has_none_or_one_instance_of(value)
|
71
|
+
pattern = contains(value)&.raw_pattern
|
72
|
+
|
73
|
+
pattern_object = Regexer::Models::Pattern.new(String.new(pattern).insert(-1, "?"), single_entity: false)
|
74
|
+
Regexer::Utils::StringHelper.update_string_pattern(@final_pattern, pattern, pattern_object.raw_pattern)
|
75
|
+
pattern_object
|
76
|
+
end
|
77
|
+
|
78
|
+
# BASIC EASE OF USE PATTERNS
|
79
|
+
def has_letter(from:, to:)
|
80
|
+
Regexer::Validators::FromToValidator.valid_values?("letter", from, to)
|
81
|
+
pattern_object = Regexer::Models::Pattern.new("[#{from}-#{to}]")
|
82
|
+
@final_pattern += pattern_object.raw_pattern
|
83
|
+
pattern_object
|
84
|
+
end
|
85
|
+
|
86
|
+
def has_number(from:, to:)
|
87
|
+
Regexer::Validators::FromToValidator.valid_values?("number", from, to)
|
88
|
+
pattern_object = Regexer::Models::Pattern.new("[#{from}-#{to}]")
|
89
|
+
@final_pattern += pattern_object.raw_pattern
|
90
|
+
pattern_object
|
91
|
+
end
|
92
|
+
|
93
|
+
def has_ascii_character(from:, to:)
|
94
|
+
Regexer::Validators::FromToValidator.valid_values?("ascii_character", from, to)
|
95
|
+
pattern_object = Regexer::Models::Pattern.new("[#{Regexp.escape(from)}-#{Regexp.escape(to)}]")
|
96
|
+
@final_pattern += pattern_object.raw_pattern
|
97
|
+
pattern_object
|
98
|
+
end
|
99
|
+
|
100
|
+
def has_word_character
|
101
|
+
pattern_object = Regexer::Models::Pattern.new("\\w")
|
102
|
+
@final_pattern += pattern_object.raw_pattern
|
103
|
+
pattern_object
|
104
|
+
end
|
105
|
+
|
106
|
+
def _or_
|
107
|
+
pattern_object = Regexer::Models::Pattern.new("\|")
|
108
|
+
@final_pattern += pattern_object.raw_pattern
|
109
|
+
pattern_object
|
110
|
+
end
|
111
|
+
|
112
|
+
def has_whitespace_character
|
113
|
+
pattern_object = Regexer::Models::Pattern.new("\\s")
|
114
|
+
@final_pattern += pattern_object.raw_pattern
|
115
|
+
pattern_object
|
116
|
+
end
|
117
|
+
|
118
|
+
def has_digit_character
|
119
|
+
pattern_object = Regexer::Models::Pattern.new("\\d")
|
120
|
+
@final_pattern += pattern_object.raw_pattern
|
121
|
+
pattern_object
|
122
|
+
end
|
123
|
+
|
124
|
+
def has_alphanumeric_character
|
125
|
+
pattern_object = Regexer::Models::Pattern.new("[A-Za-z0-9]")
|
126
|
+
@final_pattern += pattern_object.raw_pattern
|
127
|
+
pattern_object
|
128
|
+
end
|
129
|
+
|
130
|
+
def has_any_character_except_new_line
|
131
|
+
pattern_object = Regexer::Models::Pattern.new(".")
|
132
|
+
@final_pattern += pattern_object.raw_pattern
|
133
|
+
pattern_object
|
134
|
+
end
|
135
|
+
|
136
|
+
def contains(value)
|
137
|
+
Regexer::Validators::ContainsValueValidator.value_valid?(value)
|
138
|
+
|
139
|
+
sanitized_pattern = Regexer::Utils::PatternSanitizer.sanitize(value)
|
140
|
+
|
141
|
+
pattern_object = if ::Regexer::Utils::SingleEntityChecker.single_entity?(value)
|
142
|
+
Regexer::Models::Pattern.new(sanitized_pattern)
|
143
|
+
else
|
144
|
+
Regexer::Models::Pattern.new("(#{sanitized_pattern})")
|
145
|
+
end
|
146
|
+
|
147
|
+
Regexer::Utils::StringHelper.update_string_pattern(
|
148
|
+
@final_pattern,
|
149
|
+
value.instance_of?(::Regexer::Models::Pattern) ? sanitized_pattern : "",
|
150
|
+
pattern_object.raw_pattern
|
151
|
+
)
|
152
|
+
pattern_object
|
153
|
+
end
|
154
|
+
|
155
|
+
def has_group(&block)
|
156
|
+
raise Regexer::Exceptions::NoBlockGivenError unless block_given?
|
157
|
+
|
158
|
+
value = Regexer::PatternBuilder.new(&block).result
|
159
|
+
sanitized_pattern = Regexer::Utils::PatternSanitizer.sanitize(value)
|
160
|
+
pattern_object = Regexer::Models::Pattern.new("(#{sanitized_pattern})")
|
161
|
+
Regexer::Utils::StringHelper.update_string_pattern(@final_pattern, sanitized_pattern, pattern_object.raw_pattern)
|
162
|
+
pattern_object
|
163
|
+
end
|
164
|
+
|
165
|
+
def has_any_character_in(*values)
|
166
|
+
combined_pattern = values.reduce("") do |pattern, value|
|
167
|
+
Regexer::Validators::AnyCharacterInValidator.value_valid?(value)
|
168
|
+
if value.instance_of?(Hash)
|
169
|
+
Regexer::Validators::FromToValidator.valid_values?("ascii_character", value[:from], value[:to])
|
170
|
+
pattern + "#{value[:from]}-#{value[:to]}"
|
171
|
+
else
|
172
|
+
pattern + Regexer::Utils::PatternSanitizer.sanitize(value)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
pattern_object = Regexer::Models::Pattern.new("[#{combined_pattern}]")
|
177
|
+
@final_pattern += pattern_object.raw_pattern
|
178
|
+
pattern_object
|
179
|
+
end
|
180
|
+
|
181
|
+
# VALUE BUILDER METHOD THAT IS COMPATIBILE WITH THE PATTERN BUILDER
|
182
|
+
def character_range(from:, to:)
|
183
|
+
Regexer::Validators::FromToValidator.valid_values?("ascii_character", from, to)
|
184
|
+
{ from: Regexp.escape(from), to: Regexp.escape(to) }
|
185
|
+
end
|
186
|
+
|
187
|
+
alias word_character has_word_character
|
188
|
+
alias whitespace_character has_whitespace_character
|
189
|
+
alias digit_character has_digit_character
|
190
|
+
alias alphanumeric_character has_alphanumeric_character
|
191
|
+
alias any_character_except_new_line has_any_character_except_new_line
|
192
|
+
alias letter has_letter
|
193
|
+
alias number has_number
|
194
|
+
alias ascii_character has_ascii_character
|
195
|
+
alias consecutive_instances_of has_consecutive_instances_of
|
196
|
+
alias none_or_consecutive_instances_of has_none_or_consecutive_instances_of
|
197
|
+
alias none_or_one_instance_of has_none_or_one_instance_of
|
198
|
+
alias group has_group
|
199
|
+
alias any_character_in has_any_character_in
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Regexer
|
4
|
+
module Utils
|
5
|
+
module Handlers
|
6
|
+
# A Base interface class for handlers
|
7
|
+
class BaseHandler
|
8
|
+
def handle
|
9
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
10
|
+
end
|
11
|
+
|
12
|
+
def next_handler(_handler)
|
13
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/base_handler"
|
4
|
+
|
5
|
+
module Regexer
|
6
|
+
module Utils
|
7
|
+
module Handlers
|
8
|
+
module QuantifierOptionsHandler
|
9
|
+
# The base class for the quantifier options handler
|
10
|
+
class Base < ::Regexer::Utils::Handlers::BaseHandler
|
11
|
+
def next_handler(handler)
|
12
|
+
@next_handler = handler
|
13
|
+
|
14
|
+
handler
|
15
|
+
end
|
16
|
+
|
17
|
+
def give_to_next_handler(value)
|
18
|
+
@next_handler&.handle(value) if @next_handler
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/quantifier_options_handlers/base"
|
4
|
+
require "regexer/validators/consecutive_instances_of_options_value_validator"
|
5
|
+
|
6
|
+
module Regexer
|
7
|
+
module Utils
|
8
|
+
module Handlers
|
9
|
+
module QuantifierOptionsHandler
|
10
|
+
# A handler class to return the appropriate quantifier value
|
11
|
+
# if given the exactly option
|
12
|
+
class ExactlyOptionHandler < Base
|
13
|
+
def handle(value)
|
14
|
+
if value.exactly
|
15
|
+
Regexer::Validators::ConsecutiveInstancesOfOptionsValueValidator.value_valid?(value.exactly)
|
16
|
+
"{#{value.exactly}}"
|
17
|
+
else
|
18
|
+
give_to_next_handler(value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/quantifier_options_handlers/base"
|
4
|
+
require "regexer/validators/consecutive_instances_of_options_value_validator"
|
5
|
+
|
6
|
+
module Regexer
|
7
|
+
module Utils
|
8
|
+
module Handlers
|
9
|
+
module QuantifierOptionsHandler
|
10
|
+
# A handler class to return the appropriate quantifier value
|
11
|
+
# if given the minimum & maximum options only
|
12
|
+
class MinMaxOptionHandler < Base
|
13
|
+
def handle(value)
|
14
|
+
if value.maximum
|
15
|
+
raise ArgumentError, "missing minimum keyword argument" unless value.minimum
|
16
|
+
|
17
|
+
Regexer::Validators::ConsecutiveInstancesOfOptionsValueValidator.value_valid?(value.minimum)
|
18
|
+
Regexer::Validators::ConsecutiveInstancesOfOptionsValueValidator.value_valid?(value.maximum)
|
19
|
+
Regexer::Validators::ConsecutiveInstancesOfOptionsValueValidator
|
20
|
+
.min_max_range_valid?(value.minimum, value.maximum)
|
21
|
+
|
22
|
+
"{#{value.minimum},#{value.maximum}}"
|
23
|
+
else
|
24
|
+
give_to_next_handler(value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/quantifier_options_handlers/base"
|
4
|
+
require "regexer/validators/consecutive_instances_of_options_value_validator"
|
5
|
+
|
6
|
+
module Regexer
|
7
|
+
module Utils
|
8
|
+
module Handlers
|
9
|
+
module QuantifierOptionsHandler
|
10
|
+
# A handler class to return the appropriate quantifier value
|
11
|
+
# if given the minimum option only
|
12
|
+
class MinimumOptionHandler < Base
|
13
|
+
def handle(value)
|
14
|
+
if value.minimum && !value.maximum
|
15
|
+
Regexer::Validators::ConsecutiveInstancesOfOptionsValueValidator.value_valid?(value.minimum)
|
16
|
+
"{#{value.minimum},}"
|
17
|
+
else
|
18
|
+
give_to_next_handler(value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/quantifier_options_handlers/base"
|
4
|
+
require "regexer/validators/consecutive_instances_of_options_value_validator"
|
5
|
+
|
6
|
+
module Regexer
|
7
|
+
module Utils
|
8
|
+
module Handlers
|
9
|
+
module QuantifierOptionsHandler
|
10
|
+
# A handler class to return the appropriate quantifier value
|
11
|
+
# if given no options
|
12
|
+
class NoOptionHandler < Base
|
13
|
+
def handle(value)
|
14
|
+
if !value.exactly && !value.minimum && !value.maximum
|
15
|
+
"+"
|
16
|
+
else
|
17
|
+
give_to_next_handler(value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/base_handler"
|
4
|
+
|
5
|
+
module Regexer
|
6
|
+
module Utils
|
7
|
+
module Handlers
|
8
|
+
module SingleEntityCheckerValueHandler
|
9
|
+
# The base class for the single engtity checker value handler
|
10
|
+
class Base < ::Regexer::Utils::Handlers::BaseHandler
|
11
|
+
def next_handler(handler)
|
12
|
+
@next_handler = handler
|
13
|
+
|
14
|
+
handler
|
15
|
+
end
|
16
|
+
|
17
|
+
def give_to_next_handler(value)
|
18
|
+
@next_handler&.handle(value) if @next_handler
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/single_entity_checker_value_handlers/base"
|
4
|
+
|
5
|
+
module Regexer
|
6
|
+
module Utils
|
7
|
+
module Handlers
|
8
|
+
module SingleEntityCheckerValueHandler
|
9
|
+
# A handler class to check if a number is considered as single entity or not
|
10
|
+
# if this handler sees that the value is not a number, it will then pass it to
|
11
|
+
# the next handler
|
12
|
+
class NumberHandler < Base
|
13
|
+
def handle(value)
|
14
|
+
if value.instance_of?(Integer)
|
15
|
+
value.digits.length == 1
|
16
|
+
else
|
17
|
+
give_to_next_handler(value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/regexer/utils/handlers/single_entity_checker_value_handlers/pattern_object_handler.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/single_entity_checker_value_handlers/base"
|
4
|
+
|
5
|
+
module Regexer
|
6
|
+
module Utils
|
7
|
+
module Handlers
|
8
|
+
module SingleEntityCheckerValueHandler
|
9
|
+
# A handler class to check if a pattern object is considered as single entity or not
|
10
|
+
# if this handler sees that the value is not a pattern object, it will then pass it to
|
11
|
+
# the next handler
|
12
|
+
class PatternObjectHandler < Base
|
13
|
+
def handle(value)
|
14
|
+
if value.instance_of?(::Regexer::Models::Pattern)
|
15
|
+
value.single_entity?
|
16
|
+
else
|
17
|
+
give_to_next_handler(value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def wrapped_in_parentheses?(value)
|
24
|
+
value.raw_pattern[0] == "(" && value.raw_pattern[-1] == ")"
|
25
|
+
end
|
26
|
+
|
27
|
+
def wrapped_in_square_brackets?(value)
|
28
|
+
value.raw_pattern[0] == "[" && value.raw_pattern[-1] == "]"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/single_entity_checker_value_handlers/base"
|
4
|
+
|
5
|
+
module Regexer
|
6
|
+
module Utils
|
7
|
+
module Handlers
|
8
|
+
module SingleEntityCheckerValueHandler
|
9
|
+
# A handler class to check if a string value is considered as single entity or not
|
10
|
+
# if this handler sees that the value is not a string, it will then pass it to
|
11
|
+
# the next handler
|
12
|
+
class StringHandler < Base
|
13
|
+
def handle(value)
|
14
|
+
if value.instance_of?(String)
|
15
|
+
value.length == 1
|
16
|
+
else
|
17
|
+
give_to_next_handler(value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/models/pattern"
|
4
|
+
|
5
|
+
module Regexer
|
6
|
+
module Utils
|
7
|
+
# A Utility Class that sanitizes a given value (mostly values given from the pattern builder)
|
8
|
+
# that is valid for regex
|
9
|
+
class PatternSanitizer
|
10
|
+
def self.sanitize(value)
|
11
|
+
if value.instance_of?(Regexer::Models::Pattern)
|
12
|
+
sanitize(value.raw_pattern) unless value.regex_escaped?
|
13
|
+
value.raw_pattern
|
14
|
+
else
|
15
|
+
Regexp.escape(value.to_s)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/quantifier_options_handlers/exactly_option_handler"
|
4
|
+
require "regexer/utils/handlers/quantifier_options_handlers/minimum_option_handler"
|
5
|
+
require "regexer/utils/handlers/quantifier_options_handlers/min_max_option_handler"
|
6
|
+
require "regexer/utils/handlers/quantifier_options_handlers/no_option_handler"
|
7
|
+
|
8
|
+
module Regexer
|
9
|
+
module Utils
|
10
|
+
# A Utility Class that generates a quantifier value based on
|
11
|
+
# the given options
|
12
|
+
class QuantifierValueGenerator
|
13
|
+
def self.generate(value)
|
14
|
+
exactly_option_handler = ::Regexer::Utils::Handlers::QuantifierOptionsHandler::ExactlyOptionHandler.new
|
15
|
+
minimum_option_handler = ::Regexer::Utils::Handlers::QuantifierOptionsHandler::MinimumOptionHandler.new
|
16
|
+
min_max_option_handler = ::Regexer::Utils::Handlers::QuantifierOptionsHandler::MinMaxOptionHandler.new
|
17
|
+
no_option_handler = ::Regexer::Utils::Handlers::QuantifierOptionsHandler::NoOptionHandler.new
|
18
|
+
|
19
|
+
exactly_option_handler.next_handler(minimum_option_handler)
|
20
|
+
.next_handler(min_max_option_handler)
|
21
|
+
.next_handler(no_option_handler)
|
22
|
+
|
23
|
+
exactly_option_handler.handle(value) || ""
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/utils/handlers/single_entity_checker_value_handlers/string_handler"
|
4
|
+
require "regexer/utils/handlers/single_entity_checker_value_handlers/number_handler"
|
5
|
+
require "regexer/utils/handlers/single_entity_checker_value_handlers/pattern_object_handler"
|
6
|
+
|
7
|
+
module Regexer
|
8
|
+
module Utils
|
9
|
+
# A Utility Class that checks if a value is a single entity or not
|
10
|
+
class SingleEntityChecker
|
11
|
+
def self.single_entity?(value)
|
12
|
+
string_handler = ::Regexer::Utils::Handlers::SingleEntityCheckerValueHandler::StringHandler.new
|
13
|
+
number_handler = ::Regexer::Utils::Handlers::SingleEntityCheckerValueHandler::NumberHandler.new
|
14
|
+
pattern_object_handler = ::Regexer::Utils::Handlers::SingleEntityCheckerValueHandler::PatternObjectHandler.new
|
15
|
+
|
16
|
+
string_handler.next_handler(number_handler)
|
17
|
+
.next_handler(pattern_object_handler)
|
18
|
+
|
19
|
+
string_handler.handle(value) || false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Regexer
|
2
|
+
module Utils
|
3
|
+
# A Utility Class that contains helper methods
|
4
|
+
# in dealing with strings
|
5
|
+
class StringHelper
|
6
|
+
def self.update_string_pattern(pattern_to_update, previous_appended_pattern, new_pattern)
|
7
|
+
if !previous_appended_pattern.empty? && pattern_to_update.end_with?(previous_appended_pattern)
|
8
|
+
pattern_to_update.sub!(/(#{Regexp.escape(previous_appended_pattern)})$/) { new_pattern }
|
9
|
+
else
|
10
|
+
pattern_to_update << new_pattern
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/exceptions/invalid_value_error"
|
4
|
+
require "regexer/models/pattern"
|
5
|
+
|
6
|
+
module Regexer
|
7
|
+
module Validators
|
8
|
+
# A Validator Class for validating values being passed to has_any_character_in Regexer::Pattern method
|
9
|
+
class AnyCharacterInValidator
|
10
|
+
def self.value_valid?(value)
|
11
|
+
error_message = "Value should only be of type String or Integer or Hash with from & to keys"
|
12
|
+
raise Regexer::Exceptions::InvalidValueError, error_message unless valid?(value)
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
private
|
17
|
+
|
18
|
+
def number?(value)
|
19
|
+
value.instance_of?(Integer) || value.instance_of?(Float)
|
20
|
+
end
|
21
|
+
|
22
|
+
def string?(value)
|
23
|
+
value.instance_of?(String)
|
24
|
+
end
|
25
|
+
|
26
|
+
def from_to_hash?(value)
|
27
|
+
value.instance_of?(Hash) && value.keys == %i[from to]
|
28
|
+
end
|
29
|
+
|
30
|
+
def valid?(value)
|
31
|
+
number?(value) || string?(value) || from_to_hash?(value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/exceptions/invalid_value_error"
|
4
|
+
|
5
|
+
module Regexer
|
6
|
+
module Validators
|
7
|
+
# A Validator Class for validating if a value is a single letter
|
8
|
+
class AsciiCharacterValidator
|
9
|
+
def self.ascii_character?(value)
|
10
|
+
error_message = "Value should only be a single character in the ascii table"
|
11
|
+
raise Regexer::Exceptions::InvalidValueError, error_message unless string?(value) && single_ascii_letter?(value)
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
private
|
16
|
+
|
17
|
+
def string?(value)
|
18
|
+
value.instance_of?(String)
|
19
|
+
end
|
20
|
+
|
21
|
+
def single_ascii_letter?(value)
|
22
|
+
value.length == 1 && value.match?(/[[:ascii:]]/)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/exceptions/invalid_value_error"
|
4
|
+
|
5
|
+
module Regexer
|
6
|
+
module Validators
|
7
|
+
# A Validator Class for validating option values being passed to consecutive_instances_of Regexer::Pattern method
|
8
|
+
class ConsecutiveInstancesOfOptionsValueValidator
|
9
|
+
def self.value_valid?(value)
|
10
|
+
error_message = "Value should only be of type Integer"
|
11
|
+
|
12
|
+
raise Regexer::Exceptions::InvalidValueError, error_message unless integer?(value)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.min_max_range_valid?(min_value, max_value)
|
16
|
+
error_message = "minimum value is larger than maximum value"
|
17
|
+
|
18
|
+
raise RangeError, error_message unless min_value < max_value
|
19
|
+
end
|
20
|
+
|
21
|
+
private_class_method def self.integer?(value)
|
22
|
+
value.instance_of?(Integer)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/exceptions/invalid_value_error"
|
4
|
+
require "regexer/models/pattern"
|
5
|
+
|
6
|
+
module Regexer
|
7
|
+
module Validators
|
8
|
+
# A Validator Class for validating values being passed to contains Regexer::Pattern method
|
9
|
+
class ContainsValueValidator
|
10
|
+
def self.value_valid?(value)
|
11
|
+
error_message = "Value should only be of type String or Integer or Float or Regexer::Models::Pattern"
|
12
|
+
raise Regexer::Exceptions::InvalidValueError, error_message unless valid?(value)
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
private
|
17
|
+
|
18
|
+
def number?(value)
|
19
|
+
value.instance_of?(Integer) || value.instance_of?(Float)
|
20
|
+
end
|
21
|
+
|
22
|
+
def string?(value)
|
23
|
+
value.instance_of?(String)
|
24
|
+
end
|
25
|
+
|
26
|
+
def pattern?(value)
|
27
|
+
value.instance_of?(Regexer::Models::Pattern)
|
28
|
+
end
|
29
|
+
|
30
|
+
def valid?(value)
|
31
|
+
number?(value) || string?(value) || pattern?(value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/validators/letter_validator"
|
4
|
+
require "regexer/validators/number_validator"
|
5
|
+
require "regexer/validators/ascii_character_validator"
|
6
|
+
|
7
|
+
module Regexer
|
8
|
+
module Validators
|
9
|
+
# A Validator Class for validating range values in Regexer::Pattern methods
|
10
|
+
# that takes in from and to values as method arguments
|
11
|
+
class FromToValidator
|
12
|
+
def self.valid_values?(value_type, from_value, to_value)
|
13
|
+
case value_type
|
14
|
+
when "number"
|
15
|
+
Regexer::Validators::NumberValidator.number?(from_value)
|
16
|
+
Regexer::Validators::NumberValidator.number?(to_value)
|
17
|
+
when "letter"
|
18
|
+
Regexer::Validators::LetterValidator.letter?(from_value)
|
19
|
+
Regexer::Validators::LetterValidator.letter?(to_value)
|
20
|
+
when "ascii_character"
|
21
|
+
Regexer::Validators::AsciiCharacterValidator.ascii_character?(from_value)
|
22
|
+
Regexer::Validators::AsciiCharacterValidator.ascii_character?(to_value)
|
23
|
+
end
|
24
|
+
|
25
|
+
validate_range(from_value, to_value)
|
26
|
+
end
|
27
|
+
|
28
|
+
private_class_method def self.validate_range(from_value, to_value)
|
29
|
+
raise RangeError, "From value is greater than the To value" if from_value > to_value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/exceptions/invalid_value_error"
|
4
|
+
|
5
|
+
module Regexer
|
6
|
+
module Validators
|
7
|
+
# A Validator Class for validating if a value is a single letter
|
8
|
+
class LetterValidator
|
9
|
+
def self.letter?(value)
|
10
|
+
error_message = "Value should only be a single letter"
|
11
|
+
raise Regexer::Exceptions::InvalidValueError, error_message unless string?(value) && single_letter?(value)
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
private
|
16
|
+
|
17
|
+
def string?(value)
|
18
|
+
value.instance_of?(String)
|
19
|
+
end
|
20
|
+
|
21
|
+
def single_letter?(value)
|
22
|
+
value.length == 1 && value.match?(/[[:alpha:]]/)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "regexer/exceptions/invalid_value_error"
|
4
|
+
|
5
|
+
module Regexer
|
6
|
+
module Validators
|
7
|
+
# A Validator Class for validating if a value is an integer from 0 - 9
|
8
|
+
class NumberValidator
|
9
|
+
def self.number?(value)
|
10
|
+
error_message = "Value should only be an integer from 0 to 9"
|
11
|
+
raise Regexer::Exceptions::InvalidValueError, error_message unless integer?(value) && in_0_to_9?(value)
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
private
|
16
|
+
|
17
|
+
def integer?(value)
|
18
|
+
value.instance_of?(Integer)
|
19
|
+
end
|
20
|
+
|
21
|
+
def in_0_to_9?(value)
|
22
|
+
(0..9).to_a.include?(value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/regexer.rb
ADDED
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: regexer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Genesis Ivan Ilagan
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-08-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.13.1
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.13.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '13.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '13.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.7'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.7'
|
69
|
+
description: A ruby DSL for building regex patterns in a human readable format. Regexer
|
70
|
+
aims in making regex more easily read, learned and understood at first glance. Syntax
|
71
|
+
wise, it is inspired by FactoryBot and RSpec
|
72
|
+
email:
|
73
|
+
- ivanilagan1109@gmail.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- lib/regexer.rb
|
79
|
+
- lib/regexer/exceptions/invalid_value_error.rb
|
80
|
+
- lib/regexer/exceptions/no_block_given_error.rb
|
81
|
+
- lib/regexer/models/pattern.rb
|
82
|
+
- lib/regexer/pattern_builder.rb
|
83
|
+
- lib/regexer/utils/handlers/base_handler.rb
|
84
|
+
- lib/regexer/utils/handlers/quantifier_options_handlers/base.rb
|
85
|
+
- lib/regexer/utils/handlers/quantifier_options_handlers/exactly_option_handler.rb
|
86
|
+
- lib/regexer/utils/handlers/quantifier_options_handlers/min_max_option_handler.rb
|
87
|
+
- lib/regexer/utils/handlers/quantifier_options_handlers/minimum_option_handler.rb
|
88
|
+
- lib/regexer/utils/handlers/quantifier_options_handlers/no_option_handler.rb
|
89
|
+
- lib/regexer/utils/handlers/single_entity_checker_value_handlers/base.rb
|
90
|
+
- lib/regexer/utils/handlers/single_entity_checker_value_handlers/number_handler.rb
|
91
|
+
- lib/regexer/utils/handlers/single_entity_checker_value_handlers/pattern_object_handler.rb
|
92
|
+
- lib/regexer/utils/handlers/single_entity_checker_value_handlers/string_handler.rb
|
93
|
+
- lib/regexer/utils/pattern_sanitizer.rb
|
94
|
+
- lib/regexer/utils/quantifier_value_generator.rb
|
95
|
+
- lib/regexer/utils/single_entity_checker.rb
|
96
|
+
- lib/regexer/utils/string_helper.rb
|
97
|
+
- lib/regexer/validators/any_character_in_validator.rb
|
98
|
+
- lib/regexer/validators/ascii_character_validator.rb
|
99
|
+
- lib/regexer/validators/consecutive_instances_of_options_value_validator.rb
|
100
|
+
- lib/regexer/validators/contains_value_validator.rb
|
101
|
+
- lib/regexer/validators/from_to_validator.rb
|
102
|
+
- lib/regexer/validators/letter_validator.rb
|
103
|
+
- lib/regexer/validators/number_validator.rb
|
104
|
+
- lib/regexer/version.rb
|
105
|
+
homepage: https://github.com/IvanIlagan/regexer-ruby
|
106
|
+
licenses:
|
107
|
+
- MIT
|
108
|
+
metadata:
|
109
|
+
homepage_uri: https://github.com/IvanIlagan/regexer-ruby
|
110
|
+
source_code_uri: https://github.com/IvanIlagan/regexer-ruby
|
111
|
+
changelog_uri: https://github.com/IvanIlagan/regexer-ruby/blob/main/CHANGELOG.md
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options: []
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 2.5.0
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubygems_version: 3.2.22
|
128
|
+
signing_key:
|
129
|
+
specification_version: 4
|
130
|
+
summary: A ruby DSL for generating regex patterns
|
131
|
+
test_files: []
|