string_pattern 2.1.4 → 2.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28c7899f11212df7952a480dfd6b4e55080387d258980d004a7a78fe64c0915d
4
- data.tar.gz: 6513592762e0a85e0a727386c40e75081b065d139afed808a26cb2af669856a3
3
+ metadata.gz: c451e4295f5c62ea8b7c8113815a0c7a2b5c70a739826fdf651a7fb99a75be48
4
+ data.tar.gz: 2445e4958a2bf96b70e0ce99f4df31ab02a61183a496289a1b20b3360e2fecaf
5
5
  SHA512:
6
- metadata.gz: 515dd4e564d3b9be7586a4c18153faf4b3d79761bffcf2fd26b516df141e681f2ff0774a30556e3a9cd16b2cbfdd83a2780dcad3a378e386e8e87a1d7183db98
7
- data.tar.gz: 70fbd57c3e47798f1b1414e4ccc63266bc896039b5cfa22960af6e3f669dbfe372488f1c72c5af0fd573ca8777703fdc791806d818c254f0a4f416c4e21c0d46
6
+ metadata.gz: 650a16f6a2cda5c762f2f685b4fe515848135a6c4995ba08504ec80435696d4e1ab6289adaf4aae839ca0d77978338d2603411a7330fe2db0f2bede587554cfd
7
+ data.tar.gz: 996deb9300188c286dc0a051f744262367f928192e5c30fcd981f7f964283463f2dc606c4876163378397b767ed235f51bc749bac55e801866810aa19318da91
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # StringPattern
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/string_pattern.svg)](https://rubygems.org/gems/string_pattern)
4
+ [![Build Status](https://travis-ci.com/MarioRuiz/string_pattern.svg?branch=master)](https://github.com/MarioRuiz/string_pattern)
5
+ [![Coverage Status](https://coveralls.io/repos/github/MarioRuiz/string_pattern/badge.svg?branch=master)](https://coveralls.io/github/MarioRuiz/string_pattern?branch=master)
4
6
 
5
7
  With this gem, you can easily generate strings supplying a very simple pattern. Even generate random words in English or Spanish.
6
8
  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. Perfect to be used in test data factories.
@@ -35,10 +35,21 @@ class String
35
35
  # Convert to CamelCase a string
36
36
  ########################################################
37
37
  def to_camel_case
38
- return self if self !~ /_/ && self !~ /\s/ && self =~ /[A-Z]+.*/
38
+ return self if self !~ /_/ && self !~ /\s/ && self =~ /^[A-Z]+.*/
39
39
 
40
+ gsub(/[^a-zA-Z0-9ññÑáéíóúÁÉÍÓÚüÜ_]/, "_")
41
+ .split("_").map(&:capitalize).join
42
+ end
43
+
44
+ ########################################################
45
+ # Convert to snake_case a string
46
+ ########################################################
47
+ def to_snake_case
40
48
  gsub(/\W/, '_')
41
- .split('_').map(&:capitalize).join
49
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
50
+ .gsub(/([a-z])([A-Z])/, '\1_\2')
51
+ .downcase
52
+ .gsub(/_+/, '_')
42
53
  end
43
54
  end
44
55
 
@@ -70,40 +81,39 @@ class Regexp
70
81
  # adds method to convert a Regexp to StringPattern
71
82
  # returns an array of string patterns or just one string pattern
72
83
  def to_sp
73
- regexp_s = self.to_s
84
+ regexp_s = self.to_s
74
85
  return StringPattern.cache[regexp_s] unless StringPattern.cache[regexp_s].nil?
75
86
  regexp = Regexp.new regexp_s
76
- require 'regexp_parser'
87
+ require "regexp_parser"
77
88
  default_infinite = StringPattern.default_infinite
78
89
  pata = []
79
- pats = ''
90
+ pats = ""
80
91
  patg = [] # for (aa|bb|cc) group
81
92
  set = false
82
93
  capture = false
83
94
 
84
- range = ''
85
- fixed_text=false
86
- last_char = (regexp.to_s.gsub("?-mix:",'').length)-2
95
+ range = ""
96
+ fixed_text = false
97
+ last_char = (regexp.to_s.gsub("?-mix:", "").length) - 2
87
98
  Regexp::Scanner.scan regexp do |type, token, text, ts, te|
88
99
  if type == :escape
89
100
  if token == :dot
90
101
  token = :literal
91
- text = '.'
102
+ text = "."
92
103
  elsif token == :literal and text.size == 2
93
104
  text = text[1]
94
- else
105
+ else
95
106
  puts "Report token not controlled: type: #{type}, token: #{token}, text: '#{text}' [#{ts}..#{te}]"
96
107
  end
97
108
  end
98
109
 
99
-
100
110
  unless set || (token == :interval) || (token == :zero_or_one) ||
101
- (token == :zero_or_more) || (token == :one_or_more) || (pats == '')
102
- if (pats[0] == '[') && (pats[-1] == ']')
103
- pats[0] = ''
111
+ (token == :zero_or_more) || (token == :one_or_more) || (pats == "")
112
+ if (pats[0] == "[") && (pats[-1] == "]")
113
+ pats[0] = ""
104
114
  if (token == :alternation) || !patg.empty?
105
- if fixed_text
106
- if patg.size==0
115
+ if fixed_text
116
+ if patg.size == 0
107
117
  patg << (pata.pop + pats.chop)
108
118
  else
109
119
  patg[-1] += pats.chop
@@ -112,15 +122,15 @@ class Regexp
112
122
  patg << pats.chop
113
123
  end
114
124
  else
115
- if fixed_text
116
- pata[-1]+=pats.chop
125
+ if fixed_text
126
+ pata[-1] += pats.chop
117
127
  else
118
- if pats.size==2
128
+ if pats.size == 2
119
129
  pata << pats.chop #jal
120
130
  else
121
131
  pata << "1:[#{pats}" #jal
122
132
  end
123
- if last_char==te and type==:literal and token==:literal
133
+ if last_char == te and type == :literal and token == :literal
124
134
  pata << text
125
135
  pats = ""
126
136
  next
@@ -134,66 +144,66 @@ class Regexp
134
144
  pata << "1:#{pats}"
135
145
  end
136
146
  end
137
- pats = ''
147
+ pats = ""
138
148
  end
139
- fixed_text=false
149
+ fixed_text = false
140
150
 
141
151
  case token
142
152
  when :open
143
153
  set = true
144
- pats += '['
154
+ pats += "["
145
155
  when :close
146
156
  if type == :set
147
157
  set = false
148
- if pats[-1] == '['
158
+ if pats[-1] == "["
149
159
  pats.chop!
150
160
  else
151
- pats += ']'
161
+ pats += "]"
152
162
  end
153
163
  elsif type == :group
154
164
  capture = false
155
165
  unless patg.empty?
156
- patg << pats if pats.to_s != ''
166
+ patg << pats if pats.to_s != ""
157
167
  pata << patg
158
168
  patg = []
159
- pats = ''
169
+ pats = ""
160
170
  end
161
171
  end
162
172
  when :capture
163
173
  capture = true if type == :group
164
174
  when :alternation
165
175
  if type == :meta
166
- if pats != ''
176
+ if pats != ""
167
177
  patg << pats
168
- pats = ''
178
+ pats = ""
169
179
  elsif patg.empty?
170
180
  # for the case the first element was not added to patg and was on pata fex: (a+|b|c)
171
181
  patg << pata.pop
172
- end
182
+ end
173
183
  end
174
184
  when :range
175
185
  range = pats[-1]
176
186
  pats.chop!
177
187
  when :digit
178
- pats += 'n'
188
+ pats += "n"
179
189
  when :nondigit
180
- pats += '*[%0123456789%]'
190
+ pats += "*[%0123456789%]"
181
191
  when :space
182
- pats += '_'
192
+ pats += "_"
183
193
  when :nonspace
184
- pats += '*[% %]'
194
+ pats += "*[% %]"
185
195
  when :word
186
- pats += 'Ln_'
196
+ pats += "Ln_"
187
197
  when :nonword
188
- pats += '$'
198
+ pats += "$"
189
199
  when :word_boundary
190
- pats += '$'
200
+ pats += "$"
191
201
  when :dot
192
- pats += '*'
202
+ pats += "*"
193
203
  when :literal
194
- if range == ''
204
+ if range == ""
195
205
  if text.size > 1
196
- fixed_text=true
206
+ fixed_text = true
197
207
  if !patg.empty?
198
208
  patg << text.chop
199
209
  else
@@ -204,42 +214,41 @@ class Regexp
204
214
  pats += text
205
215
  end
206
216
  else
207
- range = range + '-' + text
208
- if range == 'a-z'
209
- pats = 'x' + pats
210
- elsif range == 'A-Z'
211
- pats = 'X' + pats
212
- elsif range == '0-9'
213
- pats = 'n' + pats
217
+ range = range + "-" + text
218
+ if range == "a-z"
219
+ pats = "x" + pats
220
+ elsif range == "A-Z"
221
+ pats = "X" + pats
222
+ elsif range == "0-9"
223
+ pats = "n" + pats
214
224
  else
215
225
  pats += if set
216
226
  (range[0]..range[2]).to_a.join
217
227
  else
218
- '[' + (range[0]..range[2]).to_a.join + ']'
219
- end
220
-
228
+ "[" + (range[0]..range[2]).to_a.join + "]"
229
+ end
221
230
  end
222
- range = ''
231
+ range = ""
223
232
  end
224
- pats = '[' + pats + ']' unless set
233
+ pats = "[" + pats + "]" unless set
225
234
  when :interval
226
- size = text.sub(',', '-').sub('{', '').sub('}', '')
227
- size.chop! if size[-1] == '-'
228
- pats = size + ':' + pats
235
+ size = text.sub(",", "-").sub("{", "").sub("}", "")
236
+ size.chop! if size[-1] == "-"
237
+ pats = size + ":" + pats
229
238
  if !patg.empty?
230
239
  patg << pats
231
240
  else
232
241
  pata << pats
233
242
  end
234
- pats = ''
243
+ pats = ""
235
244
  when :zero_or_one
236
- pats = '0-1:' + pats
245
+ pats = "0-1:" + pats
237
246
  if !patg.empty?
238
247
  patg << pats
239
248
  else
240
249
  pata << pats
241
250
  end
242
- pats = ''
251
+ pats = ""
243
252
  when :zero_or_more
244
253
  pats = "0-#{default_infinite}:" + pats
245
254
  if !patg.empty?
@@ -247,7 +256,7 @@ class Regexp
247
256
  else
248
257
  pata << pats
249
258
  end
250
- pats = ''
259
+ pats = ""
251
260
  when :one_or_more
252
261
  pats = "1-#{default_infinite}:" + pats
253
262
  if !patg.empty?
@@ -255,19 +264,19 @@ class Regexp
255
264
  else
256
265
  pata << pats
257
266
  end
258
- pats = ''
267
+ pats = ""
259
268
  end
260
269
  end
261
- if pats!=""
262
- if pata.empty?
263
- if pats[0]=="[" and pats[-1]=="]" #fex: /[12ab]/
270
+ if pats != ""
271
+ if pata.empty?
272
+ if pats[0] == "[" and pats[-1] == "]" #fex: /[12ab]/
264
273
  pata = ["1:#{pats}"]
265
274
  end
266
275
  else
267
- pata[-1]+=pats[1] #fex: /allo/
276
+ pata[-1] += pats[1] #fex: /allo/
268
277
  end
269
278
  end
270
- if pata.size==1 and pata[0].kind_of?(String)
279
+ if pata.size == 1 and pata[0].kind_of?(String)
271
280
  res = pata[0]
272
281
  else
273
282
  res = pata
@@ -0,0 +1,195 @@
1
+ class StringPattern
2
+ ###############################################
3
+ # Analyze the pattern supplied and returns an object of Pattern structure including:
4
+ # min_length, max_length, symbol_type, required_data, excluded_data, data_provided, string_set, all_characters_set
5
+ ###############################################
6
+ def StringPattern.analyze(pattern, silent: false)
7
+ #unless @cache[pattern.to_s].nil?
8
+ # return Pattern.new(@cache[pattern.to_s].min_length.clone, @cache[pattern.to_s].max_length.clone,
9
+ # @cache[pattern.to_s].symbol_type.clone, @cache[pattern.to_s].required_data.clone,
10
+ # @cache[pattern.to_s].excluded_data.clone, @cache[pattern.to_s].data_provided.clone,
11
+ # @cache[pattern.to_s].string_set.clone, @cache[pattern.to_s].all_characters_set.clone, @cache[pattern.to_s].unique.clone)
12
+ #end
13
+ return @cache[pattern.to_s].clone unless @cache[pattern.to_s].nil?
14
+ min_length, max_length, symbol_type = pattern.to_s.scan(/(\d+)-(\d+):(.+)/)[0]
15
+ if min_length.nil?
16
+ min_length, symbol_type = pattern.to_s.scan(/^!?(\d+):(.+)/)[0]
17
+ max_length = min_length
18
+ if min_length.nil?
19
+ puts "pattern argument not valid on StringPattern.generate: #{pattern.inspect}" unless silent
20
+ return pattern.to_s
21
+ end
22
+ end
23
+ if symbol_type[-1] == "&"
24
+ symbol_type.chop!
25
+ unique = true
26
+ else
27
+ unique = false
28
+ end
29
+
30
+ symbol_type = "!" + symbol_type if pattern.to_s[0] == "!"
31
+ min_length = min_length.to_i
32
+ max_length = max_length.to_i
33
+
34
+ required_data = Array.new
35
+ excluded_data = Array.new
36
+ required = false
37
+ excluded = false
38
+ data_provided = Array.new
39
+ a = symbol_type
40
+ begin_provided = a.index("[")
41
+ excluded_end_tag = false
42
+ unless begin_provided.nil?
43
+ c = begin_provided + 1
44
+ until c == a.size or (a[c..c] == "]" and a[c..c + 1] != "]]")
45
+ if a[c..c + 1] == "]]"
46
+ data_provided.push("]")
47
+ c = c + 2
48
+ elsif a[c..c + 1] == "%%" and !excluded
49
+ data_provided.push("%")
50
+ c = c + 2
51
+ else
52
+ if a[c..c] == "/" and !excluded
53
+ if a[c..c + 1] == "//"
54
+ data_provided.push(a[c..c])
55
+ if required
56
+ required_data.push([a[c..c]])
57
+ end
58
+ c = c + 1
59
+ else
60
+ if !required
61
+ required = true
62
+ else
63
+ required = false
64
+ end
65
+ end
66
+ else
67
+ if required
68
+ required_data.push([a[c..c]])
69
+ else
70
+ if a[c..c] == "%"
71
+ if a[c..c + 1] == "%%" and excluded
72
+ excluded_data.push([a[c..c]])
73
+ c = c + 1
74
+ else
75
+ if !excluded
76
+ excluded = true
77
+ else
78
+ excluded = false
79
+ excluded_end_tag = true
80
+ end
81
+ end
82
+ else
83
+ if excluded
84
+ excluded_data.push([a[c..c]])
85
+ end
86
+ end
87
+ end
88
+ if excluded == false and excluded_end_tag == false
89
+ data_provided.push(a[c..c])
90
+ end
91
+ excluded_end_tag = false
92
+ end
93
+ c = c + 1
94
+ end
95
+ end
96
+ symbol_type = symbol_type[0..begin_provided].to_s + symbol_type[c..symbol_type.size].to_s
97
+ end
98
+
99
+ required = false
100
+ required_symbol = ""
101
+ if symbol_type.include?("/")
102
+ symbol_type.chars.each { |stc|
103
+ if stc == "/"
104
+ if !required
105
+ required = true
106
+ else
107
+ required = false
108
+ end
109
+ else
110
+ if required
111
+ required_symbol += stc
112
+ end
113
+ end
114
+ }
115
+ end
116
+
117
+ national_set = @national_chars.chars
118
+
119
+ if symbol_type.include?("L")
120
+ alpha_set = ALPHA_SET_LOWER.clone + ALPHA_SET_CAPITAL.clone
121
+ elsif symbol_type.include?("x")
122
+ alpha_set = ALPHA_SET_LOWER.clone
123
+ if symbol_type.include?("X")
124
+ alpha_set = alpha_set + ALPHA_SET_CAPITAL.clone
125
+ end
126
+ elsif symbol_type.include?("X")
127
+ alpha_set = ALPHA_SET_CAPITAL.clone
128
+ else
129
+ alpha_set = []
130
+ end
131
+ if symbol_type.include?("T")
132
+ alpha_set = alpha_set + national_set
133
+ end
134
+
135
+ unless required_symbol.nil?
136
+ if required_symbol.include?("x")
137
+ required_data.push ALPHA_SET_LOWER.clone
138
+ end
139
+ if required_symbol.include?("X")
140
+ required_data.push ALPHA_SET_CAPITAL.clone
141
+ end
142
+ if required_symbol.include?("L")
143
+ required_data.push(ALPHA_SET_CAPITAL.clone + ALPHA_SET_LOWER.clone)
144
+ end
145
+ if required_symbol.include?("T")
146
+ required_data.push national_set
147
+ end
148
+ required_symbol = required_symbol.downcase
149
+ end
150
+ string_set = Array.new
151
+
152
+ all_characters_set = ALPHA_SET_CAPITAL.clone + ALPHA_SET_LOWER.clone + NUMBER_SET.clone + SPECIAL_SET.clone + data_provided + national_set
153
+ if symbol_type.include?("_")
154
+ unless symbol_type.include?("$")
155
+ string_set.push(" ")
156
+ end
157
+ if required_symbol.include?("_")
158
+ required_data.push([" "])
159
+ end
160
+ end
161
+
162
+ #symbol_type = symbol_type.downcase
163
+
164
+ if symbol_type.downcase.include?("x") or symbol_type.downcase.include?("l") or symbol_type.downcase.include?("t")
165
+ string_set = string_set + alpha_set
166
+ end
167
+ if symbol_type.downcase.include?("n")
168
+ string_set = string_set + NUMBER_SET
169
+ end
170
+ if symbol_type.include?("$")
171
+ string_set = string_set + SPECIAL_SET
172
+ end
173
+ if symbol_type.include?("*")
174
+ string_set = string_set + all_characters_set
175
+ end
176
+ if data_provided.size != 0
177
+ string_set = string_set + data_provided
178
+ end
179
+ unless required_symbol.empty?
180
+ if required_symbol.include?("n")
181
+ required_data.push NUMBER_SET.clone
182
+ end
183
+ if required_symbol.include?("$")
184
+ required_data.push SPECIAL_SET.clone
185
+ end
186
+ end
187
+ unless excluded_data.empty?
188
+ string_set = string_set - excluded_data.flatten
189
+ end
190
+ string_set.uniq!
191
+ @cache[pattern.to_s] = Pattern.new(min_length, max_length, symbol_type, required_data, excluded_data, data_provided,
192
+ string_set, all_characters_set, unique)
193
+ return @cache[pattern.to_s].clone
194
+ end
195
+ end