regexp-examples 0.3.2 → 0.4.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/README.md +39 -3
- data/coverage/.resultset.json +212 -173
- data/coverage/index.html +1219 -985
- data/lib/regexp-examples/backreferences.rb +11 -5
- data/lib/regexp-examples/constants.rb +30 -13
- data/lib/regexp-examples/exceptions.rb +1 -0
- data/lib/regexp-examples/groups.rb +3 -9
- data/lib/regexp-examples/helpers.rb +1 -1
- data/lib/regexp-examples/parser.rb +5 -1
- data/lib/regexp-examples/regexp_extensions.rb +3 -3
- data/lib/regexp-examples/repeaters.rb +12 -8
- data/lib/regexp-examples/version.rb +1 -1
- data/spec/regexp-examples_spec.rb +28 -2
- metadata +2 -2
@@ -2,18 +2,24 @@ module RegexpExamples
|
|
2
2
|
class BackReferenceReplacer
|
3
3
|
def substitute_backreferences(full_examples)
|
4
4
|
full_examples.map do |full_example|
|
5
|
-
|
6
|
-
full_example.
|
5
|
+
begin
|
6
|
+
while full_example.match(/__(\w+?)__/)
|
7
|
+
full_example.sub!(/__(\w+?)__/, find_backref_for(full_example, $1))
|
8
|
+
end
|
9
|
+
full_example
|
10
|
+
rescue RegexpExamples::BackrefNotFound
|
11
|
+
# For instance, one "full example" from /(a|(b)) \2/: "a __2__"
|
12
|
+
# should be rejected because the backref (\2) does not exist
|
13
|
+
nil
|
7
14
|
end
|
8
|
-
|
9
|
-
end
|
15
|
+
end.compact
|
10
16
|
end
|
11
17
|
|
12
18
|
private
|
13
19
|
def find_backref_for(full_example, group_id)
|
14
20
|
full_example.all_subgroups.detect do |subgroup|
|
15
21
|
subgroup.group_id == group_id
|
16
|
-
end
|
22
|
+
end || raise(RegexpExamples::BackrefNotFound)
|
17
23
|
end
|
18
24
|
|
19
25
|
end
|
@@ -1,18 +1,35 @@
|
|
1
1
|
module RegexpExamples
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
class ResultCountLimiters
|
3
|
+
# The maximum variance for any given repeater, to prevent a huge/infinite number of
|
4
|
+
# examples from being listed. For example, if @@max_repeater_variance = 2 then:
|
5
|
+
# .* is equivalent to .{0,2}
|
6
|
+
# .+ is equivalent to .{1,3}
|
7
|
+
# .{2,} is equivalent to .{2,4}
|
8
|
+
# .{,3} is equivalent to .{0,2}
|
9
|
+
# .{3,8} is equivalent to .{3,5}
|
10
|
+
MaxRepeaterVarianceDefault = 2
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
# Maximum number of characters returned from a char set, to reduce output spam
|
13
|
+
# For example, if @@max_group_results = 5 then:
|
14
|
+
# \d = ["0", "1", "2", "3", "4"]
|
15
|
+
# \w = ["a", "b", "c", "d", "e"]
|
16
|
+
MaxGroupResultsDefault = 5
|
17
|
+
|
18
|
+
class << self
|
19
|
+
attr_reader :max_repeater_variance, :max_group_results
|
20
|
+
def configure!(max_repeater_variance, max_group_results)
|
21
|
+
@max_repeater_variance = (max_repeater_variance || MaxRepeaterVarianceDefault)
|
22
|
+
@max_group_results = (max_group_results || MaxGroupResultsDefault)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.MaxRepeaterVariance
|
28
|
+
ResultCountLimiters.max_repeater_variance
|
29
|
+
end
|
30
|
+
def self.MaxGroupResults
|
31
|
+
ResultCountLimiters.max_group_results
|
32
|
+
end
|
16
33
|
|
17
34
|
module CharSets
|
18
35
|
Lower = Array('a'..'z')
|
@@ -16,12 +16,6 @@ module RegexpExamples
|
|
16
16
|
def all_subgroups
|
17
17
|
[self, subgroups].flatten.reject { |subgroup| subgroup.group_id.nil? }
|
18
18
|
end
|
19
|
-
|
20
|
-
# Overridden in order to preserve the @group_id and @subgroups
|
21
|
-
# Used by BaseGroup (which, in turn, is used by all Group objects)
|
22
|
-
def *(int)
|
23
|
-
self.class.new(super.to_s, group_id, subgroups)
|
24
|
-
end
|
25
19
|
end
|
26
20
|
|
27
21
|
class SingleCharGroup
|
@@ -120,7 +114,7 @@ module RegexpExamples
|
|
120
114
|
# itself
|
121
115
|
def result
|
122
116
|
strings = @groups.map {|repeater| repeater.result}
|
123
|
-
RegexpExamples
|
117
|
+
RegexpExamples.permutations_of_strings(strings).map do |result|
|
124
118
|
GroupResult.new(result, group_id)
|
125
119
|
end
|
126
120
|
end
|
@@ -137,8 +131,8 @@ module RegexpExamples
|
|
137
131
|
|
138
132
|
|
139
133
|
def result
|
140
|
-
left_result = RegexpExamples
|
141
|
-
right_result = RegexpExamples
|
134
|
+
left_result = RegexpExamples.map_results(@left_repeaters)
|
135
|
+
right_result = RegexpExamples.map_results(@right_repeaters)
|
142
136
|
left_result.concat(right_result).flatten.uniq.map do |result|
|
143
137
|
GroupResult.new(result)
|
144
138
|
end
|
@@ -1,10 +1,14 @@
|
|
1
1
|
module RegexpExamples
|
2
2
|
class Parser
|
3
3
|
attr_reader :regexp_string
|
4
|
-
def initialize(regexp_string)
|
4
|
+
def initialize(regexp_string, options={})
|
5
5
|
@regexp_string = regexp_string
|
6
6
|
@num_groups = 0
|
7
7
|
@current_position = 0
|
8
|
+
RegexpExamples::ResultCountLimiters.configure!(
|
9
|
+
options[:max_repeater_variance],
|
10
|
+
options[:max_group_results]
|
11
|
+
)
|
8
12
|
end
|
9
13
|
|
10
14
|
def parse
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class Regexp
|
2
2
|
module Examples
|
3
|
-
def examples
|
4
|
-
full_examples = RegexpExamples
|
5
|
-
RegexpExamples::Parser.new(source).parse
|
3
|
+
def examples(options={})
|
4
|
+
full_examples = RegexpExamples.map_results(
|
5
|
+
RegexpExamples::Parser.new(source, options).parse
|
6
6
|
)
|
7
7
|
RegexpExamples::BackReferenceReplacer.new.substitute_backreferences(full_examples)
|
8
8
|
end
|
@@ -6,14 +6,18 @@ module RegexpExamples
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def result(min_repeats, max_repeats)
|
9
|
-
group_results = @group.result[0 .. MaxGroupResults-1]
|
9
|
+
group_results = @group.result[0 .. RegexpExamples.MaxGroupResults-1]
|
10
10
|
results = []
|
11
11
|
min_repeats.upto(max_repeats) do |repeats|
|
12
|
-
|
13
|
-
results <<
|
12
|
+
if repeats.zero?
|
13
|
+
results << [ GroupResult.new('') ]
|
14
|
+
else
|
15
|
+
results << RegexpExamples.permutations_of_strings(
|
16
|
+
[group_results] * repeats
|
17
|
+
)
|
14
18
|
end
|
15
19
|
end
|
16
|
-
results.uniq
|
20
|
+
results.flatten.uniq
|
17
21
|
end
|
18
22
|
end
|
19
23
|
|
@@ -33,7 +37,7 @@ module RegexpExamples
|
|
33
37
|
end
|
34
38
|
|
35
39
|
def result
|
36
|
-
super(0, MaxRepeaterVariance)
|
40
|
+
super(0, RegexpExamples.MaxRepeaterVariance)
|
37
41
|
end
|
38
42
|
end
|
39
43
|
|
@@ -43,7 +47,7 @@ module RegexpExamples
|
|
43
47
|
end
|
44
48
|
|
45
49
|
def result
|
46
|
-
super(1, MaxRepeaterVariance + 1)
|
50
|
+
super(1, RegexpExamples.MaxRepeaterVariance + 1)
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
@@ -63,9 +67,9 @@ module RegexpExamples
|
|
63
67
|
@min = min || 0
|
64
68
|
if max
|
65
69
|
# Prevent huge number of results in case of e.g. /.{1,100}/.examples
|
66
|
-
@max = smallest(max, @min + MaxRepeaterVariance)
|
70
|
+
@max = smallest(max, @min + RegexpExamples.MaxRepeaterVariance)
|
67
71
|
elsif has_comma
|
68
|
-
@max = @min + MaxRepeaterVariance
|
72
|
+
@max = @min + RegexpExamples.MaxRepeaterVariance
|
69
73
|
else
|
70
74
|
@max = @min
|
71
75
|
end
|
@@ -115,7 +115,9 @@ RSpec.describe Regexp, "#examples" do
|
|
115
115
|
/((ref2)ref1) \1 \2/,
|
116
116
|
/((ref1and2)) \1 \2/,
|
117
117
|
/(one)(two)(three)(four)(five)(six)(seven)(eight)(nine)(ten) \10\9\8\7\6\5\4\3\2\1/,
|
118
|
-
/(a?(b?(c?(d?(e?)))))
|
118
|
+
/(a?(b?(c?(d?(e?)))))/,
|
119
|
+
/(a)? \1/,
|
120
|
+
/(a|(b)) \2/
|
119
121
|
)
|
120
122
|
end
|
121
123
|
|
@@ -208,12 +210,36 @@ RSpec.describe Regexp, "#examples" do
|
|
208
210
|
/[^\h\H]/,
|
209
211
|
/[^\D0-9]/,
|
210
212
|
/[^\Wa-zA-Z0-9_]/,
|
211
|
-
/[^\d\D]*/,
|
212
213
|
/[^\d\D]+/,
|
213
214
|
/[^\d\D]{2}/,
|
214
215
|
/[^\d\D]word/
|
215
216
|
)
|
216
217
|
end
|
217
218
|
|
219
|
+
context "exact examples match" do
|
220
|
+
# More rigorous tests to assert that ALL examples are being listed
|
221
|
+
context "default options" do
|
222
|
+
it { expect(/[ab]{2}/.examples).to eq ["aa", "ab", "ba", "bb"] }
|
223
|
+
it { expect(/(a|b){2}/.examples).to eq ["aa", "ab", "ba", "bb"] }
|
224
|
+
it { expect(/a+|b?/.examples).to eq ["a", "aa", "aaa", "", "b"] }
|
225
|
+
end
|
226
|
+
context "max_repeater_variance option" do
|
227
|
+
it do
|
228
|
+
expect(/a+/.examples(max_repeater_variance: 5))
|
229
|
+
.to eq %w(a aa aaa aaaa aaaaa aaaaaa)
|
230
|
+
end
|
231
|
+
it do
|
232
|
+
expect(/a{4,8}/.examples(max_repeater_variance: 0))
|
233
|
+
.to eq %w(aaaa)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
context "max_group_results option" do
|
237
|
+
it do
|
238
|
+
expect(/\d/.examples(max_group_results: 10))
|
239
|
+
.to eq %w(0 1 2 3 4 5 6 7 8 9)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
218
244
|
end
|
219
245
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: regexp-examples
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Lord
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|