fat_core 6.0.0 → 7.1.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.
@@ -133,18 +133,15 @@ module FatCore
133
133
  a
134
134
  an
135
135
  the
136
- at
137
- for
138
- up
139
136
  and
140
137
  but
141
138
  or
142
139
  nor
140
+ at
141
+ for
143
142
  in
144
143
  on
145
- under
146
144
  of
147
- from
148
145
  as
149
146
  by
150
147
  to
@@ -179,10 +176,13 @@ module FatCore
179
176
  elsif /^(N|S|E|W|NE|NW|SE|SW)$/i.match?(w)
180
177
  # Compass directions all caps
181
178
  newwords.push(w.upcase)
179
+ elsif little_words.include?(w.downcase)
180
+ # Only capitalize at beginning or end
181
+ newwords.push(first || last ? w.capitalize : w.downcase)
182
182
  elsif w =~ /^[^aeiouy]*$/i && w.size > 2
183
183
  # All consonants and at least 3 chars, probably abbr
184
184
  newwords.push(w.upcase)
185
- elsif w =~ /^[A-Z0-9]+\z/ && preserve_acronyms
185
+ elsif w =~ /[0-9]/ && w =~ /^[A-Z0-9]+\z/ && w.size <= 5 && preserve_acronyms
186
186
  # All uppercase and numbers, keep as is
187
187
  newwords.push(w)
188
188
  elsif w =~ /^(\w+)-(\w+)$/i
@@ -192,9 +192,6 @@ module FatCore
192
192
  # Last word ended with a ':'
193
193
  newwords.push(w.capitalize)
194
194
  capitalize_next = false
195
- elsif little_words.include?(w.downcase)
196
- # Only capitalize at beginning or end
197
- newwords.push(first || last ? w.capitalize : w.downcase)
198
195
  else
199
196
  # All else
200
197
  newwords.push(w.capitalize)
@@ -229,11 +226,13 @@ module FatCore
229
226
  # @see #fuzzy_match #fuzzy_match for the specifics of string matching
230
227
  # @see #as_regexp #as_regexp for conversion of `matcher` to regular expression
231
228
  def matches_with(matcher)
229
+ target = clean.gsub(/[\*.,']/, '')
232
230
  if matcher.nil?
233
231
  nil
234
- elsif matcher =~ %r{^\s*/}
232
+ elsif matcher.match?(%r{^\s*/})
235
233
  re = matcher.as_regexp
236
- $& if to_s =~ re
234
+ md = target.match(re)
235
+ md[0] if md
237
236
  else
238
237
  to_s.fuzzy_match(matcher)
239
238
  end
@@ -242,22 +241,36 @@ module FatCore
242
241
  # Return the matched portion of self, minus punctuation characters, if self
243
242
  # matches the string `matcher` using the following notion of matching:
244
243
  #
245
- # 1. Remove all periods, commas, apostrophes, and asterisks (the punctuation
246
- # characters) from both self and `matcher`,
247
- # 2. Treat internal ':stuff' in the matcher as the equivalent of
248
- # '\bstuff.*?\b' in a regular expression, that is, match any word
244
+ # 1. Remove leading and trailing whitespace in the subject and the matcher
245
+ # and collapse its internal whitespace to a single space,
246
+ # 2. In the subject string replace periods and commas with a space (so
247
+ # they still act as word separators) but remove apostrophes, and
248
+ # asterisks so the user need not remember whether they were used when
249
+ # forming the matcher.
250
+ # 3. In the matcher, make any period, comma, asterisk, or apostrophe
251
+ # optional for the same reason.
252
+ # 4. Treat internal ':stuff' or ' :stuff' in the matcher as the equivalent
253
+ # of /\bstuff.*/ in a regular expression, that is, match any word
249
254
  # starting with stuff in self,
250
- # 3. Treat leading ':' in the matcher as anchoring the match to the
255
+ # 5. Treat internal 'stuff: ' in the matcher as the equivalent
256
+ # of /.*stuff\b/ in a regular expression, that is, match any word
257
+ # ending with stuff in self,
258
+ # 6. A colon with no spaces around it is treated as belonging to the
259
+ # following word, requiring it to start with it, so 'some:stuff'
260
+ # requires 'some' anywhere followed by a word beginning with 'stuff',
261
+ # i.e., /some.*\bstuff/i,
262
+ # 7. Treat leading ':' in the matcher as anchoring the match to the
251
263
  # beginning of the target string,
252
- # 4. Treat ending ':' in the matcher as anchoring the match to the
264
+ # 8. Treat ending ':' in the matcher as anchoring the match to the
253
265
  # end of the target string,
254
- # 5. Require each component to match the beginning of a word boundary
255
- # 6. Ignore case in the match
266
+ # 9. Require each component to match some part of self, and
267
+ # 10. Ignore case in the match
256
268
  #
257
269
  # @example
258
270
  # "St. Luke's Hospital".fuzzy_match('st lukes') #=> 'St Lukes'
259
271
  # "St. Luke's Hospital".fuzzy_match('luk:hosp') #=> 'Lukes Hosp'
260
- # "St. Luke's Hospital".fuzzy_match('st:spital') #=> 'St Lukes Hospital'
272
+ # "St. Luke's Hospital".fuzzy_match('st:spital') #=> nil
273
+ # "St. Luke's Hospital".fuzzy_match('st spital') #=> 'St Lukes Hospital'
261
274
  # "St. Luke's Hospital".fuzzy_match('st:laks') #=> nil
262
275
  # "St. Luke's Hospital".fuzzy_match(':lukes') #=> nil
263
276
  # "St. Luke's Hospital".fuzzy_match('lukes:hospital:') #=> 'Lukes Hospital'
@@ -266,23 +279,20 @@ module FatCore
266
279
  # @return [String] the unpunctuated part of self that matched
267
280
  # @return [nil] if self did not match matcher
268
281
  def fuzzy_match(matcher)
269
- # Remove periods, asterisks, commas, and apostrophes
270
- matcher = matcher.strip.gsub(/[\*.,']/, '')
271
- if matcher.start_with?(':')
272
- begin_anchor = true
273
- matcher.delete_prefix!(':')
274
- end
275
- if matcher.end_with?(':')
276
- end_anchor = true
277
- matcher.delete_suffix!(':')
278
- end
279
- target = gsub(/[\*.,']/, '')
280
- matchers = matcher.split(/[: ]+/)
281
- regexp_string = matchers.map { |m| ".*?\\b#{Regexp.escape(m)}.*?" }.join('\\b')
282
- regexp_string.sub!(/^\.\*\?/, '')
283
- regexp_string.sub!(/\.\*\?$/, '')
284
- regexp_string.sub!(/\A/, '\\A') if begin_anchor
285
- regexp_string.sub!(/\z/, '\\z') if end_anchor
282
+ # Make asterisks, periods, commas, and apostrophes optional
283
+ matcher = matcher.clean.gsub(/[\*.,']/, '\0?')
284
+ # Replace periods and commas with a space (so they are still word
285
+ # separators, e.g. 'WWW.WOLFRAM' -> 'WWW WOLFRAM' and 'AMZON,INC.' ->
286
+ # 'AMAZON INC') and remove asterisks and apostrophes
287
+ target = gsub(/[.,]/, ' ').gsub(/[\*']/, '').clean
288
+ regexp_string =
289
+ if matcher.match?(/[: ]/)
290
+ matcher.sub(/\A:/, "\\A").sub(/:\z/, "\\z")
291
+ .gsub(/:\s+/, "\\b.*").gsub(':', ".*\\b")
292
+ .gsub(/\s+/, ".*")
293
+ else
294
+ Regexp.escape(matcher)
295
+ end
286
296
  regexp = /#{regexp_string}/i
287
297
  matched_text =
288
298
  if (match = regexp.match(target))
@@ -317,7 +327,6 @@ module FatCore
317
327
  flags |= Regexp::MULTILINE if opts.include?('m')
318
328
  end
319
329
  flags = nil if flags.zero?
320
- # body = Regexp.quote(body) if REGEXP_META_CHARACTERS.include?(body)
321
330
  Regexp.new(body, flags)
322
331
  else
323
332
  Regexp.new(Regexp.quote(self), Regexp::IGNORECASE)
@@ -388,3 +397,34 @@ class String
388
397
  # @!parse include FatCore::String
389
398
  # @!parse extend FatCore::String::ClassMethods
390
399
  end
400
+
401
+ module StringPred
402
+ refine String do
403
+ # This is a kludgy version of #pred (Ruby does define it for a good
404
+ # reason, namely there is no unique string for which x.pred.succ == x).
405
+ # Still, for my Range extensions, it helps to have this limited version to
406
+ # produce a usable #pred for the #gaps method.
407
+ def pred
408
+ str = clean
409
+ return "9" if str.length == 1 && str[0] == 'A'
410
+ return "Z" if str.length == 1 && str[0] == 'a'
411
+ return "a" if str.length == 1 && str[0] == '0'
412
+ return "" if str.empty?
413
+
414
+ unless str.match?(/\A[A-Za-z0-9]+\z/)
415
+ raise NoMethodError, "undefined method :pred for \"#{self}\":String"
416
+ end
417
+
418
+ case str[-1]
419
+ when 'A'
420
+ str[0..-2].pred + 'Z'
421
+ when 'a'
422
+ str[0..-2].pred + 'z'
423
+ when '0'
424
+ str[0..-2].pred + '9'
425
+ else
426
+ str[0..-2] + (str[-1].ord - 1).chr
427
+ end
428
+ end
429
+ end
430
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'fat_core/string'
3
+ require_relative 'string'
4
4
 
5
5
  module FatCore
6
6
  module Symbol
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FatCore
4
- MAJOR = 6
5
- MINOR = 0
6
- PATCH = 0
4
+ MAJOR = 7
5
+ MINOR = 1
6
+ PATCH = 1
7
7
 
8
8
  # FatCore version number
9
9
  VERSION = [MAJOR, MINOR, PATCH].compact.join('.')
data/lib/fat_core.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/core_ext/object/blank'
2
4
  require 'active_support/core_ext/object/deep_dup'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  require 'fat_core/array'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'fat_core/bigdecimal'
3
5
 
@@ -1,51 +1,41 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'fat_core/enumerable'
3
5
 
4
6
  describe Enumerable do
5
- it 'enumerates groups of size k' do
6
- letters = ('a'..'z').to_a
7
- letters.groups_of(3).each do |_k, grp|
8
- expect(grp.class).to eq Array
9
- if grp.last == 'z'
10
- expect(grp.size).to eq(2)
11
- expect(grp).to eq(['y', 'z'])
12
- else
13
- expect(grp.size).to eq(3)
14
- expect(grp.join).to match(/\A[a-z]{3}\z/)
7
+ describe '#each_with_flags' do
8
+ it 'enumerates each with first and last flags' do
9
+ letters = ('a'..'z').to_a
10
+ letters.each_with_flags do |l, first, last|
11
+ if l == 'a'
12
+ expect(first).to be true
13
+ expect(last).to be false
14
+ elsif l == 'z'
15
+ expect(first).to be false
16
+ expect(last).to be true
17
+ else
18
+ expect(first).to be false
19
+ expect(last).to be false
20
+ end
15
21
  end
16
22
  end
17
- end
18
23
 
19
- it 'enumerates each with first and last flags' do
20
- letters = ('a'..'z').to_a
21
- letters.each_with_flags do |l, first, last|
22
- if l == 'a'
23
- expect(first).to be true
24
- expect(last).to be false
25
- elsif l == 'z'
26
- expect(first).to be false
27
- expect(last).to be true
28
- else
29
- expect(first).to be false
30
- expect(last).to be false
31
- end
24
+ it 'returns nil enumerating a beginless Range' do
25
+ bless = (..100)
26
+ result = bless.each_with_flags { |_l, _first, _last| 44 }
27
+ expect(result).to be_nil
32
28
  end
33
- end
34
29
 
35
- it 'returns nil enumerating a beginless Range' do
36
- bless = (..100)
37
- result = bless.each_with_flags { |_l, _first, _last| 44 }
38
- expect(result).to be_nil
39
- end
40
-
41
- it 'enumerates an endless Range' do
42
- eless = (1..)
43
- num = 0
44
- eless.each_with_flags do |i, _first, _last|
45
- num += i
46
- break if i >= 100
30
+ it 'enumerates an endless Range' do
31
+ eless = (1..)
32
+ num = 0
33
+ eless.each_with_flags do |i, _first, _last|
34
+ num += i
35
+ break if i >= 100
36
+ end
37
+ # Look at me, I'm Gauss
38
+ expect(num).to eq(5050)
47
39
  end
48
- # Look at me, I'm Gauss
49
- expect(num).to eq(5050)
50
40
  end
51
41
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'fat_core/hash'
3
5
 
@@ -10,8 +12,8 @@ describe Hash do
10
12
 
11
13
  it 'deletes entries with a value == to X' do
12
14
  hh = { :a => 1, :b => 2, :c => 1 }
13
- expect(hh.delete_with_value(1)).to eq({ :b => 2 })
14
- expect(hh.delete_with_value(9)).to eq hh
15
+ expect(hh.delete_with_value!(1)).to eq({ :b => 2 })
16
+ expect(hh.delete_with_value!(9)).to eq hh
15
17
  end
16
18
 
17
19
  it 'maps keys to new keys' do
@@ -29,4 +31,19 @@ describe Hash do
29
31
  h3 = { e: 'EEE' }
30
32
  expect(h1 << h2 << h3).to eq({ a: 'A', b: 'BB', c: 'C', d: 'DD', e: 'EEE' })
31
33
  end
34
+
35
+ it 'can take any Enumerable as a right argument' do
36
+ FileUtils.mkdir_p('./tmp')
37
+ ff = File.open('./tmp/junk', 'w')
38
+ ff.write("f\n", "FFFF\n", "g\n", "GGGG\n")
39
+ ff.close
40
+ ff = File.open('./tmp/junk', 'r')
41
+ h = { a: 'A', b: 'B', c: 'C' } << [:c, 'CC', :d, 'DD'] <<
42
+ { d: 'DDD', e: 'EEE' } <<
43
+ ff.readlines.map(&:chomp)
44
+ h.transform_keys!(&:to_sym)
45
+ ff.close
46
+ expect(h.keys).to include(:a, :b, :c, :d, :e, :f, :g)
47
+ FileUtils.rm_rf('./tmp/junk')
48
+ end
32
49
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'fat_core/nil'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'fat_core/numeric'
3
5
 
@@ -16,6 +18,18 @@ describe Numeric do
16
18
 
17
19
  it 'provides a tex_quote method for erb docs' do
18
20
  expect(195.45.tex_quote).to eq '195.45'
21
+ expect(195.00.tex_quote).to eq '195.0'
22
+ expect(58743.44.tex_quote).to eq '58743.44'
23
+ expect(Float::INFINITY.tex_quote).to eq("$\\infty$")
24
+ expect((-Float::INFINITY).tex_quote).to eq("$-\\infty$")
25
+ expect(Complex(5, 3).tex_quote).to eq("$5+3i$")
26
+ expect(Complex(7, 1).tex_quote).to eq("$7+i$")
27
+ expect(Complex(7.00, 1).tex_quote).to eq("$7+i$")
28
+ expect(Complex(Math::PI, 1).tex_quote).to eq("$\\pi+i$")
29
+ expect(Complex(Math::E, 1).tex_quote).to eq("$e+i$")
30
+ expect(Complex(Math::E, Math::PI).tex_quote).to eq("$e+\\pi i$")
31
+ expect(Complex(Math::PI, Math::E).tex_quote).to eq("$\\pi+e i$")
32
+ expect(Rational(5, 3).tex_quote).to eq("$\\frac{5}{3}$")
19
33
  end
20
34
 
21
35
  it 'knows if its a whole number' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'fat_core/range'
3
5
 
@@ -206,6 +208,10 @@ describe Range do
206
208
  expect(gaps[1]).to eq(7..8)
207
209
  end
208
210
 
211
+ it 'returns gaps for letter ranges' do
212
+ expect(('a'..'z').gaps([('a'..'g'), ('j'..'s'), ('t'..'z')])).to eq([Range.new('h', 'i')])
213
+ end
214
+
209
215
  it 'allows ranges to extend before and after self' do
210
216
  gaps = (0..10).gaps([(-3..3), (4..6), (7..13)])
211
217
  expect(gaps).to be_empty
@@ -244,6 +250,10 @@ describe Range do
244
250
  gaps = (0..10).gaps([(-2..3), (2..8), (4..10)])
245
251
  expect(gaps).to be_empty
246
252
  end
253
+
254
+ it 'raises an error if argument types are incompatible' do
255
+ expect { ('A'..'F').gaps([(1..5), (6..11)]) }.to raise_error(/incompatible/)
256
+ end
247
257
  end
248
258
 
249
259
  describe '#overlaps' do
@@ -96,6 +96,22 @@ the people, for the people, shall not perish from the earth."
96
96
  expect(' string here '.clean).to eq 'string here'
97
97
  end
98
98
 
99
+ using StringPred
100
+
101
+ it 'computes predecessor to String' do
102
+ expect("B".pred).to eq("A")
103
+ expect("C".pred).to eq("B")
104
+ expect("D".pred).to eq("C")
105
+ expect("Z".pred).to eq("Y")
106
+ expect("AAA".pred).to eq("9ZZ")
107
+ expect("A".pred).to eq("9")
108
+ expect("BBA".pred).to eq("BAZ")
109
+ expect("00123".pred).to eq("00122")
110
+ expect("9999".succ).to eq("10000")
111
+ expect("00000".pred).to eq("a9999")
112
+ expect { "00123+".pred }.to raise_error(/undefined method/)
113
+ end
114
+
99
115
  describe 'numeric strings' do
100
116
  it 'converts a numeric string to a commified form' do
101
117
  expect('20140521'.commas).to eq '20,140,521'
@@ -138,7 +154,6 @@ the people, for the people, shall not perish from the earth."
138
154
  expect('-8.008'.number?).to be true
139
155
  expect('8.008e33'.number?).to be true
140
156
  expect('-8.008e33'.number?).to be true
141
- expect('0x8.008').to be_number
142
157
  expect('hello world'.number?).to be false
143
158
  end
144
159
  end
@@ -205,7 +220,7 @@ the people, for the people, shall not perish from the earth."
205
220
  expect('tr'.entitle).to eq('Tr')
206
221
  expect('trd'.entitle).to eq('TRD')
207
222
  # Don't capitalize c/o
208
- expect('IBM c/o watson'.entitle).to eq('IBM c/o Watson')
223
+ expect('sherLOCK c/o watson'.entitle).to eq('Sherlock c/o Watson')
209
224
  # Capitlaize p.o.
210
225
  expect('p.o. box 123'.entitle).to eq('P.O. Box 123')
211
226
  # Don't capitalize ordinals
@@ -215,8 +230,6 @@ the people, for the people, shall not perish from the earth."
215
230
  expect('nw territory'.entitle).to eq('NW Territory')
216
231
  # Leave word starting with numbers alone
217
232
  expect('apartment 33-B'.entitle).to eq('Apartment 33-B')
218
- # Assume all uppercase is an acronym
219
- expect('the ABC network'.entitle).to eq('The ABC Network')
220
233
  # But not if the whole string is uppercase
221
234
  expect('THE ABC NETWORK'.entitle).to eq('The Abc Network')
222
235
  # Capitalize both parts of a hyphenated word
@@ -244,37 +257,61 @@ the people, for the people, shall not perish from the earth."
244
257
  describe 'Fuzzy Matching' do
245
258
  it 'fuzzy matches with another string' do
246
259
  expect('Hello, world'.fuzzy_match('wor')).to be_truthy
260
+ expect('Hello, world'.fuzzy_match('orl')).to be_truthy
247
261
  expect('Hello, world'.fuzzy_match('ox')).to be_falsy
248
262
  end
249
263
 
250
- it 'fuzzy matches with another string containing re' do
251
- expect('Hello, world'.matches_with('/or/')).to be_truthy
252
- expect('Hello, world'.matches_with('/ox/')).to be_falsy
264
+ it 'replaces periods and commas with a space so they are still word separators' do
265
+ expect('WWW.WOLFRAM.COM'.fuzzy_match('wolf')).to be_truthy
266
+ expect('AMAZON,INC'.fuzzy_match('amazon inc')).to be_truthy
267
+ end
268
+
269
+ it 'modifies self by removing asterisks and apostrophes' do
270
+ expect('WWW*WOLFRAM*COM'.fuzzy_match('wolf')).to be_truthy
271
+ expect('E*TRADE'.fuzzy_match('etrade')).to be_truthy
272
+ expect('WWW*WOLFRAM*COM'.fuzzy_match(':wolf')).to be_falsy
273
+ expect('WWW.WOLFRAM.COM'.fuzzy_match('wolf')).to be_truthy
274
+ expect('AMAZON,INC'.fuzzy_match('amazon inc')).to be_truthy
253
275
  end
254
276
 
255
- it 'fuzzy matches space-separated parts' do
277
+ it 'treats internal space as dot-star' do
256
278
  expect('Hello world'.fuzzy_match('hel wor')).to be_truthy
279
+ expect('Hello, world'.fuzzy_match('el or')).to be_truthy
257
280
  expect('Hello, world'.fuzzy_match('hel ox')).to be_falsy
281
+ expect('Hello, what is with the world?'.fuzzy_match('at wi or')).to be_truthy
258
282
  end
259
283
 
260
284
  it 'fuzzy matches colon-separated parts' do
261
285
  expect('Hello:world'.fuzzy_match('hel:wor')).to be_truthy
262
- expect('Hello:world'.fuzzy_match('hel:ox')).to be_falsy
286
+ expect('Hello:world'.fuzzy_match('hel :wor')).to be_truthy
287
+ expect('Hello:world'.fuzzy_match('hel: wor')).to be_falsy
288
+ expect('Hello:world'.fuzzy_match('hel:orld')).to be_falsy
289
+ expect("Hello, 'world'".fuzzy_match('hel:wor')).to be_truthy
290
+ expect('Hello "world"'.fuzzy_match('hel:world')).to be_truthy
263
291
  end
264
292
 
265
- it 'treats an internal `:stuff in the matcher as \bstuff.*?\b' do
293
+ it 'treats an internal `:stuff` as \bstuff.*' do
266
294
  expect('Hello, what is with the world?'.fuzzy_match('wha:wi:wor')).to be_truthy
295
+ expect('Hello, what is with the world?'.fuzzy_match('hat :wi :wor')).to be_truthy
267
296
  expect('Hello:world'.fuzzy_match('what:or')).to be_falsy
268
297
  expect('Hello, what=+&is (with) the world?'.fuzzy_match('wha:wi:wor')).to be_truthy
269
298
  end
270
299
 
300
+ it 'treats an internal `stuff: ` as stuff\b.*' do
301
+ expect('Hello, what is with the world?'.fuzzy_match('llo: th: :wor')).to be_truthy
302
+ expect('Hello:world'.fuzzy_match('llox: ')).to be_falsy
303
+ expect('Hello, what=+&is (with) the world?'.fuzzy_match('at: ith: the')).to be_truthy
304
+ end
305
+
271
306
  it 'requires end-anchor for ending colon' do
272
307
  expect('Hello, to the world'.fuzzy_match('hel:world:')).to eq('Hello to the world')
308
+ expect('Hello, to the world '.fuzzy_match('hel:world:')).to eq('Hello to the world')
273
309
  expect('Hello, to the world today'.fuzzy_match('to:world:')).to be_nil
274
310
  end
275
311
 
276
312
  it 'requires start-anchor for leading colon' do
277
313
  expect('Hello, to the world'.fuzzy_match(':hel:the')).to eq('Hello to the')
314
+ expect(' Hello, to the world'.fuzzy_match(':hel:the')).to eq('Hello to the')
278
315
  expect('Hello, to the world today'.fuzzy_match(':world:today')).to be_nil
279
316
  end
280
317
 
@@ -289,15 +326,62 @@ the people, for the people, shall not perish from the earth."
289
326
  expect('Hello:world'.matches_with('/^h.*r/')).to eq('Hello:wor')
290
327
  end
291
328
 
292
- it 'ignores periods, commas, and apostrophes when matching' do
329
+ it 'make periods, commas, and apostrophes optional when matching' do
293
330
  expect("St. Luke's".fuzzy_match('st lukes')).to eq('St Lukes')
294
- expect('St Lukes'.fuzzy_match('st. luke\'s')).to eq('St Lukes')
331
+ expect("St. Luke's".fuzzy_match('st. luke\'s')).to eq('St Lukes')
332
+ expect("St Lukes".fuzzy_match('st. luke\'s')).to eq('St Lukes')
295
333
  expect('St Lukes, Inc.'.fuzzy_match('st luke inc')).to eq('St Lukes Inc')
334
+ expect('St Lukes, Inc.'.fuzzy_match('st lukes, inc')).to eq('St Lukes Inc')
296
335
  expect('E*TRADE'.fuzzy_match('etrade')).to eq('ETRADE')
297
336
  # Does not recognize non-alphanumerics as start of string.
298
337
  expect('The 1 Dollar Store'.fuzzy_match('1 stor')).to be_truthy
299
338
  expect('The $1 Dollar Store'.fuzzy_match('$1 stor')).to be_falsy
300
339
  end
340
+
341
+ it 'performs examples in documentation' do
342
+ expect("St. Luke's".fuzzy_match('st lukes')).to eq('St Lukes')
343
+ expect("St. Luke's Hospital".fuzzy_match('st lukes')).to eq('St Lukes')
344
+ expect("St. Luke's Hospital".fuzzy_match('luk:hosp')).to eq('Lukes Hosp')
345
+ expect("St. Luke's Hospital".fuzzy_match('st:spital')).to be_nil
346
+ expect("St. Luke's Hospital".fuzzy_match('st spital')).to eq('St Lukes Hospital')
347
+ expect("St. Luke's Hospital".fuzzy_match('st:laks')).to be_nil
348
+ expect("St. Luke's Hospital".fuzzy_match(':lukes')).to be_nil
349
+ expect("St. Luke's Hospital".fuzzy_match('lukes:hospital')).to eq('Lukes Hospital')
350
+ end
351
+ end
352
+
353
+ describe '#matches_with' do
354
+ it 'matches with another string containing a plain string' do
355
+ expect('Hello, world'.matches_with('or')).to be_truthy
356
+ expect('Hello, world'.matches_with('ox')).to be_falsy
357
+ end
358
+
359
+ it 'matches with another string containing re' do
360
+ expect('Hello, world'.matches_with('/or/')).to be_truthy
361
+ expect('Hello, world'.matches_with('/ox/')).to be_falsy
362
+ end
363
+
364
+ it 'performs examples in documentation with just strings' do
365
+ expect("St. Luke's".matches_with('st lukes')).to eq('St Lukes')
366
+ expect("St. Luke's Hospital".matches_with('st lukes')).to eq('St Lukes')
367
+ expect("St. Luke's Hospital".matches_with('luk:hosp')).to eq('Lukes Hosp')
368
+ expect("St. Luke's Hospital".matches_with('st:spital')).to be_nil
369
+ expect("St. Luke's Hospital".matches_with('st spital')).to eq('St Lukes Hospital')
370
+ expect("St. Luke's Hospital".matches_with('st:laks')).to be_nil
371
+ expect("St. Luke's Hospital".matches_with(':lukes')).to be_nil
372
+ expect("St. Luke's Hospital".matches_with('lukes:hospital')).to eq('Lukes Hospital')
373
+ end
374
+
375
+ it 'performs examples in documentation with regexes' do
376
+ expect("St. Luke's".matches_with('/st\s*lukes/')).to eq('St Lukes')
377
+ expect("St. Luke's Hospital".matches_with('/st lukes/')).to eq('St Lukes')
378
+ expect("St. Luke's Hospital".matches_with('/luk.*\bhosp/')).to eq('Lukes Hosp')
379
+ expect("St. Luke's Hospital".matches_with('/st(.*)spital\z/')).to eq('St Lukes Hospital')
380
+ expect("St. Luke's Hospital".matches_with('/st spital/')).to be_nil
381
+ expect("St. Luke's Hospital".matches_with('/st.*laks/')).to be_nil
382
+ expect("St. Luke's Hospital".matches_with('/\Alukes/')).to be_nil
383
+ expect("St. Luke's Hospital".matches_with('/lukes hospital/')).to eq('Lukes Hospital')
384
+ end
301
385
  end
302
386
  end
303
387
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'fat_core/symbol'
3
5
 
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'simplecov'
2
4
  SimpleCov.command_name 'Rspec'
3
5
 
@@ -8,7 +10,7 @@ require 'pry'
8
10
  require 'debug'
9
11
 
10
12
  require 'active_support/testing/time_helpers'
11
- require 'fat_core'
13
+ require_relative '../lib/fat_core/all'
12
14
 
13
15
  # This file was generated by the `rspec --init` command. Conventionally, all
14
16
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.