string_pattern 1.6.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d4c76309330e0ce36e6f110971791053f1c932a92246d30454342c58df5ca82
4
- data.tar.gz: dd885204b85c12ce3d734187649270b5e38a6f89b7b8789a8ed5d76fb5492b80
3
+ metadata.gz: 70bf11f69ccc9fe41a84e7314f88fb12e98d9639f9619869504b455e132bd5b5
4
+ data.tar.gz: 3ad181fe7fabbcafe4467c76c3cdba59beefc752cf8f773dc6729b6c13d7d642
5
5
  SHA512:
6
- metadata.gz: f3dc754593a2838186535d4330eefba9e0f560a90c63f3e8981a2883498fbe5e68d325cadecaaa3993fde53e21e5c22a52b10eb3159ba44c7fa6d8c3692b8305
7
- data.tar.gz: baee5bb1e9e032b68fb2f19f683e0b0c458d946225c0b000501f0676cde020f56ad26420e0868a7c2eada703e728043a8557b10fa622561c29f0e4aebe633651
6
+ metadata.gz: '05936978cbd0e45df53493d779c2b031001e591313578e5283348f9bfea78e1f20fa446b013d001b6d1c108d259ed7cdc12d36a8c3910e300bd976a3ab6f4fb7'
7
+ data.tar.gz: 6983689728bd7437e2937ee8c5c739bf2dea4638dc942de8ebf1451ee5525586246b135ee0a7d9251d09c8834f617d92dc47172afd3f320db9591ae6d749c955
data/README.md CHANGED
@@ -5,6 +5,8 @@
5
5
  With this gem, you can easily generate strings supplying a very simple pattern.
6
6
  Also, you can validate if a text fulfills a specific pattern or even generate a string following a pattern and returning the wrong length, value... for testing your applications.
7
7
 
8
+ Also you can use regular expressions (Regexp) to generate strings: `/[a-z0-9]{2,5}\w+/.gen`
9
+
8
10
  To do even more take a look at [nice_hash gem](https://github.com/MarioRuiz/nice_hash)
9
11
 
10
12
  ## Installation
@@ -102,6 +104,53 @@ The pattern needs to be a symbol object.
102
104
  }
103
105
  ```
104
106
 
107
+ #### Generate strings using Regular Expressions (Regexp)
108
+
109
+ Take in consideration this feature is not supporting all possibilities for Regular expressions but it is fully functional. If you find any bug or limitation please add it to issues: https://github.com/MarioRuiz/string_pattern/issues
110
+
111
+ In case you you want to change the default maximum for repetitions when using * or +: `StringPattern.default_infinite = 30` . By default is 10.
112
+
113
+ If you want to translate a regular expression into an StringPattern use the method we added to Regexp class: `to_sp`
114
+
115
+ Examples:
116
+
117
+ ```ruby
118
+ /[a-z0-9]{2-5}\w+/.to_sp
119
+ #> ["2-5:nx", "1-10:Ln_"]
120
+
121
+ #regular expression for UUID v4
122
+ /[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}/.to_sp
123
+ #> ["8:n[ABCDEF]", "-", "4:n[ABCDEF]", "-4", "3:n[ABCDEF]", "-", "1:[89AB]", "3:n[ABCDEF]", "-", "12:n[ABCDEF]"]
124
+ ```
125
+
126
+ If you want to generate a random string following the regular expression, you can do it like a normal string pattern:
127
+
128
+ ```ruby
129
+
130
+ regexp = /[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}/
131
+
132
+ # using StringPattern class
133
+ puts StringPattern.generate(regexp)
134
+
135
+ # using Kernel
136
+ puts generate(regexp)
137
+
138
+ # using generate method added to Regexp class
139
+ puts regexp.generate
140
+
141
+ #using the alias 'gen'
142
+ puts regexp.gen
143
+
144
+ # output:
145
+ #>7009574B-6F2F-436E-BB7A-EA5FDA6B4E47
146
+ #>5FB1718F-108A-4F62-8170-33C43FD86B1D
147
+ #>05745B6F-93BA-475F-8118-DD56E5EAC4D1
148
+ #>2D6FC189-8D50-45A8-B182-780193838502
149
+
150
+ ```
151
+
152
+ ### String patterns
153
+
105
154
  #### How to generate one or another string
106
155
 
107
156
  In case you need to specify that the string is generated selecting one or another fixed string or pattern, you can do it by using Array of patterns and in the position you want you can add an array with the possible values
@@ -117,6 +166,7 @@ p ["uno:", :"5:N", ['.red','.green', :'3:L'] ].gen
117
166
  # 'uno:34322.red'
118
167
  # 'uno:44432.green'
119
168
  # 'uno:34322.red'
169
+ # 'uno:28795xAB'
120
170
 
121
171
  ```
122
172
 
@@ -213,6 +263,7 @@ Examples:
213
263
 
214
264
  "10:L/n/".gen errors: [:value]
215
265
  #> 1hwIw;v{KQ, mpk*l]!7:!, wocipgZt8@
266
+
216
267
  ```
217
268
 
218
269
  ### Validate if a string is following a pattern
@@ -6,14 +6,14 @@ class Array
6
6
  StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
7
7
  end
8
8
 
9
- alias_method :gen, :generate
9
+ alias gen generate
10
10
 
11
11
  # it will validate an string following the pattern specified
12
12
  def validate(string_to_validate, expected_errors: [], not_expected_errors: [], **synonyms)
13
13
  StringPattern.validate(text: string_to_validate, pattern: self, expected_errors: expected_errors, not_expected_errors: not_expected_errors, **synonyms)
14
14
  end
15
15
 
16
- alias_method :val, :validate
16
+ alias val validate
17
17
  end
18
18
 
19
19
  class String
@@ -22,46 +22,263 @@ class String
22
22
  StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
23
23
  end
24
24
 
25
- alias_method :gen, :generate
25
+ alias gen generate
26
26
 
27
27
  # it will validate an string following the pattern specified
28
28
  def validate(string_to_validate, expected_errors: [], not_expected_errors: [], **synonyms)
29
29
  StringPattern.validate(text: string_to_validate, pattern: self, expected_errors: expected_errors, not_expected_errors: not_expected_errors, **synonyms)
30
30
  end
31
31
 
32
- alias_method :val, :validate
32
+ alias val validate
33
33
  end
34
34
 
35
-
36
35
  class Symbol
37
36
  # it will generate an string following the pattern specified
38
37
  def generate(expected_errors: [], **synonyms)
39
38
  StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
40
39
  end
41
40
 
42
- alias_method :gen, :generate
41
+ alias gen generate
43
42
 
44
43
  # it will validate an string following the pattern specified
45
44
  def validate(string_to_validate, expected_errors: [], not_expected_errors: [], **synonyms)
46
- StringPattern.validate(text: string_to_validate, pattern: self.to_s, expected_errors: expected_errors, not_expected_errors: not_expected_errors, **synonyms)
45
+ StringPattern.validate(text: string_to_validate, pattern: to_s, expected_errors: expected_errors, not_expected_errors: not_expected_errors, **synonyms)
47
46
  end
48
47
 
49
- alias_method :val, :validate
48
+ alias val validate
50
49
  end
51
50
 
51
+ class Regexp
52
+
53
+ # it will generate an string following the pattern specified
54
+ def generate(expected_errors: [], **synonyms)
55
+ StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
56
+ end
57
+
58
+ alias gen generate
59
+
60
+ # adds method to convert a Regexp to StringPattern
61
+ # returns an array of string patterns or just one string pattern
62
+ def to_sp
63
+ regexp_s = self.to_s
64
+ return StringPattern.cache[regexp_s] unless StringPattern.cache[regexp_s].nil?
65
+ regexp = Regexp.new regexp_s
66
+ require 'regexp_parser'
67
+ default_infinite = StringPattern.default_infinite
68
+ pata = []
69
+ pats = ''
70
+ patg = [] # for (aa|bb|cc) group
71
+ set = false
72
+ capture = false
73
+
74
+ range = ''
75
+ fixed_text=false
76
+ last_char = (regexp.to_s.gsub("?-mix:",'').length)-2
77
+ Regexp::Scanner.scan regexp do |type, token, text, ts, te|
78
+ if type == :escape
79
+ if token == :dot
80
+ token = :literal
81
+ text = '.'
82
+ elsif token == :literal and text.size == 2
83
+ text = text[1]
84
+ else
85
+ puts "Report token not controlled: type: #{type}, token: #{token}, text: '#{text}' [#{ts}..#{te}]"
86
+ end
87
+ end
88
+
89
+
90
+ unless set || (token == :interval) || (token == :zero_or_one) ||
91
+ (token == :zero_or_more) || (token == :one_or_more) || (pats == '')
92
+ if (pats[0] == '[') && (pats[-1] == ']')
93
+ pats[0] = ''
94
+ if (token == :alternation) || !patg.empty?
95
+ if fixed_text
96
+ if patg.size==0
97
+ patg << (pata.pop + pats.chop)
98
+ else
99
+ patg[-1] += pats.chop
100
+ end
101
+ else
102
+ patg << pats.chop
103
+ end
104
+ else
105
+ if fixed_text
106
+ pata[-1]+=pats.chop
107
+ else
108
+ if pats.size==2
109
+ pata << pats.chop #jal
110
+ else
111
+ pata << "1:[#{pats}" #jal
112
+ end
113
+ if last_char==te and type==:literal and token==:literal
114
+ pata << text
115
+ pats = ""
116
+ next
117
+ end
118
+ end
119
+ end
120
+ else
121
+ if (token == :alternation) || !patg.empty?
122
+ patg << "1:#{pats}"
123
+ else
124
+ pata << "1:#{pats}"
125
+ end
126
+ end
127
+ pats = ''
128
+ end
129
+ fixed_text=false
130
+
131
+ case token
132
+ when :open
133
+ set = true
134
+ pats += '['
135
+ when :close
136
+ if type == :set
137
+ set = false
138
+ if pats[-1] == '['
139
+ pats.chop!
140
+ else
141
+ pats += ']'
142
+ end
143
+ elsif type == :group
144
+ capture = false
145
+ unless patg.empty?
146
+ patg << pats if pats.to_s != ''
147
+ pata << patg
148
+ patg = []
149
+ pats = ''
150
+ end
151
+ end
152
+ when :capture
153
+ capture = true if type == :group
154
+ when :alternation
155
+ if type == :meta
156
+ if pats != ''
157
+ patg << pats
158
+ pats = ''
159
+ elsif patg.empty?
160
+ # for the case the first element was not added to patg and was on pata fex: (a+|b|c)
161
+ patg << pata.pop
162
+ end
163
+ end
164
+ when :range
165
+ range = pats[-1]
166
+ pats.chop!
167
+ when :digit
168
+ pats += 'n'
169
+ when :nondigit
170
+ pats += '*[%0123456789%]'
171
+ when :space
172
+ pats += '_'
173
+ when :nonspace
174
+ pats += '*[% %]'
175
+ when :word
176
+ pats += 'Ln_'
177
+ when :nonword
178
+ pats += '$'
179
+ when :word_boundary
180
+ pats += '$'
181
+ when :dot
182
+ pats += '*'
183
+ when :literal
184
+ if range == ''
185
+ if text.size > 1
186
+ fixed_text=true
187
+ if !patg.empty?
188
+ patg << text.chop
189
+ else
190
+ pata << text.chop
191
+ end
192
+ pats = text[-1]
193
+ else
194
+ pats += text
195
+ end
196
+ else
197
+ range = range + '-' + text
198
+ if range == 'a-z'
199
+ pats = 'x' + pats
200
+ elsif range == 'A-Z'
201
+ pats = 'X' + pats
202
+ elsif range == '0-9'
203
+ pats = 'n' + pats
204
+ else
205
+ pats += if set
206
+ (range[0]..range[2]).to_a.join
207
+ else
208
+ '[' + (range[0]..range[2]).to_a.join + ']'
209
+ end
210
+
211
+ end
212
+ range = ''
213
+ end
214
+ pats = '[' + pats + ']' unless set
215
+ when :interval
216
+ size = text.sub(',', '-').sub('{', '').sub('}', '')
217
+ size.chop! if size[-1] == '-'
218
+ pats = size + ':' + pats
219
+ if !patg.empty?
220
+ patg << pats
221
+ else
222
+ pata << pats
223
+ end
224
+ pats = ''
225
+ when :zero_or_one
226
+ pats = '0-1:' + pats
227
+ if !patg.empty?
228
+ patg << pats
229
+ else
230
+ pata << pats
231
+ end
232
+ pats = ''
233
+ when :zero_or_more
234
+ pats = "0-#{default_infinite}:" + pats
235
+ if !patg.empty?
236
+ patg << pats
237
+ else
238
+ pata << pats
239
+ end
240
+ pats = ''
241
+ when :one_or_more
242
+ pats = "1-#{default_infinite}:" + pats
243
+ if !patg.empty?
244
+ patg << pats
245
+ else
246
+ pata << pats
247
+ end
248
+ pats = ''
249
+ end
250
+ end
251
+ if pats!=""
252
+ if pata.empty?
253
+ if pats[0]=="[" and pats[-1]=="]" #fex: /[12ab]/
254
+ pata = ["1:#{pats}"]
255
+ end
256
+ else
257
+ pata[-1]+=pats[1] #fex: /allo/
258
+ end
259
+ end
260
+ if pata.size==1 and pata[0].kind_of?(String)
261
+ res = pata[0]
262
+ else
263
+ res = pata
264
+ end
265
+ StringPattern.cache[regexp_s] = res
266
+ return res
267
+ end
268
+ end
52
269
 
53
270
  module Kernel
54
271
  public
272
+
55
273
  # if string or symbol supplied it will generate a string with the supplied pattern specified on the string
56
274
  # if array supplied then it will generate a string with the supplied patterns. If a position contains a pattern supply it as symbol, for example: [:"10:N", "fixed", :"10-20:XN/x/"]
57
275
  def generate(pattern, expected_errors: [], **synonyms)
58
- if pattern.kind_of?(String) or pattern.kind_of?(Array) or pattern.kind_of?(Symbol)
276
+ if pattern.is_a?(String) || pattern.is_a?(Array) || pattern.is_a?(Symbol) || pattern.is_a?(Regexp)
59
277
  StringPattern.generate(pattern, expected_errors: expected_errors, **synonyms)
60
278
  else
61
279
  puts " Kernel generate method: class not recognized:#{pattern.class}"
62
280
  end
63
281
  end
64
282
 
65
- alias_method :gen, :generate
283
+ alias gen generate
66
284
  end
67
-
@@ -18,15 +18,18 @@ require_relative 'string/pattern/add_to_ruby' if SP_ADD_TO_RUBY
18
18
  # If true it will check on the strings of the array positions if they have the pattern format and assume in that case that is a pattern.
19
19
  # dont_repeat: (TrueFalse, default: false)
20
20
  # If you want to generate for example 1000 strings and be sure all those strings are different you can set it to true
21
+ # default_infinite: (Integer, default: 10)
22
+ # In case using regular expressions the maximum when using * or + for repetitions
21
23
  class StringPattern
22
24
  class << self
23
- attr_accessor :national_chars, :optimistic, :dont_repeat, :cache, :cache_values
25
+ attr_accessor :national_chars, :optimistic, :dont_repeat, :cache, :cache_values, :default_infinite
24
26
  end
25
27
  @national_chars = (('a'..'z').to_a + ('A'..'Z').to_a).join
26
28
  @optimistic = true
27
29
  @cache = Hash.new()
28
30
  @cache_values = Hash.new()
29
31
  @dont_repeat = false
32
+ @default_infinite = 10
30
33
  NUMBER_SET = ('0'..'9').to_a
31
34
  SPECIAL_SET = [' ', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '+', '=', '{', '}', '[', ']', "'", ';', ':', '?', '>', '<', '`', '|', '/', '"']
32
35
  ALPHA_SET_LOWER = ('a'..'z').to_a
@@ -346,7 +349,8 @@ class StringPattern
346
349
  end
347
350
  end
348
351
  string_set_not_allowed = Array.new
349
-
352
+ elsif pattern.kind_of?(Regexp)
353
+ return generate(pattern.to_sp, expected_errors: expected_errors)
350
354
  else
351
355
  puts "pattern argument not valid on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
352
356
  return pattern.to_s
metadata CHANGED
@@ -1,18 +1,39 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: string_pattern
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mario Ruiz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-08 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2019-01-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: regexp_parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.3.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.3.0
13
33
  description: 'You can easily generate strings supplying a very simple pattern. ''10-20:Xn/x/''.generate
14
- #>qBstvc6JN8ra. Also, you can validate if a text fulfills a specific pattern or
15
- even generate a string following a pattern and returning the wrong length, value...
34
+ #>qBstvc6JN8ra. Now generate random strings using a regular expression (Regexp):
35
+ /[a-z0-9]{2,5}w+/.gen . Also, you can validate if a text fulfills a specific pattern
36
+ or even generate a string following a pattern and returning the wrong length, value...
16
37
  for testing your applications.'
17
38
  email: marioruizs@gmail.com
18
39
  executables: []
@@ -49,6 +70,6 @@ rubyforge_project:
49
70
  rubygems_version: 2.7.6
50
71
  signing_key:
51
72
  specification_version: 4
52
- summary: 'Generate easily random strings following a simple pattern. ''10-20:Xn/x/''.generate
53
- #>qBstvc6JN8ra'
73
+ summary: 'Generate easily random strings following a simple pattern or regular expression.
74
+ ''10-20:Xn/x/''.generate #>qBstvc6JN8ra'
54
75
  test_files: []