regexp-examples 1.1.4 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/README.md +51 -29
- data/db/unicode_ranges_2.1.pstore +0 -0
- data/lib/core_extensions/regexp/examples.rb +10 -9
- data/lib/regexp-examples.rb +1 -0
- data/lib/regexp-examples/constants.rb +11 -2
- data/lib/regexp-examples/groups.rb +5 -3
- data/lib/regexp-examples/helpers.rb +11 -19
- data/lib/regexp-examples/max_results_limiter.rb +58 -0
- data/lib/regexp-examples/repeaters.rb +9 -7
- data/lib/regexp-examples/version.rb +1 -1
- data/spec/regexp-examples_spec.rb +35 -0
- metadata +4 -3
- data/db/unicode_ranges_2.1.pstore +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47da78b8a954d0a3cc88910fffd716e34675d953
|
4
|
+
data.tar.gz: 69705d5fa7a10b0e4980fd6036b8aa8b29486947
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 224d21492ee5097eac3700ea168866f04f32e62e0bb8a2e2fd955a2398df27e5ff97daf9907ed0e27e3523238b020ef676243ecc9bc888dc24aad49565d4fae0
|
7
|
+
data.tar.gz: 91c0d6413d6f7ef35e8cb3a20dda797eb33b26ec4e6da88e23afad5c02e0f61fea3fceeb8afd2727980efbbe7667051e6c0df92e8f2e576cbc99354113d7f18b
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -15,7 +15,7 @@ or a huge number of possible matches, such as `/.\w/`, then only a subset of the
|
|
15
15
|
|
16
16
|
For more detail on this, see [configuration options](#configuration-options).
|
17
17
|
|
18
|
-
If you'd like to understand how/why this gem works, please check out my [blog post](http://tom-lord.weebly.com/blog/reverse-engineering-regular-expressions) about it
|
18
|
+
If you'd like to understand how/why this gem works, please check out my [blog post](http://tom-lord.weebly.com/blog/reverse-engineering-regular-expressions) about it.
|
19
19
|
|
20
20
|
## Usage
|
21
21
|
|
@@ -46,6 +46,24 @@ If you'd like to understand how/why this gem works, please check out my [blog po
|
|
46
46
|
/written by tom lord/i.random_example #=> "WrITtEN bY tOM LORD"
|
47
47
|
```
|
48
48
|
|
49
|
+
## Supported ruby versions
|
50
|
+
* MRI 2.0.x
|
51
|
+
* MRI 2.1.x
|
52
|
+
* MRI 2.2.x
|
53
|
+
* MRI 2.3.x
|
54
|
+
* MRI 2.4.0-dev
|
55
|
+
|
56
|
+
MRI ≤ 1.9.3 are not supported. This is primarily because MRI 2.0.0 introduced a new
|
57
|
+
regexp engine (`Oniguruma` was replaced by `Onigmo`). Whilst *most* of this gem could
|
58
|
+
be made to work with MRI 1.9.x (or even 1.8.x), I feel the changes are too significant
|
59
|
+
to implement backwards compatability (especially since [long-term support for MRI
|
60
|
+
1.9.3 has now ended](https://www.ruby-lang.org/en/news/2014/01/10/ruby-1-9-3-will-end-on-2015/)).
|
61
|
+
|
62
|
+
For example, named properties (e.g. `/\p{Alpha}/`) are illegal syntax on MRI 1.9.3.
|
63
|
+
|
64
|
+
Other implementations, such as JRuby, could probably work fine -
|
65
|
+
but I haven't fully tried/tested it. Pull requests are welcome.
|
66
|
+
|
49
67
|
## Installation
|
50
68
|
|
51
69
|
Add this line to your application's Gemfile:
|
@@ -86,12 +104,12 @@ Long answer:
|
|
86
104
|
* Non-capture groups, e.g. `/(?:foo)/`
|
87
105
|
* Comment groups, e.g. `/foo(?#comment)bar/`
|
88
106
|
* Control characters, e.g. `/\ca/`, `/\cZ/`, `/\C-9/`
|
89
|
-
* Escape sequences, e.g. `/\x42/`, `/\x5word/`, `/#{"\x80".
|
107
|
+
* Escape sequences, e.g. `/\x42/`, `/\x5word/`, `/#{"\x80".force\_encoding("ASCII-8BIT")}/`
|
90
108
|
* Unicode characters, e.g. `/\u0123/`, `/\uabcd/`, `/\u{789}/`
|
91
109
|
* Octal characters, e.g. `/\10/`, `/\177/`
|
92
110
|
* Named properties, e.g. `/\p{L}/` ("Letter"), `/\p{Arabic}/` ("Arabic character")
|
93
|
-
, `/\p{^Ll}/` ("Not a lowercase letter"), `/\P{^
|
94
|
-
* ...Even between different ruby versions!! (e.g. `/\p{Arabic}/.examples(
|
111
|
+
, `/\p{^Ll}/` ("Not a lowercase letter"), `/\P{^Canadian\_Aboriginal}/` ("Not not a Canadian aboriginal character")
|
112
|
+
* ...Even between different ruby versions!! (e.g. `/\p{Arabic}/.examples(max\_group\_results: 999)` will give you a different answer in ruby v2.1.x and v2.2.x)
|
95
113
|
* **Arbitrarily complex combinations of all the above!**
|
96
114
|
|
97
115
|
* Regexp options can also be used:
|
@@ -102,12 +120,12 @@ Long answer:
|
|
102
120
|
|
103
121
|
## Bugs and Not-Yet-Supported syntax
|
104
122
|
|
105
|
-
* There are some (rare) edge cases where backreferences do not work properly, e.g. `/(a
|
123
|
+
* There are some (rare) edge cases where backreferences do not work properly, e.g. `/(a\*)a\* \1/.examples` - which includes "aaaa aa". This is because each repeater is not context-aware, so the "greediness" logic is flawed. (E.g. in this case, the second `a\*` should always evaluate to an empty string, because the previous `a\*` was greedy!) However, patterns like this are highly unusual...
|
106
124
|
|
107
125
|
Since the Regexp language is so vast, it's quite likely I've missed something (please raise an issue if you find something)! The only missing feature that I'm currently aware of is:
|
108
126
|
* Conditional capture groups, e.g. `/(group1)? (?(1)yes|no)/.examples` (which *should* return: `["group1 yes", " no"]`)
|
109
127
|
|
110
|
-
Some of the most obscure regexp features are not even mentioned in the ruby docs
|
128
|
+
Some of the most obscure regexp features are not even mentioned in the ruby docs. However, full documentation on all the intricate obscurities in the ruby (version 2.x) regexp parser can be found [here](https://raw.githubusercontent.com/k-takata/Onigmo/master/doc/RE).
|
111
129
|
|
112
130
|
## Impossible features ("illegal syntax")
|
113
131
|
|
@@ -116,61 +134,65 @@ If you'd like to understand this in more detail, check out what I had to say in
|
|
116
134
|
|
117
135
|
Using any of the following will raise a RegexpExamples::IllegalSyntax exception:
|
118
136
|
|
119
|
-
* Lookarounds, e.g. `/foo(?=bar)/`, `/foo(?!bar)/`, `/(?<=foo)bar/`, `/(
|
137
|
+
* Lookarounds, e.g. `/foo(?=bar)/`, `/foo(?!bar)/`, `/(?<=foo)bar/`, `/(?<\!foo)bar/`
|
120
138
|
* [Anchors](http://ruby-doc.org/core-2.2.0/Regexp.html#class-Regexp-label-Anchors) (`\b`, `\B`, `\G`, `^`, `\A`, `$`, `\z`, `\Z`), e.g. `/\bword\b/`, `/line1\n^line2/`
|
121
139
|
* However, a special case has been made to allow `^`, `\A` and `\G` at the start of a pattern; and to allow `$`, `\z` and `\Z` at the end of pattern. In such cases, the characters are effectively just ignored.
|
122
|
-
* Subexpression calls (`\g`), e.g. `/(?<name> ... \g<name
|
140
|
+
* Subexpression calls (`\g`), e.g. `/(?<name> ... \g<name>\* )/`
|
123
141
|
|
124
|
-
(Note: Backreferences are not really "regular" either, but I got these to work with a bit of hackery
|
142
|
+
(Note: Backreferences are not really "regular" either, but I got these to work with a bit of hackery.)
|
125
143
|
|
126
144
|
##Configuration Options
|
127
145
|
|
128
|
-
When generating examples, the gem uses
|
146
|
+
When generating examples, the gem uses 3 configurable values to limit how many examples are listed:
|
129
147
|
|
130
|
-
* `
|
131
|
-
*
|
148
|
+
* `max\_repeater\_variance` (default = `2`) restricts how many examples to return for each repeater. For example:
|
149
|
+
* `.\*` is equivalent to `.{0,2}`
|
132
150
|
* `.+` is equivalent to `.{1,3}`
|
133
151
|
* `.{2,}` is equivalent to `.{2,4}`
|
134
152
|
* `.{,3}` is equivalent to `.{0,2}`
|
135
153
|
* `.{3,8}` is equivalent to `.{3,5}`
|
136
154
|
|
137
|
-
* `
|
155
|
+
* `max\_group\_results` (default = `5`) restricts how many characters to return for each "set". For example:
|
138
156
|
* `\d` is equivalent to `[01234]`
|
139
157
|
* `\w` is equivalent to `[abcde]`
|
140
158
|
* `[h-s]` is equivalent to `[hijkl]`
|
141
159
|
* `(1|2|3|4|5|6|7|8)` is equivalent to `[12345]`
|
142
160
|
|
143
|
-
`
|
161
|
+
* `max\_results\_limit` (default = `10000`) restricts the maximum number of results that can possibly be generated. For example:
|
162
|
+
* `/(crazy){1,999} B\*I\*G\* regex/.examples.length <= 10000` -- Attempting this will NOT freeze your system
|
163
|
+
|
164
|
+
`Rexexp#examples` makes use of *all* these options; `Rexexp#random\_example` only uses `max\_repeater\_variance`, since the other options are redundant.
|
144
165
|
|
145
166
|
To use an alternative value, simply pass the configuration option as follows:
|
146
167
|
|
147
168
|
```ruby
|
148
|
-
/a*/.examples(
|
169
|
+
/a*/.examples(max\_repeater\_variance: 5)
|
149
170
|
#=> [''. 'a', 'aa', 'aaa', 'aaaa' 'aaaaa']
|
150
|
-
/[F-X]/.examples(
|
171
|
+
/[F-X]/.examples(max\_group\_results: 10)
|
151
172
|
#=> ['F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O']
|
152
|
-
|
173
|
+
/[ab]{10}/.examples(max\_results\_limit: 64).length == 64 # NOT 1024
|
174
|
+
/[slow]{9}/.examples(max\_results\_limit: 9999999).length == 4 \*\* 9 == 262144 # Warning - this will take a while!
|
175
|
+
/.\*/.random\_example(max\_repeater\_variance: 50)
|
153
176
|
#=> "A very unlikely result!"
|
154
177
|
```
|
155
178
|
|
156
|
-
|
179
|
+
A sensible use case might be, for example, to generate all 1-5 digit strings:
|
157
180
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
A more sensible use case might be, for example, to generate all 1-4 digit strings:
|
163
|
-
|
164
|
-
`/\d{1,4}/.examples(max_repeater_variance: 3, max_group_results: 10)`
|
181
|
+
```ruby
|
182
|
+
/\d{1,5}/.examples(max\_repeater\_variance: 4, max\_group\_results: 10, max\_results\_limit: 100000)
|
183
|
+
#=> ['0', '1', '2', ..., '99998', '99999']
|
184
|
+
```
|
165
185
|
|
166
|
-
Due to code optimisation,
|
186
|
+
Due to code optimisation, `Regexp#random\_example` runs pretty fast even on very complex patterns.
|
187
|
+
(I.e. It's a _lot_ faster than using `/pattern/.exammples.sample(1)`.)
|
188
|
+
For instance, the following takes no more than ~ 1 second on my machine:
|
167
189
|
|
168
|
-
|
190
|
+
`/.\*\w+\d{100}/.random\_example(max\_repeater\_variance: 1000)`
|
169
191
|
|
170
192
|
## TODO
|
171
193
|
|
172
|
-
*
|
173
|
-
|
194
|
+
* Make regexp#examples always return up to `max\_results\_limit` - currenty, it usually "aborts" before this limit is reached.
|
195
|
+
* `\z` should be interpreted like `\n?\z`, not just `\z` like it is currently.
|
174
196
|
|
175
197
|
## Contributing
|
176
198
|
|
Binary file
|
@@ -1,30 +1,31 @@
|
|
1
1
|
module CoreExtensions
|
2
2
|
module Regexp
|
3
|
-
# A wrapper module to namespace/isolate the Regexp#examples and Regexp#
|
3
|
+
# A wrapper module to namespace/isolate the Regexp#examples and Regexp#random_example
|
4
4
|
# monkey patches.
|
5
5
|
# No core classes are extended in any way, other than the above two methods.
|
6
6
|
module Examples
|
7
7
|
def examples(**config_options)
|
8
8
|
RegexpExamples::ResultCountLimiters.configure!(
|
9
|
-
config_options[:max_repeater_variance],
|
10
|
-
config_options[:max_group_results]
|
9
|
+
max_repeater_variance: config_options[:max_repeater_variance],
|
10
|
+
max_group_results: config_options[:max_group_results],
|
11
|
+
max_results_limit: config_options[:max_results_limit]
|
11
12
|
)
|
12
|
-
examples_by_method(:
|
13
|
+
examples_by_method(:result)
|
13
14
|
end
|
14
15
|
|
15
16
|
def random_example(**config_options)
|
16
17
|
RegexpExamples::ResultCountLimiters.configure!(
|
17
|
-
config_options[:max_repeater_variance]
|
18
|
+
max_repeater_variance: config_options[:max_repeater_variance]
|
18
19
|
)
|
19
|
-
examples_by_method(:
|
20
|
+
examples_by_method(:random_result).first
|
20
21
|
end
|
21
22
|
|
22
23
|
private
|
23
24
|
|
24
25
|
def examples_by_method(method)
|
25
|
-
full_examples = RegexpExamples.
|
26
|
-
|
27
|
-
|
26
|
+
full_examples = RegexpExamples.generic_map_result(
|
27
|
+
RegexpExamples::Parser.new(source, options).parse,
|
28
|
+
method
|
28
29
|
)
|
29
30
|
RegexpExamples::BackReferenceReplacer.new.substitute_backreferences(full_examples)
|
30
31
|
end
|
data/lib/regexp-examples.rb
CHANGED
@@ -3,6 +3,7 @@ require_relative 'regexp-examples/chargroup_parser'
|
|
3
3
|
require_relative 'regexp-examples/constants'
|
4
4
|
require_relative 'regexp-examples/groups'
|
5
5
|
require_relative 'regexp-examples/backreferences'
|
6
|
+
require_relative 'regexp-examples/max_results_limiter'
|
6
7
|
require_relative 'regexp-examples/helpers'
|
7
8
|
require_relative 'regexp-examples/parser'
|
8
9
|
require_relative 'regexp-examples/repeaters'
|
@@ -17,11 +17,17 @@ module RegexpExamples
|
|
17
17
|
# \w is equivalent to [abcde]
|
18
18
|
MAX_GROUP_RESULTS_DEFAULT = 5
|
19
19
|
|
20
|
+
# Maximum number of results to be generated, for Regexp#examples
|
21
|
+
# This is to prevent the system "freezing" when given instructions like:
|
22
|
+
# /[ab]{30}/.examples
|
23
|
+
# (Which would attempt to generate 2**30 == 1073741824 examples!!!)
|
24
|
+
MAX_RESULTS_LIMIT_DEFAULT = 10000
|
20
25
|
class << self
|
21
|
-
attr_reader :max_repeater_variance, :max_group_results
|
22
|
-
def configure!(max_repeater_variance, max_group_results
|
26
|
+
attr_reader :max_repeater_variance, :max_group_results, :max_results_limit
|
27
|
+
def configure!(max_repeater_variance: nil, max_group_results: nil, max_results_limit: nil)
|
23
28
|
@max_repeater_variance = (max_repeater_variance || MAX_REPEATER_VARIANCE_DEFAULT)
|
24
29
|
@max_group_results = (max_group_results || MAX_GROUP_RESULTS_DEFAULT)
|
30
|
+
@max_results_limit = (max_results_limit || MAX_RESULTS_LIMIT_DEFAULT)
|
25
31
|
end
|
26
32
|
end
|
27
33
|
end
|
@@ -32,6 +38,9 @@ module RegexpExamples
|
|
32
38
|
def self.max_group_results
|
33
39
|
ResultCountLimiters.max_group_results
|
34
40
|
end
|
41
|
+
def self.max_results_limit
|
42
|
+
ResultCountLimiters.max_results_limit
|
43
|
+
end
|
35
44
|
|
36
45
|
# Definitions of various special characters, used in regular expressions.
|
37
46
|
# For example, `/\h/.examples` will return the value of `Hex` in this module
|
@@ -158,18 +158,20 @@ module RegexpExamples
|
|
158
158
|
end
|
159
159
|
|
160
160
|
def result
|
161
|
-
result_by_method(:
|
161
|
+
result_by_method(:result)
|
162
162
|
end
|
163
163
|
|
164
164
|
def random_result
|
165
|
-
result_by_method(:
|
165
|
+
result_by_method(:random_result).sample(1)
|
166
166
|
end
|
167
167
|
|
168
168
|
private
|
169
169
|
|
170
170
|
def result_by_method(method)
|
171
|
+
max_results_limiter = MaxResultsLimiterBySum.new
|
171
172
|
repeaters_list
|
172
|
-
.map { |repeaters| RegexpExamples.
|
173
|
+
.map { |repeaters| RegexpExamples.generic_map_result(repeaters, method) }
|
174
|
+
.map { |result| max_results_limiter.limit_results(result)}
|
173
175
|
.inject(:concat)
|
174
176
|
.map { |result| GroupResult.new(result) }
|
175
177
|
.uniq
|
@@ -6,10 +6,14 @@ module RegexpExamples
|
|
6
6
|
# For example:
|
7
7
|
# permutations_of_strings [ ['a'], ['b'], ['c', 'd', 'e'] ] #=> ['abc', 'abd', 'abe']
|
8
8
|
# permutations_of_strings [ ['a', 'b'], ['c', 'd'] ] #=> [ 'ac', 'ad', 'bc', 'bd' ]
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
#
|
10
|
+
# Edge case:
|
11
|
+
# permutations_of_strings [ [] ] #=> nil
|
12
|
+
# (For example, ths occurs during /[^\d\D]/.examples #=> [])
|
13
|
+
def self.permutations_of_strings(arrays_of_strings, max_results_limiter = MaxResultsLimiterByProduct.new)
|
14
|
+
partial_result = max_results_limiter.limit_results(arrays_of_strings.shift)
|
15
|
+
return partial_result if arrays_of_strings.empty?
|
16
|
+
partial_result.product(permutations_of_strings(arrays_of_strings, max_results_limiter)).map do |result|
|
13
17
|
join_preserving_capture_groups(result)
|
14
18
|
end
|
15
19
|
end
|
@@ -25,21 +29,9 @@ module RegexpExamples
|
|
25
29
|
GroupResult.new(result.join, nil, subgroups)
|
26
30
|
end
|
27
31
|
|
28
|
-
def self.map_results(repeaters)
|
29
|
-
generic_map_result(repeaters, :result)
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.map_random_result(repeaters)
|
33
|
-
generic_map_result(repeaters, :random_result)
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
32
|
def self.generic_map_result(repeaters, method)
|
39
|
-
|
40
|
-
.map { |repeater| repeater.public_send(method) }
|
41
|
-
|
42
|
-
RegexpExamples.permutations_of_strings(partial_results)
|
43
|
-
end
|
33
|
+
permutations_of_strings(
|
34
|
+
repeaters.map { |repeater| repeater.public_send(method) }
|
35
|
+
)
|
44
36
|
end
|
45
37
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module RegexpExamples
|
2
|
+
class MaxResultsLimiter # Base class
|
3
|
+
def initialize(initial_results_count)
|
4
|
+
@results_count = initial_results_count
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
# limiter_method and cumulator_method must be inverses
|
10
|
+
# i.e. :- and :+, or :/ and :*
|
11
|
+
def limit_results(partial_results, limiter_method, cumulator_method)
|
12
|
+
return [] if partial_results.empty? # guard clause
|
13
|
+
results_allowed = results_allowed_from(partial_results, limiter_method)
|
14
|
+
cumulate_total(results_allowed.length, cumulator_method)
|
15
|
+
results_allowed
|
16
|
+
end
|
17
|
+
|
18
|
+
def cumulate_total(new_results_count, cumulator_method)
|
19
|
+
if @results_count.zero?
|
20
|
+
@results_count = new_results_count
|
21
|
+
else
|
22
|
+
@results_count = @results_count.public_send(cumulator_method, new_results_count)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def results_allowed_from(partial_results, limiter_method)
|
27
|
+
partial_results.first(
|
28
|
+
RegexpExamples.max_results_limit.public_send(limiter_method, @results_count)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# For example:
|
34
|
+
# Needed when generating examples for /[ab]{10}/
|
35
|
+
# (here, results_count will reach 2**10 == 1024)
|
36
|
+
class MaxResultsLimiterByProduct < MaxResultsLimiter
|
37
|
+
def initialize
|
38
|
+
super(1)
|
39
|
+
end
|
40
|
+
|
41
|
+
def limit_results(partial_results)
|
42
|
+
super(partial_results, :/, :*)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# For example:
|
47
|
+
# Needed when generating examples for /[ab]{10}|{cd}{11}/
|
48
|
+
# (here, results_count will reach 1024 + 2048 == 3072)
|
49
|
+
class MaxResultsLimiterBySum < MaxResultsLimiter
|
50
|
+
def initialize
|
51
|
+
super(0)
|
52
|
+
end
|
53
|
+
|
54
|
+
def limit_results(partial_results)
|
55
|
+
super(partial_results, :-, :+)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -12,14 +12,16 @@ module RegexpExamples
|
|
12
12
|
def result
|
13
13
|
group_results = group.result.first(RegexpExamples.max_group_results)
|
14
14
|
results = []
|
15
|
+
max_results_limiter = MaxResultsLimiterBySum.new
|
15
16
|
min_repeats.upto(max_repeats) do |repeats|
|
16
|
-
if repeats.zero?
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
result = if repeats.zero?
|
18
|
+
[GroupResult.new('')]
|
19
|
+
else
|
20
|
+
RegexpExamples.permutations_of_strings(
|
21
|
+
[group_results] * repeats
|
22
|
+
)
|
23
|
+
end
|
24
|
+
results << max_results_limiter.limit_results(result)
|
23
25
|
end
|
24
26
|
results.flatten.uniq
|
25
27
|
end
|
@@ -369,6 +369,41 @@ RSpec.describe Regexp, '#examples' do
|
|
369
369
|
it { expect(/a(?-i:b)c/i.examples).to match_array %w(abc abC Abc AbC) }
|
370
370
|
end
|
371
371
|
end
|
372
|
+
end # context 'exact examples match'
|
373
|
+
end # context 'returns matching strings'
|
374
|
+
|
375
|
+
context 'max_results_limit config option' do
|
376
|
+
it 'with low limit' do
|
377
|
+
expect(/[A-Z]/.examples(max_results_limit: 5))
|
378
|
+
.to match_array %w(A B C D E)
|
379
|
+
end
|
380
|
+
it 'with (default) high limit' do
|
381
|
+
expect(/[ab]{14}/.examples.length)
|
382
|
+
.to be <= 10000 # NOT 2**14 == 16384, because it's been limited
|
383
|
+
end
|
384
|
+
it 'with (custom) high limit' do
|
385
|
+
expect(/[ab]{14}/.examples(max_results_limit: 20000).length)
|
386
|
+
.to eq 16384 # NOT 10000, because it's below the limit
|
387
|
+
end
|
388
|
+
it 'for boolean or groups' do
|
389
|
+
expect(/[ab]{3}|[cd]{3}/.examples(max_results_limit: 10).length)
|
390
|
+
.to eq 10
|
391
|
+
end
|
392
|
+
it 'for case insensitive examples' do
|
393
|
+
expect(/[ab]{3}/i.examples(max_results_limit: 10).length)
|
394
|
+
.to be <= 10
|
395
|
+
end
|
396
|
+
it 'for range repeaters' do
|
397
|
+
expect(/[ab]{2,3}/.examples(max_results_limit: 10).length)
|
398
|
+
.to be <= 10 # NOT 4 + 8 = 12
|
399
|
+
end
|
400
|
+
it 'for backreferences' do
|
401
|
+
expect(/([ab]{3})\1?/.examples(max_results_limit: 10).length)
|
402
|
+
.to be <= 10 # NOT 8 * 2 = 16
|
403
|
+
end
|
404
|
+
it 'for a complex pattern' do
|
405
|
+
expect(/(a|[bc]{2})\1{1,3}/.examples(max_results_limit: 14).length)
|
406
|
+
.to be <= 14 # NOT (1 + 4) * 3 = 15
|
372
407
|
end
|
373
408
|
end
|
374
409
|
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: 1.
|
4
|
+
version: 1.2.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:
|
11
|
+
date: 2016-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -65,6 +65,7 @@ files:
|
|
65
65
|
- lib/regexp-examples/constants.rb
|
66
66
|
- lib/regexp-examples/groups.rb
|
67
67
|
- lib/regexp-examples/helpers.rb
|
68
|
+
- lib/regexp-examples/max_results_limiter.rb
|
68
69
|
- lib/regexp-examples/parser.rb
|
69
70
|
- lib/regexp-examples/parser_helpers/charset_negation_helper.rb
|
70
71
|
- lib/regexp-examples/parser_helpers/parse_after_backslash_group_helper.rb
|
@@ -100,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
101
|
version: '0'
|
101
102
|
requirements: []
|
102
103
|
rubyforge_project:
|
103
|
-
rubygems_version: 2.
|
104
|
+
rubygems_version: 2.4.6
|
104
105
|
signing_key:
|
105
106
|
specification_version: 4
|
106
107
|
summary: Extends the Regexp class with '#examples' and '#random_example'
|
@@ -1 +0,0 @@
|
|
1
|
-
unicode_ranges_2.0.pstore
|