pattern_expander 0.0.1
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.
- data/.gitignore +2 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +27 -0
- data/LICENSE.txt +22 -0
- data/README.md +81 -0
- data/Rakefile +1 -0
- data/init.rb +1 -0
- data/lib/combination_index.rb +60 -0
- data/lib/pattern_expander/version.rb +3 -0
- data/lib/pattern_expander.rb +21 -0
- data/lib/pattern_parser.rb +34 -0
- data/pattern_expander.gemspec +24 -0
- data/spec/lib/combination_index_spec.rb +89 -0
- data/spec/lib/pattern_expander_spec.rb +70 -0
- data/spec/lib/pattern_parser_spec.rb +65 -0
- data/spec/spec_helper.rb +2 -0
- metadata +116 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pattern_expander (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.2.4)
|
10
|
+
rake (10.1.0)
|
11
|
+
rspec (2.14.1)
|
12
|
+
rspec-core (~> 2.14.0)
|
13
|
+
rspec-expectations (~> 2.14.0)
|
14
|
+
rspec-mocks (~> 2.14.0)
|
15
|
+
rspec-core (2.14.5)
|
16
|
+
rspec-expectations (2.14.2)
|
17
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
18
|
+
rspec-mocks (2.14.3)
|
19
|
+
|
20
|
+
PLATFORMS
|
21
|
+
ruby
|
22
|
+
|
23
|
+
DEPENDENCIES
|
24
|
+
bundler (~> 1.3)
|
25
|
+
pattern_expander!
|
26
|
+
rake
|
27
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Noah Thorp
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
Pattern Expander
|
2
|
+
======
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
gem 'pattern_expander'
|
9
|
+
|
10
|
+
And then execute:
|
11
|
+
|
12
|
+
$ bundle
|
13
|
+
|
14
|
+
Or install it yourself as:
|
15
|
+
|
16
|
+
$ gem install pattern_expander
|
17
|
+
|
18
|
+
Usage
|
19
|
+
=====
|
20
|
+
|
21
|
+
Takes patterns and outputs their combinations - think reverse regex. Lazily loads "pages" of combinations and returns results before the heat death of the universe.
|
22
|
+
|
23
|
+
Pass in a string with randomly chosen values in square brackets"[]":
|
24
|
+
|
25
|
+
expander = PatternExpander.new(
|
26
|
+
"My [startup|band|puppy's] name is [i|e||Power |Awesome ][Ninja|Rockstar] [Ministry|Labs|Quux]"
|
27
|
+
)
|
28
|
+
|
29
|
+
Get random samples with #sample:
|
30
|
+
|
31
|
+
expander.sample # my startup name is Power Rockstar Ministry
|
32
|
+
expander.sample # my puppy's name is iNinja Labs
|
33
|
+
expander.sample(3) # get multiple samples
|
34
|
+
|
35
|
+
Get specific index values:
|
36
|
+
|
37
|
+
expander = PatternExpander.new("[a|b][1|2]")
|
38
|
+
expander[0] # "a1"
|
39
|
+
expander[1] # "a2"
|
40
|
+
expander[0..3] # ["a1", "a2", "b1", "b2"]
|
41
|
+
|
42
|
+
By default you can use "+d" and "+w" to map to digits and alphanumeric
|
43
|
+
characters. Here's an example of constructing a big UUID like pattern:
|
44
|
+
|
45
|
+
expander = PatternExpander.new(
|
46
|
+
"[+w][+w][+w][+w]-[+w][+w][+w][+w]-[+w][+w][+w][+w]-[+w][+w][+w][+w]"
|
47
|
+
)
|
48
|
+
expander.sample # "eo6a-68m6-coxw-14j7"
|
49
|
+
expander[10_000_000_000..10_000_000_002]
|
50
|
+
# returns ["aaaa-aaaa-aaaa-ahz2", "aaaa-aaaa-aaaa-ahz3", "aaaa-aaaa-aaaa-ahz4"]
|
51
|
+
|
52
|
+
And you can pass your own substitutes in and come up with your next
|
53
|
+
startup elevator pitch:
|
54
|
+
|
55
|
+
expander = PatternExpander.new("It's like [+company] for [+customer]",
|
56
|
+
substitutes: {
|
57
|
+
'+company' => ['Chat Roulette', 'Kickstarter', 'Stack Overflow', 'SpaceX'],
|
58
|
+
'+customer' => ['Texas', 'pets', 'tweens', 'magicians', 'figure skaters']
|
59
|
+
}
|
60
|
+
)
|
61
|
+
expander.sample # It's like Chat Roulette for magicians
|
62
|
+
expander.sample # It's like Stack Overflow for Texas
|
63
|
+
expander.sample # It's like SpaceX for figure skaters
|
64
|
+
|
65
|
+
|
66
|
+
TODO
|
67
|
+
====
|
68
|
+
* Sample should return any value only once
|
69
|
+
* Error when max range has been exceeded for the index
|
70
|
+
* Delegate methods from PatternExpander to CombinationIndex
|
71
|
+
* Gemify
|
72
|
+
|
73
|
+
|
74
|
+
Contributing
|
75
|
+
=====
|
76
|
+
|
77
|
+
1. Fork it
|
78
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
79
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
80
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
81
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Dir.glob(__dir__ + '/lib/*').each {|file| require file }
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class CombinationIndex
|
2
|
+
attr_reader :element_lists
|
3
|
+
|
4
|
+
def initialize(element_lists)
|
5
|
+
@element_lists = element_lists
|
6
|
+
end
|
7
|
+
|
8
|
+
def [](index_or_range)
|
9
|
+
if index_or_range.class == Range
|
10
|
+
index_or_range.to_a.map { |index| _single_combination(index) }
|
11
|
+
else
|
12
|
+
_single_combination(index_or_range)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def sample(quantity=1)
|
17
|
+
return _sample_one if quantity == 1
|
18
|
+
result = []
|
19
|
+
quantity.times { result << _sample_one }
|
20
|
+
result
|
21
|
+
end
|
22
|
+
|
23
|
+
def size
|
24
|
+
_element_list_sizes.reduce(:*)
|
25
|
+
end
|
26
|
+
|
27
|
+
def _sample_one
|
28
|
+
self[rand(size)]
|
29
|
+
end
|
30
|
+
# converts a single index to several indexes
|
31
|
+
# ie converts from base ten (index) to a mixed base value
|
32
|
+
# with each place (element array) being a new base (size of the element array)
|
33
|
+
def _multi_array_indexes(i)
|
34
|
+
element_list_sizes_tmp = _element_list_sizes
|
35
|
+
array_indexes = []
|
36
|
+
|
37
|
+
while element_list_size = element_list_sizes_tmp.pop
|
38
|
+
i, remainder = i.divmod(element_list_size)
|
39
|
+
array_indexes.unshift remainder
|
40
|
+
end
|
41
|
+
|
42
|
+
array_indexes
|
43
|
+
end
|
44
|
+
|
45
|
+
def _element_list_sizes
|
46
|
+
element_lists.map(&:size)
|
47
|
+
end
|
48
|
+
|
49
|
+
def _single_combination(i)
|
50
|
+
combination = ""
|
51
|
+
element_list_indexes = _multi_array_indexes(i)
|
52
|
+
|
53
|
+
element_lists.each do |element_list|
|
54
|
+
element_list_index = element_list_indexes.shift
|
55
|
+
combination += element_list[element_list_index]
|
56
|
+
end
|
57
|
+
|
58
|
+
combination
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class PatternExpander
|
2
|
+
attr_reader :combination_index
|
3
|
+
|
4
|
+
def initialize(pattern, substitutes: nil, parser_class: PatternParser)
|
5
|
+
|
6
|
+
unless substitutes.nil?
|
7
|
+
parser = parser_class.new(substitutes: substitutes)
|
8
|
+
else
|
9
|
+
parser = parser_class.new
|
10
|
+
end
|
11
|
+
@combination_index = CombinationIndex.new(parser.parse(pattern))
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](index_or_range)
|
15
|
+
combination_index[index_or_range]
|
16
|
+
end
|
17
|
+
|
18
|
+
def sample(quantity=1)
|
19
|
+
combination_index.sample(quantity)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class PatternParser
|
2
|
+
attr_reader :substitutes, :delimiter
|
3
|
+
|
4
|
+
DEFAULT_SUBSTITUTES = {
|
5
|
+
"+w" => ('a'..'z').to_a + ('0'..'9').to_a,
|
6
|
+
"+d" => ('0'..'9').to_a,
|
7
|
+
}
|
8
|
+
|
9
|
+
def initialize(substitutes: DEFAULT_SUBSTITUTES)
|
10
|
+
@substitutes = substitutes
|
11
|
+
@delimiter = '|'
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse(string)
|
15
|
+
parsed_groups = _parse_groups(string).map do |group|
|
16
|
+
group.split(delimiter)
|
17
|
+
end
|
18
|
+
_substitute(parsed_groups)
|
19
|
+
end
|
20
|
+
|
21
|
+
def _parse_groups(string)
|
22
|
+
string.scan(
|
23
|
+
/([^\[\]]+|[\#{delimiter}]+)/
|
24
|
+
).flatten
|
25
|
+
end
|
26
|
+
|
27
|
+
def _substitute(groups)
|
28
|
+
groups.map do |group|
|
29
|
+
group.inject([]) do |memo, item|
|
30
|
+
memo += substitutes[item] || [item]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pattern_expander/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "pattern_expander"
|
8
|
+
spec.version = PatternExpander::VERSION
|
9
|
+
spec.authors = ["Noah Thorp"]
|
10
|
+
spec.email = ["noah@rixiform.com"]
|
11
|
+
spec.description = %q{Lazily generate string pattern combinations to name your [puppy|startup|band] or write bad poems or produce UUID variants. Kinda like reverse regex. Lazily loads "pages" of combinations and returns results before the heat death of the universe.}
|
12
|
+
spec.summary = %q{Takes patterns and outputs their combinations - think reverse regex. }
|
13
|
+
spec.homepage = "http://www.github.com/aquabu/pattern_expander"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe CombinationIndex do
|
4
|
+
let(:combination_index) do
|
5
|
+
CombinationIndex.new([['a','b'], ['1','2']])
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#[]' do
|
9
|
+
it 'takes an integer and references the required array values' do
|
10
|
+
combination_index[0].should == 'a1'
|
11
|
+
combination_index[1].should == 'a2'
|
12
|
+
combination_index[2].should == 'b1'
|
13
|
+
combination_index[3].should == 'b2'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'can take a range' do
|
17
|
+
combination_index[0..2].should == ['a1','a2','b1']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#_multi_array_indexes' do
|
22
|
+
it 'should take an index and an array of index sizes and return an array of indexes' do
|
23
|
+
combination_index = CombinationIndex.new([[:a,:b],[:a,:b],[:a,:b]])
|
24
|
+
combination_index._multi_array_indexes(0).should == [0,0,0]
|
25
|
+
combination_index._multi_array_indexes(1).should == [0,0,1]
|
26
|
+
combination_index._multi_array_indexes(2).should == [0,1,0]
|
27
|
+
combination_index._multi_array_indexes(3).should == [0,1,1]
|
28
|
+
combination_index._multi_array_indexes(4).should == [1,0,0]
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'can handle a collection of index sizes of variable length' do
|
32
|
+
combination_index = CombinationIndex.new([[:a,:b],[:a,:b],[:a,:b],[:a,:b]])
|
33
|
+
combination_index._multi_array_indexes(8).should == [1,0,0,0]
|
34
|
+
combination_index._multi_array_indexes(15).should == [1,1,1,1]
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'can handle a collection of indexes with different sizes' do
|
38
|
+
combination_index = CombinationIndex.new([[:a,:b,:c,:d,:e],[:a,:b,:c]])
|
39
|
+
combination_index._multi_array_indexes(0).should == [0,0]
|
40
|
+
combination_index._multi_array_indexes(2).should == [0,2]
|
41
|
+
combination_index._multi_array_indexes(3).should == [1,0]
|
42
|
+
combination_index._multi_array_indexes(14).should == [4,2]
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'can handle many indexes of varying sizes' do
|
46
|
+
a = [:a]
|
47
|
+
combination_index = CombinationIndex.new(
|
48
|
+
[a * 6, a * 5, a * 4, a * 3, a * 2]
|
49
|
+
)
|
50
|
+
combination_index._multi_array_indexes(0).should == [0,0,0,0,0]
|
51
|
+
combination_index._multi_array_indexes(719).should == [5,4,3,2,1]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#sample' do
|
56
|
+
it 'should get a random combination' do
|
57
|
+
letters = ('a'..'z').to_a + ('0'..'9').to_a
|
58
|
+
combination_elements = []
|
59
|
+
32.times do
|
60
|
+
combination_elements << letters
|
61
|
+
end
|
62
|
+
|
63
|
+
combination_index = CombinationIndex.new(combination_elements)
|
64
|
+
|
65
|
+
pattern = /^[a-z0-9]{32}$/
|
66
|
+
|
67
|
+
sample_1 = combination_index.sample
|
68
|
+
sample_1.should =~ pattern
|
69
|
+
|
70
|
+
sample_2 = combination_index.sample
|
71
|
+
sample_2.should =~ pattern
|
72
|
+
|
73
|
+
# chance of collision 1 in 36**32
|
74
|
+
sample_1.should_not == sample_2
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'can return an arbitrary number of samples' do
|
78
|
+
combination_index.stub(:_sample_one) { 'foo' }
|
79
|
+
samples = combination_index.sample(3)
|
80
|
+
samples.should == ['foo','foo','foo']
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it '#size should return the total number of combinations' do
|
85
|
+
CombinationIndex.new([[:a,:b],[0,1]]).size.should == 4
|
86
|
+
CombinationIndex.new([[:a,:b,:c],[0,1]]).size.should == 6
|
87
|
+
CombinationIndex.new([[:a,:b,:c],[0,1],[0,1]]).size.should == 12
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe PatternExpander do
|
4
|
+
describe '#initialize' do
|
5
|
+
it 'can take substitutes' do
|
6
|
+
pattern_expander = PatternExpander.new(
|
7
|
+
'[+x]',
|
8
|
+
substitutes: {'+x' => ['did_it']}
|
9
|
+
)
|
10
|
+
pattern_expander[0].should == 'did_it'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#[index]' do
|
15
|
+
let(:pattern_expander) { PatternExpander.new('[a|b|][1|2]') }
|
16
|
+
|
17
|
+
it 'takes an integer and references the required array values' do
|
18
|
+
pattern_expander = PatternExpander.new('[a|b|][1|2]')
|
19
|
+
pattern_expander[0].should == 'a1'
|
20
|
+
pattern_expander[1].should == 'a2'
|
21
|
+
pattern_expander[2].should == 'b1'
|
22
|
+
pattern_expander[3].should == 'b2'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'can use single values in expansions' do
|
26
|
+
pattern_expander = PatternExpander.new('[foo|biz|bang|bar][_][+d]')
|
27
|
+
pattern_expander[9..11].should == ["foo_9", "biz_0", "biz_1"]
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'can reference character substitutions' do
|
31
|
+
pattern_expander = PatternExpander.new('[+d][+d]')
|
32
|
+
pattern_expander[11].should == "11"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#[i..j] range selector' do
|
37
|
+
it 'should take a pattern and a range and return patterns for that range' do
|
38
|
+
pattern_expander = PatternExpander.new('[a|b|][1|2]')
|
39
|
+
pattern_expander[0..3].should == ['a1','a2','b1','b2']
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should allow combinations' do
|
43
|
+
pattern_expander = PatternExpander.new('[+d][+d]')
|
44
|
+
pattern_expander[21..23].should ==
|
45
|
+
['21','22','23']
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'handles big patterns' do
|
49
|
+
pattern_expander = PatternExpander.new('[+w][+w][+w][+w][+w][+w][+w]')
|
50
|
+
pattern_expander[100_000..100_003].should ==
|
51
|
+
["aaacff2", "aaacff3", "aaacff4", "aaacff5"]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#sample' do
|
56
|
+
let(:pattern_expander) do
|
57
|
+
PatternExpander.new('[+w][+d]')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should get a random combination' do
|
61
|
+
pattern_expander.sample.should =~ /^\w\d$/
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'can get any number of random combinations' do
|
65
|
+
samples = pattern_expander.sample(4)
|
66
|
+
samples.size.should == 4
|
67
|
+
samples.each {|s| s.should =~ /^\w\d$/ }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe PatternParser do
|
4
|
+
let(:substitutes) do
|
5
|
+
{
|
6
|
+
"+w" => ('a'..'z').to_a + ('0'..'9').to_a,
|
7
|
+
"+d" => ('0'..'9').to_a,
|
8
|
+
"+l" => ('a'..'z').to_a
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:subject) { PatternParser.new(substitutes: substitutes) }
|
13
|
+
let(:wildcard) { ['a'..'z', '0'..'9'].inject([]) {|m,v| m + v.to_a} }
|
14
|
+
|
15
|
+
describe '#parse' do
|
16
|
+
it 'converts patterns into arrays' do
|
17
|
+
subject.parse('[a|b|c][1|2|3]').should == [['a','b','c'], ['1','2','3']]
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'substitutes patterns in arrays' do
|
21
|
+
subject.parse('[+d]').should == [('0'..'9').to_a]
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'sustitutes patterns outside of arrays' do
|
25
|
+
subject.parse('+d').should == [('0'..'9').to_a]
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'leaves non substituted string as ordinary arrays' do
|
29
|
+
subject.parse('foo[+d]bar').should == [['foo'],('0'..'9').to_a,['bar']]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#_parse_groups' do
|
34
|
+
it 'should handle a single group' do
|
35
|
+
subject._parse_groups('[a]').should == ['a']
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should return an array of group string' do
|
39
|
+
subject._parse_groups('[a][b][c]').should == ['a','b','c']
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should return on array of group strings including | chars' do
|
43
|
+
subject._parse_groups('[a|b][c|d]').should == ['a|b','c|d']
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should return non bracket string as their own elements' do
|
47
|
+
subject._parse_groups('foo[a]').should == ['foo', 'a']
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
describe '#_substitute' do
|
53
|
+
it 'substitutes a +w with an array of wildcard chars' do
|
54
|
+
subject._substitute([['+w']]).should == [ wildcard ]
|
55
|
+
end
|
56
|
+
|
57
|
+
it '_substitutes a +d with an array of numbers' do
|
58
|
+
subject._substitute([['+d']]).should == [ (0..9).map {|c| c.to_s} ]
|
59
|
+
end
|
60
|
+
|
61
|
+
it '_substitutes +l with an array of letters' do
|
62
|
+
subject._substitute([['+l']]).should == [ ('a'..'z').to_a ]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pattern_expander
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Noah Thorp
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Lazily generate string pattern combinations to name your [puppy|startup|band]
|
63
|
+
or write bad poems or produce UUID variants. Kinda like reverse regex. Lazily loads
|
64
|
+
"pages" of combinations and returns results before the heat death of the universe.
|
65
|
+
email:
|
66
|
+
- noah@rixiform.com
|
67
|
+
executables: []
|
68
|
+
extensions: []
|
69
|
+
extra_rdoc_files: []
|
70
|
+
files:
|
71
|
+
- .gitignore
|
72
|
+
- Gemfile
|
73
|
+
- Gemfile.lock
|
74
|
+
- LICENSE.txt
|
75
|
+
- README.md
|
76
|
+
- Rakefile
|
77
|
+
- init.rb
|
78
|
+
- lib/combination_index.rb
|
79
|
+
- lib/pattern_expander.rb
|
80
|
+
- lib/pattern_expander/version.rb
|
81
|
+
- lib/pattern_parser.rb
|
82
|
+
- pattern_expander.gemspec
|
83
|
+
- spec/lib/combination_index_spec.rb
|
84
|
+
- spec/lib/pattern_expander_spec.rb
|
85
|
+
- spec/lib/pattern_parser_spec.rb
|
86
|
+
- spec/spec_helper.rb
|
87
|
+
homepage: http://www.github.com/aquabu/pattern_expander
|
88
|
+
licenses:
|
89
|
+
- MIT
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 1.8.25
|
109
|
+
signing_key:
|
110
|
+
specification_version: 3
|
111
|
+
summary: Takes patterns and outputs their combinations - think reverse regex.
|
112
|
+
test_files:
|
113
|
+
- spec/lib/combination_index_spec.rb
|
114
|
+
- spec/lib/pattern_expander_spec.rb
|
115
|
+
- spec/lib/pattern_parser_spec.rb
|
116
|
+
- spec/spec_helper.rb
|