fat_core 7.1.3 → 7.2.0

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/README.md ADDED
@@ -0,0 +1,1199 @@
1
+ - [Version](#org706993f)
2
+ - [Introduction](#org8e3de1e)
3
+ - [Installation](#orge71ccdc)
4
+ - [Usage](#org1ef61a0)
5
+ - [Array](#orgfc24a05)
6
+ - [Method `#comma_join(sep: nil, last_sep: nil, two_sep: nil)`](#org779ed95)
7
+ - [Method `#last_i`](#org07f787c)
8
+ - [Method `#intersect_with_dups`](#org0d2857b)
9
+ - [Method `diff_with_dups`](#org83423fa)
10
+ - [BigDecimal `#inspect`](#orgf77f8a1)
11
+ - [Enumerable](#orgdce8ffe)
12
+ - [Method `#each_with_flags`](#org166e57c)
13
+ - [Hash](#org1e11773)
14
+ - [Method `#each_pair_with_flags`](#org0bd20b9)
15
+ - [Method `#delete_with_value` and `#delete_with_value!`](#org4dc0aa1)
16
+ - [Method `#keys_with_value`](#org605ad55)
17
+ - [Method `#remap_keys`](#orgdde4b0b)
18
+ - [Method `#replace_keys`](#org7603809)
19
+ - [Alias `#merge` to `<<`](#orgadf50ea)
20
+ - [Numeric](#org3918509)
21
+ - [Method `#signum`](#org6abf375)
22
+ - [Method `#commas(places = nil)`](#org00c3e90)
23
+ - [Methods `#whole?` and `#int_if_whole`](#orgb844d6f)
24
+ - [Method `#secs_to_hms`](#orgfd1b851)
25
+ - [Range](#org7a70260)
26
+ - [Methods `#contiguous`, `#left_contiguous`, `#right_contiguous`](#orgdd06e2c)
27
+ - [Method `#join(other)`](#org28a7d95)
28
+ - [Method `#spanned_by?(others)`](#org5d367a6)
29
+ - [Methods `#gaps(others)`, `#overlaps(others)`](#orga33fd47)
30
+ - [String](#orgbd1bd5e)
31
+ - [Method `#fuzzy_match`](#org63111cb)
32
+ - [Method `#matches_with`](#orgdae93bf)
33
+ - [Method `#entitle`](#org1a5d1e4)
34
+ - [Method `#distance`](#orgd671ee5)
35
+ - [Method `#commas(places)`](#orgfdd51bd)
36
+ - [Method `#wrap(width, hang)`](#org826950e)
37
+ - [Method `#as_sym`](#orgc017d90)
38
+ - [Method `gut`](#org3459d99)
39
+ - [Symbol](#org2241c53)
40
+ - [Method `#as_str`](#orgf2478cc)
41
+ - [TeX Quoting](#org5620bc3)
42
+ - [Contributing](#orgfe2e72b)
43
+
44
+ [![CI](https://github.com/ddoherty03/fat_core/actions/workflows/ruby.yml/badge.svg?branch=master)](https://github.com/ddoherty03/fat_core/actions/workflows/ruby.yml)
45
+
46
+
47
+ <a id="org706993f"></a>
48
+
49
+ # Version
50
+
51
+ ```ruby
52
+ "Current version is: #{FatCore::VERSION}"
53
+ ```
54
+
55
+ ```
56
+ Current version is: 7.1.3
57
+ ```
58
+
59
+
60
+ <a id="org8e3de1e"></a>
61
+
62
+ # Introduction
63
+
64
+ `fat-core` is somewhat of a grab bag of core class extensions that I have found useful across several projects. It's higgeldy-piggeldy nature reflects the fact that none of them are important enough to deserve a gem of their own, but nonetheless need to be collected in one place to reduce redundancy across projects and provide a focused place to develop and test them.
65
+
66
+
67
+ <a id="orge71ccdc"></a>
68
+
69
+ # Installation
70
+
71
+ Add this line to your application's Gemfile:
72
+
73
+ ```ruby
74
+ gem 'fat_core'
75
+ ```
76
+
77
+ And then execute:
78
+
79
+ ```sh
80
+ $ bundle
81
+ ```
82
+
83
+ Or install it yourself as:
84
+
85
+ ```sh
86
+ $ gem install fat_core
87
+ ```
88
+
89
+
90
+ <a id="org1ef61a0"></a>
91
+
92
+ # Usage
93
+
94
+ You can extend classes individually by requiring the corresponding file:
95
+
96
+ ```ruby
97
+ require 'fat_core/array'
98
+ require 'fat_core/bigdecimal'
99
+ require 'fat_core/enumerable'
100
+ require 'fat_core/hash'
101
+ require 'fat_core/kernel'
102
+ require 'fat_core/numeric'
103
+ require 'fat_core/range'
104
+ require 'fat_core/string'
105
+ require 'fat_core/symbol'
106
+ ```
107
+
108
+ Or, you can require them all:
109
+
110
+ ```ruby
111
+ require 'fat_core/all'
112
+ ```
113
+
114
+ ```
115
+ false
116
+ ```
117
+
118
+ Many of these have little that is of general interest, but there are a few goodies.
119
+
120
+
121
+ <a id="orgfc24a05"></a>
122
+
123
+ ## Array
124
+
125
+
126
+ <a id="org779ed95"></a>
127
+
128
+ ### Method `#comma_join(sep: nil, last_sep: nil, two_sep: nil)`
129
+
130
+ Convert this array into a single string by (1) applying `#to_s` to each element and (2) joining the elements with the string given by the `sep:` parameter. By default the sep parameter is ', '.
131
+
132
+ You may use a different separation string in the case when there are only two items in the list by supplying a `two_sep` parameter.
133
+
134
+ You may also supply a difference separation string to separate the second-last and last items in the array by supplying a `last_sep:` parameter.
135
+
136
+ By default, the sep parameter is the string ', ', the `two_sep` is ' and ', and the `last_sep` is ', and ', all of which makes for a well-punctuated English clause.
137
+
138
+ If `sep` is given, the other two parameters are set to its value by default. If `last_sep` is given, `two_sep` takes its value by default.
139
+
140
+ If the input array is empty, `#comma_join` returns an empty string.
141
+
142
+ ```ruby
143
+ %w{hammers nails glue bolts}.comma_join
144
+ ```
145
+
146
+ ```
147
+ hammers, nails, glue, and bolts
148
+ ```
149
+
150
+ ```ruby
151
+ %w{hammers nails}.comma_join
152
+ ```
153
+
154
+ ```
155
+ hammers and nails
156
+ ```
157
+
158
+ And, if you are ideologically opposed to the Oxford comma:
159
+
160
+ ```ruby
161
+ %w{hammers nails glue bolts}.comma_join(last_sep: ' and ')
162
+ ```
163
+
164
+ ```
165
+ hammers, nails, glue and bolts
166
+ ```
167
+
168
+
169
+ <a id="org07f787c"></a>
170
+
171
+ ### Method `#last_i`
172
+
173
+ Return the index of the last element of the Array.
174
+
175
+ ```ruby
176
+ %w{hammers nails glue bolts}.last_i
177
+ ```
178
+
179
+ ```
180
+ 3
181
+ ```
182
+
183
+
184
+ <a id="org0d2857b"></a>
185
+
186
+ ### Method `#intersect_with_dups`
187
+
188
+ Return a new Array that is the intersection of this Array with all `others`, but without removing duplicates as the `Array#&` method does. All items of this Array are included in the result but only if they also appear in all of the other Arrays.
189
+
190
+ ```ruby
191
+ a = %w{hammers nails glue bolts nails}
192
+ b = %w{nails fingers bolts knuckles nails}
193
+ a.intersect_with_dups(b)
194
+ ```
195
+
196
+ ```
197
+ | nails | bolts | nails |
198
+ ```
199
+
200
+
201
+ <a id="org83423fa"></a>
202
+
203
+ ### Method `diff_with_dups`
204
+
205
+ Return an Array that is the difference between this Array and `other`, but without removing duplicates as the Array#- method does. All items of this Array are included in the result *unless* they also appear in any of the `other` Arrays.
206
+
207
+ ```ruby
208
+ a = %w{hammers nails glue bolts hammers nails}
209
+ b = %w{nails fingers knuckles nails}
210
+ a.diff_with_dups(b)
211
+ ```
212
+
213
+ ```
214
+ | hammers | glue | bolts | hammers |
215
+ ```
216
+
217
+
218
+ <a id="orgf77f8a1"></a>
219
+
220
+ ## BigDecimal `#inspect`
221
+
222
+ `FatCore` provides nothing but a better `#inspect` method for the `BigDecimal` class since the default inspect method is not very readable.
223
+
224
+ ```ruby
225
+ BigDecimal('2.1718281828').inspect
226
+ ```
227
+
228
+ ```
229
+ 2.1718281828
230
+ ```
231
+
232
+ Without `FatCore`, the result is "0.2718281828e1", forcing you to interpret the exponent to understand where the decimal place is.
233
+
234
+
235
+ <a id="orgdce8ffe"></a>
236
+
237
+ ## Enumerable
238
+
239
+
240
+ <a id="org166e57c"></a>
241
+
242
+ ### Method `#each_with_flags`
243
+
244
+ `FatCore::Enumerable` extends `Enumerable` with the `#each_with_flags` method that yields the elements of the `Enumerable` but also yields two booleans, `first` and `last` that are set to `true` on respectively, the first and last element of the Enumerable and `false` otherwise. This makes it easy to treat these two cases specially without testing the index as in `#each_with_index`.
245
+
246
+ ```ruby
247
+ result = []
248
+ fibs = %w{1, 1, 2, 3, 5, 8, 13, 21}
249
+ fibs.each_with_flags do |f, first, last|
250
+ result <<
251
+ if first
252
+ ["Start", f]
253
+ elsif last
254
+ ["Last", f]
255
+ else
256
+ ["Continue", f]
257
+ end
258
+ end
259
+ result
260
+ ```
261
+
262
+ ```
263
+ | Start | 1, |
264
+ | Continue | 1, |
265
+ | Continue | 2, |
266
+ | Continue | 3, |
267
+ | Continue | 5, |
268
+ | Continue | 8, |
269
+ | Continue | 13, |
270
+ | Last | 21 |
271
+ ```
272
+
273
+
274
+ <a id="org1e11773"></a>
275
+
276
+ ## Hash
277
+
278
+ FatCore::Hash extends the Hash class with some useful methods.
279
+
280
+
281
+ <a id="org0bd20b9"></a>
282
+
283
+ ### Method `#each_pair_with_flags`
284
+
285
+ As with the extension for `Enumerables`, `FatCore` provides a method for enumerating the key-value pair of the `Hash` with flags that are set `true` for the first and last elements but `false` otherwise:
286
+
287
+ ```ruby
288
+ h = {'Chaucer' => 'Cantebury Tales', 'Shakespeare' => 'The Merchant of Venice',
289
+ 'Austen' => 'Pride and Prejudice', 'C. Brontë' => 'Jane Eyre',
290
+ 'E. Brontë' => 'Wuthering Heights' }
291
+ result = []
292
+ result << ['Position', 'Author', 'Novel']
293
+ result << nil
294
+ h.each_pair_with_flags do |k, v, first, last|
295
+ pos=
296
+ if first
297
+ 'Begin'
298
+ elsif last
299
+ 'End'
300
+ else
301
+ 'Middle'
302
+ end
303
+ result << [pos, k, v]
304
+ end
305
+ result
306
+ ```
307
+
308
+ ```
309
+ | Position | Author | Novel |
310
+ |----------+-------------+------------------------|
311
+ | Begin | Chaucer | Cantebury Tales |
312
+ | Middle | Shakespeare | The Merchant of Venice |
313
+ | Middle | Austen | Pride and Prejudice |
314
+ | Middle | C. Brontë | Jane Eyre |
315
+ | End | E. Brontë | Wuthering Heights |
316
+ ```
317
+
318
+
319
+ <a id="org4dc0aa1"></a>
320
+
321
+ ### Method `#delete_with_value` and `#delete_with_value!`
322
+
323
+ This method modifies a `Hash` by deleting the key-value pairs when the value equals the given value or values:
324
+
325
+ ```ruby
326
+ h = { a: 1, b: 2, c: 3, d: 2, e: 1 }
327
+ h.delete_with_value!(2)
328
+ puts h
329
+ ```
330
+
331
+ ```
332
+ {:a=>1, :c=>3, :e=>1}
333
+ ```
334
+
335
+ You can supply multiple values for deletion:
336
+
337
+ ```ruby
338
+ h = { a: 1, b: 2, c: 3, d: 2, e: 1 }
339
+ h.delete_with_value!(1, 3)
340
+ puts h
341
+ ```
342
+
343
+ ```
344
+ {:b=>2, :d=>2}
345
+ ```
346
+
347
+ The non-bang method returns a clone of the Hash with the given deletions made:
348
+
349
+ ```ruby
350
+ h = { a: 1, b: 2, c: 3, d: 2, e: 1 }
351
+ h2 = h.delete_with_value(1, 3)
352
+ puts h
353
+ puts h2
354
+ ```
355
+
356
+ ```
357
+ {:a=>1, :b=>2, :c=>3, :d=>2, :e=>1}
358
+ {:b=>2, :d=>2}
359
+ ```
360
+
361
+
362
+ <a id="org605ad55"></a>
363
+
364
+ ### Method `#keys_with_value`
365
+
366
+ Return an `Array` of keys of the `Hash` with a value `==` to the given value or values.
367
+
368
+ ```ruby
369
+ h = { a: 1, b: 2, c: 3, d: 2, e: 1 }
370
+ h.keys_with_value(1).inspect
371
+ ```
372
+
373
+ ```
374
+ "[:a, :e]"
375
+ ```
376
+
377
+ ```ruby
378
+ h = { a: 1, b: 2, c: 3, d: 2, e: 1 }
379
+ h.keys_with_value(2, 3).inspect
380
+ ```
381
+
382
+ ```
383
+ "[:b, :d, :c]"
384
+ ```
385
+
386
+
387
+ <a id="orgdde4b0b"></a>
388
+
389
+ ### Method `#remap_keys`
390
+
391
+ This method pre-dates the new `#transform_keys` method now available for `Hash`, but it is kept as an alternative. It takes a `Hash` as an argument that maps existing keys to their replacement in the resulting `Hash`. The original `Hash` is not effected.
392
+
393
+ ```ruby
394
+ require_relative './lib/fat_core/hash'
395
+
396
+ h = { a: 1, b: 2, c: 3, d: 2, e: 1 }
397
+ h.remap_keys({:a => :A, :b => :B}).inspect
398
+ ```
399
+
400
+ ```
401
+ "{:A=>1, :B=>2, :c=>3, :d=>2, :e=>1}"
402
+ ```
403
+
404
+ These days, a more systematic job could be done with `#transform_keys`:
405
+
406
+ ```ruby
407
+ h = { a: 1, b: 2, c: 3, d: 2, e: 1 }
408
+ h.transform_keys { |k| k.to_s.upcase.to_sym }.inspect
409
+ ```
410
+
411
+ ```
412
+ "{:A=>1, :B=>2, :C=>3, :D=>2, :E=>1}"
413
+ ```
414
+
415
+
416
+ <a id="org7603809"></a>
417
+
418
+ ### Method `#replace_keys`
419
+
420
+ A wholesale replacement of the existing keys can be done with this method:
421
+
422
+ ```ruby
423
+ h = { a: 1, b: 2, c: 3, d: 2, e: 1 }
424
+ h.replace_keys([:z, :y, :x, :w, :v]).inspect
425
+ ```
426
+
427
+ ```
428
+ "{:z=>1, :y=>2, :x=>3, :w=>2, :v=>1}"
429
+ ```
430
+
431
+
432
+ <a id="orgadf50ea"></a>
433
+
434
+ ### Alias `#merge` to `<<`
435
+
436
+ Finally, `FatCore` adds the "shovel" operator as an alias for `#merge` to provide a pretty way to represent the merger of the right `Hash` into the left `Hash`:
437
+
438
+ ```ruby
439
+ {a: 'A', b: 'B', c: 'C'} << {c: 'CC', d: 'DD'} << {d: 'DDD', e: 'EEE'}
440
+ ```
441
+
442
+ ```
443
+ {:a=>"A", :b=>"B", :c=>"CC", :d=>"DDD", :e=>"EEE"}
444
+ ```
445
+
446
+ It groups values into pairs and applies the `#to_h` method to the right-hand argument if it is an `Enumerable`, so it also works if the right-hand argument is an `Array` or `Enumerable`:
447
+
448
+ ```ruby
449
+ require 'fileutils'
450
+
451
+ FileUtils.mkdir_p('./tmp')
452
+ ff = File.open('./tmp/junk', 'w')
453
+ ff.write("f\n", "FFFF\n", "g\n", "GGGG\n")
454
+ ff.close
455
+ ff = File.open('./tmp/junk', 'r')
456
+ h = {a: 'A', b: 'B', c: 'C'} <<
457
+ [:c, 'CC', :d, 'DD'] <<
458
+ {d: 'DDD', e: 'EEE'} <<
459
+ ff.readlines.map(&:chomp) <<
460
+ [[:h, 'HHHHH'], [:j, 'JJJJJ']]
461
+ ff.close
462
+ FileUtils.rm_rf('./tmp/junk')
463
+ h
464
+ ```
465
+
466
+ ```
467
+ {:a=>"A", :b=>"B", :c=>"CC", :d=>"DDD", :e=>"EEE", "f"=>"FFFF", "g"=>"GGGG", :h=>"HHHHH", :j=>"JJJJJ"}
468
+ ```
469
+
470
+
471
+ <a id="org3918509"></a>
472
+
473
+ ## Numeric
474
+
475
+ FatCore::Numeric has methods for inserting grouping commas into a number (`#commas` and `#group`), for converting seconds to HH:MM:SS.dd format (`#secs_to_hms`), for testing for integrality (`#whole?` and `#int_if_whole`), and testing for sign (`#signum`).
476
+
477
+
478
+ <a id="org6abf375"></a>
479
+
480
+ ### Method `#signum`
481
+
482
+ Return `-1` for negative numbers, `0` for zero, and `+1` for positive numbers. This is sometimes handy.
483
+
484
+ ```ruby
485
+ [-55.signum, 0.signum, 55.signum]
486
+ ```
487
+
488
+ ```
489
+ [-1, 0, 1]
490
+ ```
491
+
492
+
493
+ <a id="org00c3e90"></a>
494
+
495
+ ### Method `#commas(places = nil)`
496
+
497
+ To get s `String` representation of a `Numeric` with grouping commas inserted, `FatCore` provides the `#commas` method:
498
+
499
+ ```ruby
500
+ result = []
501
+ result << ['N', 'Places', 'N.commas(places)']
502
+ result << nil
503
+ nums = [3.14159, 2.718281828, 100000, 0.0059, 16236565468798.66877]
504
+ places = [0, 3, 5]
505
+ nums.each do |n|
506
+ places.each do |pl|
507
+ result << [n, pl, n.commas(pl)]
508
+ end
509
+ end
510
+ result
511
+ ```
512
+
513
+ ```
514
+ | N | Places | N.commas(places) |
515
+ |--------------------+--------+--------------------------|
516
+ | 3.14159 | 0 | 3 |
517
+ | 3.14159 | 3 | 3.142 |
518
+ | 3.14159 | 5 | 3.14159 |
519
+ | 2.718281828 | 0 | 3 |
520
+ | 2.718281828 | 3 | 2.718 |
521
+ | 2.718281828 | 5 | 2.71828 |
522
+ | 100000 | 0 | 100,000 |
523
+ | 100000 | 3 | 100,000.000 |
524
+ | 100000 | 5 | 100,000.00000 |
525
+ | 0.0059 | 0 | 0 |
526
+ | 0.0059 | 3 | 0.006 |
527
+ | 0.0059 | 5 | 0.00590 |
528
+ | 16236565468798.668 | 0 | 16,236,565,468,799 |
529
+ | 16236565468798.668 | 3 | 16,236,565,468,798.668 |
530
+ | 16236565468798.668 | 5 | 16,236,565,468,798.66800 |
531
+ ```
532
+
533
+
534
+ <a id="orgb844d6f"></a>
535
+
536
+ ### Methods `#whole?` and `#int_if_whole`
537
+
538
+ At times it is useful to know if a Float or BigDecimal can be converted to an `Integer` without losing precision.
539
+
540
+ ```ruby
541
+ result = []
542
+ result << ['N', '#whole?', '#int_if_whole', 'Classes']
543
+ result << nil
544
+ nums = [3.14159, 3.000000, 100000, 0.0059, 16236565468798.66877]
545
+ nums.each do |n|
546
+ result << [n, n.whole?, n.int_if_whole, "#{n.class} -> #{n.int_if_whole.class}"]
547
+ end
548
+ result
549
+ ```
550
+
551
+ ```
552
+ | N | #whole? | #int_if_whole | Classes |
553
+ |--------------------+---------+--------------------+--------------------|
554
+ | 3.14159 | false | 3.14159 | Float -> Float |
555
+ | 3.0 | true | 3 | Float -> Integer |
556
+ | 100000 | true | 100000 | Integer -> Integer |
557
+ | 0.0059 | false | 0.0059 | Float -> Float |
558
+ | 16236565468798.668 | false | 16236565468798.668 | Float -> Float |
559
+ ```
560
+
561
+
562
+ <a id="orgfd1b851"></a>
563
+
564
+ ### Method `#secs_to_hms`
565
+
566
+ This method converts a numeric representing a number of seconds or an angle in degrees to a `String` of the form "HH:MM:SS" representing the same quantity in hours (or degrees), minutes, and seconds.
567
+
568
+ ```ruby
569
+ result = []
570
+ result << ['N', 'HH:MM:SS']
571
+ result << nil
572
+ nums = [85777.66, 959.66, -1198.33, 0, 3.14159 * 180]
573
+ nums.each do |n|
574
+ result << [n, n.secs_to_hms]
575
+ end
576
+ result
577
+ ```
578
+
579
+ ```
580
+ | N | HH:MM:SS |
581
+ |-------------------+-------------|
582
+ | 85777.66 | 23:49:37.66 |
583
+ | 959.66 | 00:15:59.66 |
584
+ | -1198.33 | -1:40:01.67 |
585
+ | 0 | 00:00:00 |
586
+ | 565.4861999999999 | 00:09:25.48 |
587
+ ```
588
+
589
+
590
+ <a id="org7a70260"></a>
591
+
592
+ ## Range
593
+
594
+ `FatCore` can also extend the Range class with several useful methods that emphasize coverage of one range by one or more others (`#spanned_by?` and `#gaps`), contiguity of Ranges to one another (`#contiguous?`, `#left_contiguous?`, and `#right_contiguous?`, `#join`), and the testing of overlaps between ranges (`#overlaps?`, `#overlaps_among?`). These are put to good use in the 'fat\_period' (<https://github.com/ddoherty03/fat_period>) gem, which combines fat\_core's extended Range class with its extended Date class to make a useful Period class for date ranges, and you may find fat\_core's extended Range class likewise useful.
595
+
596
+
597
+ <a id="orgdd06e2c"></a>
598
+
599
+ ### Methods `#contiguous`, `#left_contiguous`, `#right_contiguous`
600
+
601
+ These methods determine whether the subject `Range` are "contiguous" with another `Range` on the left, right, or either side. The notion of contiguity is different for `Ranges` whose min and max values respond to the `#succ` method: if they do, "contiguity" only requires that the `#succ` of the max value of the left range equal the min value of the right `Range`; otherwise the max value of the left `Range` must equal the min value of the right `Range`.
602
+
603
+ ```ruby
604
+ require 'date'
605
+
606
+ result = []
607
+ result << ["Self", "Other", "Contiguous?", "Right?", "Left?"]
608
+ result << nil
609
+ pairs = [
610
+ [(0..10), (11..12)],
611
+ [(11..20), (0..10)],
612
+ [(0..10), (15..20)],
613
+ [(3.145..12.3), (0.5..3.145)],
614
+ [(3.146..12.3), (0.5..3.145)],
615
+ [('a'..'q'), ('r'..'z')],
616
+ [('a'..'q'), ('s'..'z')],
617
+ [(Date.parse('1963-11-22')..Date.parse('1964-11-03')), (Date.parse('1964-11-04')..Date.today)],
618
+ [(Date.parse('1963-11-22')..Date.parse('1964-11-03')), (Date.parse('1964-11-28')..Date.today)]
619
+ ]
620
+ pairs.each do |r1, r2|
621
+ result << [r1.to_s, r2.to_s, r1.contiguous?(r2), r1.right_contiguous?(r2), r1.left_contiguous?(r2)]
622
+ end
623
+ result
624
+ ```
625
+
626
+ ```
627
+ | Self | Other | Contiguous? | Right? | Left? |
628
+ |------------------------+------------------------+-------------+--------+-------|
629
+ | 0..10 | 11..12 | true | true | false |
630
+ | 11..20 | 0..10 | true | false | true |
631
+ | 0..10 | 15..20 | false | false | false |
632
+ | 3.145..12.3 | 0.5..3.145 | true | false | true |
633
+ | 3.146..12.3 | 0.5..3.145 | false | false | false |
634
+ | a..q | r..z | true | true | false |
635
+ | a..q | s..z | false | false | false |
636
+ | 1963-11-22..1964-11-03 | 1964-11-04..2026-05-29 | true | true | false |
637
+ | 1963-11-22..1964-11-03 | 1964-11-28..2026-05-29 | false | false | false |
638
+ ```
639
+
640
+
641
+ <a id="org28a7d95"></a>
642
+
643
+ ### Method `#join(other)`
644
+
645
+ If `self` is contiguous with `other`, return a new `Range` that splices the two `Range~s into one ~Range`.
646
+
647
+ ```ruby
648
+ require 'date'
649
+
650
+ result = []
651
+ result << ["Self", "Other", "Contiguous?", "Joined"]
652
+ result << nil
653
+ pairs = [
654
+ [(0..10), (11..12)],
655
+ [(11..20), (0..10)],
656
+ [(0..10), (15..20)],
657
+ [(3.145..12.3), (0.5..3.145)],
658
+ [(3.146..12.3), (0.5..3.145)],
659
+ [('a'..'q'), ('r'..'z')],
660
+ [('a'..'q'), ('s'..'z')],
661
+ [(Date.parse('1963-11-22')..Date.parse('1964-11-03')), (Date.parse('1964-11-04')..Date.today)],
662
+ [(Date.parse('1963-11-22')..Date.parse('1964-11-03')), (Date.parse('1964-11-28')..Date.today)]
663
+ ]
664
+ pairs.each do |r1, r2|
665
+ result << [r1.to_s, r2.to_s, r1.contiguous?(r2), "#{r1.join(r2)}"]
666
+ end
667
+ result
668
+ ```
669
+
670
+ ```
671
+ | Self | Other | Contiguous? | Joined |
672
+ |------------------------+------------------------+-------------+------------------------|
673
+ | 0..10 | 11..12 | true | 0..12 |
674
+ | 11..20 | 0..10 | true | 0..20 |
675
+ | 0..10 | 15..20 | false | |
676
+ | 3.145..12.3 | 0.5..3.145 | true | 0.5..12.3 |
677
+ | 3.146..12.3 | 0.5..3.145 | false | |
678
+ | a..q | r..z | true | a..z |
679
+ | a..q | s..z | false | |
680
+ | 1963-11-22..1964-11-03 | 1964-11-04..2026-05-29 | true | 1963-11-22..2026-05-29 |
681
+ | 1963-11-22..1964-11-03 | 1964-11-28..2026-05-29 | false | |
682
+ ```
683
+
684
+
685
+ <a id="org5d367a6"></a>
686
+
687
+ ### Method `#spanned_by?(others)`
688
+
689
+ A set of `Ranges` "spans" a given `Range` if the set is contiguous and fully covers the given `Range` with no overlaps and no gaps. A set that over-covers the given `Range` is still considered to span it, even though it is wider than the given `Range`. In other words, a set spans the given `Range` if the set can be joined and the given `Range` is within the joined `Range`.
690
+
691
+ ```ruby
692
+ require 'date'
693
+
694
+ result = []
695
+ result << ["Self", "Others", "Spanned By?"]
696
+ result << nil
697
+ pairs = [
698
+ [(0..10), [(-1..5), (6..10)]],
699
+ [(1..20), [(0..10), (11..20)]],
700
+ [(1..20), [(0..10), (10..20)]],
701
+ [(3.145..12.3), [(0.5..3.45), (3.45..10.5), (10.5..13.5)]],
702
+ [(3.145..12.3), [(0.5..3.45), (3.45..10.5), (10.6..13.5)]],
703
+ [('a'..'z'), [('a'..'g'), ('h'..'s'), ('t'..'z')]],
704
+ [('a'..'z'), [('a'..'g'), ('j'..'s'), ('t'..'z')]],
705
+ ]
706
+ pairs.each do |r, others|
707
+ result << ["#{r}", "#{others}", r.spanned_by?(others)]
708
+ end
709
+ result
710
+ ```
711
+
712
+ ```
713
+ | Self | Others | Spanned By? |
714
+ |-------------+-------------------------------------+-------------|
715
+ | 0..10 | [-1..5, 6..10] | true |
716
+ | 1..20 | [0..10, 11..20] | true |
717
+ | 1..20 | [0..10, 10..20] | false |
718
+ | 3.145..12.3 | [0.5..3.45, 3.45..10.5, 10.5..13.5] | true |
719
+ | 3.145..12.3 | [0.5..3.45, 3.45..10.5, 10.6..13.5] | false |
720
+ | a..z | ["a".."g", "h".."s", "t".."z"] | true |
721
+ | a..z | ["a".."g", "j".."s", "t".."z"] | false |
722
+ ```
723
+
724
+
725
+ <a id="orga33fd47"></a>
726
+
727
+ ### Methods `#gaps(others)`, `#overlaps(others)`
728
+
729
+ When the set of other `Ranges` does not span the given `Range`, these methods return an set of `Ranges` that represent the portions of the given `Range` no covered by the `others`, the "gaps", or the points within the given `Range` where the `others` overlap one another and thus are not contiguous.
730
+
731
+ ```ruby
732
+ require 'date'
733
+
734
+ result = []
735
+ result << ["Self", "Others", "Spanned By?", "Gaps", "Overlaps"]
736
+ result << nil
737
+ pairs = [
738
+ [(0..10), [(-1..5), (6..10)]],
739
+ [(1..20), [(0..10), (11..20)]],
740
+ [(1..20), [(0..15), (11..20)]],
741
+ [(1..20), [(0..10), (10..20)]],
742
+ [(3.145..12.3), [(0.5..3.45), (3.45..10.5), (10.5..13.5)]],
743
+ [(3.145..12.3), [(0.5..3.45), (3.45..10.5), (10.6..13.5)]],
744
+ [('a'..'z'), [('a'..'g'), ('h'..'s'), ('t'..'z')]],
745
+ [('a'..'z'), [('a'..'g'), ('j'..'s'), ('t'..'z')]],
746
+ ]
747
+ pairs.each do |r, others|
748
+ result << ["#{r}", "#{others}", r.spanned_by?(others), "#{r.gaps(others)}", "#{r.overlaps(others)}"]
749
+ end
750
+ result
751
+ ```
752
+
753
+ ```
754
+ | Self | Others | Spanned By? | Gaps | Overlaps |
755
+ |-------------+-------------------------------------+-------------+--------------+----------|
756
+ | 0..10 | [-1..5, 6..10] | true | [] | [] |
757
+ | 1..20 | [0..10, 11..20] | true | [] | [] |
758
+ | 1..20 | [0..15, 11..20] | false | [] | [11..15] |
759
+ | 1..20 | [0..10, 10..20] | false | [] | [] |
760
+ | 3.145..12.3 | [0.5..3.45, 3.45..10.5, 10.5..13.5] | true | [] | [] |
761
+ | 3.145..12.3 | [0.5..3.45, 3.45..10.5, 10.6..13.5] | false | [10.5..10.6] | [] |
762
+ | a..z | ["a".."g", "h".."s", "t".."z"] | true | [] | [] |
763
+ | a..z | ["a".."g", "j".."s", "t".."z"] | false | ["h".."i"] | [] |
764
+ ```
765
+
766
+
767
+ <a id="orgbd1bd5e"></a>
768
+
769
+ ## String
770
+
771
+ FatCore::String has methods for performing matching of one string with another (`#matches_with`, `#fuzzy_match`), for converting a string to title-case as might by used in the title of a book (`#entitle`), for converting a String into a useable Symbol (`#as_sym`) and vice-versa (`#as_str` also `Symbol#as_str`), for wrapping with an optional hanging indent (`#wrap`), cleaning up errant spaces (`#clean`), and computing the Damerau-Levenshtein distance between strings (`#distance`). And several others.
772
+
773
+
774
+ <a id="org63111cb"></a>
775
+
776
+ ### Method `#fuzzy_match`
777
+
778
+ The `#fuzzy_match` method determines whether the subject string matches the given "matcher" string, which provides a simple syntax that allows a limited kind of pattern matching. If there is a match, it returns the matched portion of self, minus punctuation characters, if self matches the string, and returns nil otherwise.
779
+
780
+ What makes this handy is that a user trying to match by memory can be loose about case, punctuation, and spaces, and still find desired matches. In the matcher both the space and colon ':' have special meaning as shown below.
781
+
782
+ `#fuzzy_match(matcher)` uses the following rules for matching:
783
+
784
+ 1. Remove leading and trailing whitespace in the subject and the matcher and collapse its internal whitespace to a single space,
785
+ 2. In the subject string replace periods and commas with a space (so they still act as word separators) but remove apostrophes, and asterisks so the user need not remember whether they were used when forming the matcher.
786
+ 3. In the matcher, make any period, comma, asterisk, or apostrophe optional for the same reason.
787
+ 4. Treat internal ':stuff' or ' :stuff' in the matcher as the equivalent of *\bstuff.\** in a regular expression, that is, match any word starting with stuff in self,
788
+ 5. Treat internal 'stuff: ' in the matcher as the equivalent of *.\*stuff\b* in a regular expression, that is, match any word ending with stuff in self,
789
+ 6. A colon with no spaces around it is treated as belonging to the following word, requiring it to start with it, so 'some:stuff' requires 'some' anywhere followed by a word beginning with 'stuff', i.e., /some.\*\bstuff/i,
790
+ 7. Treat leading ':' in the matcher as anchoring the match to the beginning of the target string,
791
+ 8. Treat ending ':' in the matcher as anchoring the match to the end of the target string,
792
+ 9. Require each component to match some part of self, and
793
+
794
+ ```ruby
795
+ result = []
796
+ result << ['Self', 'Matcher', 'Match']
797
+ result << nil
798
+ subj = "St. Luke's Hospital"
799
+ matchers = ['st lukes', 'st. luke\'s', 'luk:hosp', 'st:spital', 'uk spital', 'st:laks', ':lukes', 's lukes', 'lukes:hospital']
800
+ matchers.each do |m|
801
+ result << [subj, m, subj.fuzzy_match(m)]
802
+ end
803
+ result
804
+ ```
805
+
806
+ ```
807
+ | Self | Matcher | Match |
808
+ |---------------------+----------------+----------------|
809
+ | St. Luke's Hospital | st lukes | St Lukes |
810
+ | St. Luke's Hospital | st. luke's | St Lukes |
811
+ | St. Luke's Hospital | luk:hosp | Lukes Hosp |
812
+ | St. Luke's Hospital | st:spital | nil |
813
+ | St. Luke's Hospital | uk spital | ukes Hospital |
814
+ | St. Luke's Hospital | st:laks | nil |
815
+ | St. Luke's Hospital | :lukes | nil |
816
+ | St. Luke's Hospital | s lukes | St Lukes |
817
+ | St. Luke's Hospital | lukes:hospital | Lukes Hospital |
818
+ ```
819
+
820
+
821
+ <a id="orgdae93bf"></a>
822
+
823
+ ### Method `#matches_with`
824
+
825
+ The `#matches_with(matcher)` method allows the use of either a regular expression or fuzzy matching as described above depending on whether the matcher is enclosed in '/' characters. It also returns the matched portion of `self` or nil if there is no match. Even when a regex is given, the match is case insensitive by default and commas, apostrophes, and periods are removed from the subject string before matching.
826
+
827
+ ```ruby
828
+ result = []
829
+ result << ['Self', 'Matcher', 'Match']
830
+ result << nil
831
+ subj = "St. Luke's Hospital"
832
+ matchers = ['st lukes', '/luk.*hosp/', 'st:spital', '/u.*s\b/', 'st:laks', ':lukes', 's lukes', '/lukes hospital\z/']
833
+ matchers.each do |m|
834
+ result << [subj, m, subj.matches_with(m)]
835
+ end
836
+ result
837
+ ```
838
+
839
+ ```
840
+ | Self | Matcher | Match |
841
+ |---------------------+--------------------+-------------|
842
+ | St. Luke's Hospital | st lukes | St Lukes |
843
+ | St. Luke's Hospital | /luk.*hosp/ | Luke's Hosp |
844
+ | St. Luke's Hospital | st:spital | nil |
845
+ | St. Luke's Hospital | /u.*s\b/ | uke's |
846
+ | St. Luke's Hospital | st:laks | nil |
847
+ | St. Luke's Hospital | :lukes | nil |
848
+ | St. Luke's Hospital | s lukes | St Lukes |
849
+ | St. Luke's Hospital | /lukes hospital\z/ | nil |
850
+ ```
851
+
852
+
853
+ <a id="org1a5d1e4"></a>
854
+
855
+ ### Method `#entitle`
856
+
857
+ For a string meant to serve as the title of a book, song, or other item, there are certain rules in English as to which words should be capitalized and which should be put in lower case. "PROFILES IN courage" should be rendered "Profiles in Courage" for example. The preposition "in" is typically not capitalized unless it starts the title: "in the HEAT OF THE NIght" should be something like "In the Heat of the Night".
858
+
859
+ ```ruby
860
+ result = []
861
+ result << ['Self', 'Entitled']
862
+ result << nil
863
+ titles = ['PROFILES IN courage', 'in the HEAT OF THE NIght', 'a day in the life', 'FROM HERE TO ETERNITY',
864
+ 'lucy in the sky with diamonds']
865
+ titles.each do |t|
866
+ result << [t, t.entitle]
867
+ end
868
+ result
869
+ ```
870
+
871
+ ```
872
+ | Self | Entitled |
873
+ |-------------------------------+-------------------------------|
874
+ | PROFILES IN courage | Profiles in Courage |
875
+ | in the HEAT OF THE NIght | In the Heat of the Night |
876
+ | a day in the life | A Day in the Life |
877
+ | FROM HERE TO ETERNITY | From Here to Eternity |
878
+ | lucy in the sky with diamonds | Lucy in the Sky With Diamonds |
879
+ ```
880
+
881
+
882
+ <a id="orgd671ee5"></a>
883
+
884
+ ### Method `#distance`
885
+
886
+ `FatCore` provides `distance` as a simple wrapper around the Damerau-Levenshtein distance function in `damerau-levenshtein` gem, using a block size of 1 and a max distance of 10.
887
+
888
+ ```ruby
889
+ result = []
890
+ result << ['Word1', 'Word2', 'Distance']
891
+ result << nil
892
+ pairs = [['Shelf', 'Shell'], ['Shelf', 'Shall'], ['Doherty', 'Daughtery'], ['Doherty', 'Dorrit'], ['Smith', 'Jones']]
893
+ pairs.each do |w1, w2|
894
+ result << [w1, w2, w1.distance(w2)]
895
+ end
896
+ result
897
+ ```
898
+
899
+ ```
900
+ | Word1 | Word2 | Distance |
901
+ |---------+-----------+----------|
902
+ | Shelf | Shell | 1 |
903
+ | Shelf | Shall | 2 |
904
+ | Doherty | Daughtery | 5 |
905
+ | Doherty | Dorrit | 4 |
906
+ | Smith | Jones | 5 |
907
+ ```
908
+
909
+
910
+ <a id="orgfdd51bd"></a>
911
+
912
+ ### Method `#commas(places)`
913
+
914
+ When presenting numbers, it is common to want to add grouping digits to make the numbers more readable. The `commas(places)` method does this be converting the number into a Float, rounding to places digits, then converting back to a `String` with grouping commas inserted.
915
+
916
+ ```ruby
917
+ result = []
918
+ result << ['N', 'Places', 'With Commas']
919
+ result << nil
920
+ nums_places = [["798964655.66541325", 3], ["798964655.66541325", 0], ["798964655.66541325", 5], ["3.14159", 3],
921
+ ["3.14159e6", 3], ["-3.14159e4", 2], ["+3.14159e3", 2]]
922
+ nums_places.each do |n, p|
923
+ result << [n, p, n.commas(p)]
924
+ end
925
+ result
926
+ ```
927
+
928
+ ```
929
+ | N | Places | With Commas |
930
+ |--------------------+--------+-------------------|
931
+ | 798964655.66541325 | 3 | 798,964,655.665 |
932
+ | 798964655.66541325 | 0 | 798,964,656 |
933
+ | 798964655.66541325 | 5 | 798,964,655.66541 |
934
+ | 3.14159 | 3 | 3.142 |
935
+ | 3.14159e6 | 3 | 3,141,590.000 |
936
+ | -3.14159e4 | 2 | -31,415.90 |
937
+ | +3.14159e3 | 2 | 3,141.59 |
938
+ ```
939
+
940
+
941
+ <a id="org826950e"></a>
942
+
943
+ ### Method `#wrap(width, hang)`
944
+
945
+ This method wraps the string to a given width with an optional hanging indent for lines after the first.
946
+
947
+ ```ruby
948
+ getty = <<~EOS
949
+ Four score and seven years ago our fathers brought forth on this continent,
950
+ a new nation, conceived in Liberty, and dedicated to the proposition that
951
+ all men are created equal.
952
+
953
+ Now we are engaged in a great civil war, testing whether that nation, or any
954
+ nation so conceived and so dedicated, can long endure. We are met on a
955
+ great battle-field of that war. We have come to dedicate a portion of that
956
+ field, as a final resting place for those who here gave their lives that
957
+ that nation might live. It is altogether fitting and proper that we should
958
+ do this.
959
+
960
+ But, in a larger sense, we can not dedicate---we can not consecrate---we can
961
+ not hallow---this ground. The brave men, living and dead, who struggled
962
+ here, have consecrated it, far above our poor power to add or detract. The
963
+ world will little note, nor long remember what we say here, but it can never
964
+ forget what they did here. It is for us the living, rather, to be dedicated
965
+ here to the unfinished work which they who fought here have thus far so
966
+ nobly advanced. It is rather for us to be here dedicated to the great task
967
+ remaining before us---that from these honored dead we take increased
968
+ devotion to that cause for which they gave the last full measure of
969
+ devotion---that we here highly resolve that these dead shall not have died
970
+ in vain---that this nation, under God, shall have a new birth of
971
+ freedom---and that government of the people, by the people, for the people,
972
+ shall not perish from the earth.
973
+ EOS
974
+ getty.wrap(110, 3)
975
+ ```
976
+
977
+ ```
978
+ Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived
979
+ in Liberty, and dedicated to the proposition that all men are created equal. Now we are engaged
980
+ in a great civil war, testing whether that nation, or any nation so conceived and so dedicated,
981
+ can long endure. We are met on a great battle-field of that war. We have come to dedicate
982
+ a portion of that field, as a final resting place for those who here gave their lives that
983
+ that nation might live. It is altogether fitting and proper that we should do this. But, in
984
+ a larger sense, we can not dedicate---we can not consecrate---we can not hallow---this ground.
985
+ The brave men, living and dead, who struggled here, have consecrated it, far above our poor
986
+ power to add or detract. The world will little note, nor long remember what we say here, but
987
+ it can never forget what they did here. It is for us the living, rather, to be dedicated here
988
+ to the unfinished work which they who fought here have thus far so nobly advanced. It is rather
989
+ for us to be here dedicated to the great task remaining before us---that from these honored
990
+ dead we take increased devotion to that cause for which they gave the last full measure of
991
+ devotion---that we here highly resolve that these dead shall not have died in vain---that this
992
+ nation, under God, shall have a new birth of freedom---and that government of the people, by
993
+ the people, for the people, shall not perish from the earth.
994
+ ```
995
+
996
+ ```ruby
997
+ getty.wrap(40, 2)
998
+ ```
999
+
1000
+ ```
1001
+ Four score and seven years ago our
1002
+ fathers brought forth on this continent,
1003
+ a new nation, conceived in Liberty,
1004
+ and dedicated to the proposition that
1005
+ all men are created equal. Now we
1006
+ are engaged in a great civil war,
1007
+ testing whether that nation, or any
1008
+ nation so conceived and so dedicated,
1009
+ can long endure. We are met on a
1010
+ great battle-field of that war. We
1011
+ have come to dedicate a portion of
1012
+ that field, as a final resting place
1013
+ for those who here gave their lives
1014
+ that that nation might live. It is
1015
+ altogether fitting and proper that
1016
+ we should do this. But, in a larger
1017
+ sense, we can not dedicate---we can
1018
+ not consecrate---we can not hallow---this
1019
+ ground. The brave men, living and
1020
+ dead, who struggled here, have consecrated
1021
+ it, far above our poor power to
1022
+ add or detract. The world will little
1023
+ note, nor long remember what we say
1024
+ here, but it can never forget what
1025
+ they did here. It is for us the
1026
+ living, rather, to be dedicated here
1027
+ to the unfinished work which they
1028
+ who fought here have thus far so
1029
+ nobly advanced. It is rather for
1030
+ us to be here dedicated to the great
1031
+ task remaining before us---that from
1032
+ these honored dead we take increased
1033
+ devotion to that cause for which
1034
+ they gave the last full measure of
1035
+ devotion---that we here highly resolve
1036
+ that these dead shall not have died
1037
+ in vain---that this nation, under
1038
+ God, shall have a new birth of freedom---and
1039
+ that government of the people, by
1040
+ the people, for the people, shall
1041
+ not perish from the earth.
1042
+ ```
1043
+
1044
+
1045
+ <a id="orgc017d90"></a>
1046
+
1047
+ ### Method `#as_sym`
1048
+
1049
+ Convert a `String` to a `Symbol` by converting all letters to lower-case, replacing hyphens and white space with a single underscore, and removing all non-alphanumeric characters:
1050
+
1051
+ ```ruby
1052
+ " Hello-to-the World!!!".as_sym
1053
+ ```
1054
+
1055
+ ```
1056
+ :hello_to_the_world
1057
+ ```
1058
+
1059
+
1060
+ <a id="org3459d99"></a>
1061
+
1062
+ ### Method `gut`
1063
+
1064
+ Very often one wants to truncate a string to a given size, but it is often the case that the most important parts of a string are at the beginning and the end. The `#gut(size)` method returns a sting of length `size` by removing content from the middle of the string and leaving as much as possible at the two ends.
1065
+
1066
+ ```ruby
1067
+ result = []
1068
+ result << ['Self', 'Gutted']
1069
+ result << nil
1070
+ strings = ["/usr/bin/fallacious", "Class A Common Stock", 'PROFILES IN courage', 'in the HEAT OF THE NIght', 'a day in the life', 'FROM HERE TO ETERNITY',
1071
+ 'lucy in the sky with diamonds']
1072
+ strings.each do |t|
1073
+ result << [t, t.gut(15)]
1074
+ end
1075
+ result
1076
+ ```
1077
+
1078
+ ```
1079
+ | Self | Gutted |
1080
+ |-------------------------------+-----------------|
1081
+ | /usr/bin/fallacious | /usr/bi~lacious |
1082
+ | Class A Common Stock | Class A~n Stock |
1083
+ | PROFILES IN courage | PROFILE~courage |
1084
+ | in the HEAT OF THE NIght | in the ~E NIght |
1085
+ | a day in the life | a day i~he life |
1086
+ | FROM HERE TO ETERNITY | FROM HE~TERNITY |
1087
+ | lucy in the sky with diamonds | lucy in~iamonds |
1088
+ ```
1089
+
1090
+ By default, the deleted middle part is replace with the tilde character, but with the ellipsis parameter, you can make it whatever you want:
1091
+
1092
+ ```ruby
1093
+ 'Class A Common Stock'.gut(15, ellipsis: '...')
1094
+ ```
1095
+
1096
+ ```
1097
+ Class ... Stock
1098
+ ```
1099
+
1100
+ Including, nothing at all:
1101
+
1102
+ ```ruby
1103
+ 'Class A Common Stock'.gut(15, ellipsis: '')
1104
+ ```
1105
+
1106
+ ```
1107
+ Class A n Stock
1108
+ ```
1109
+
1110
+ And, you can optionally squeeze out spaces or other characters with the
1111
+
1112
+ ```ruby
1113
+ 'Class A Common Stock'.gut(16, ellipsis: '', squeeze: ' ')
1114
+ ```
1115
+
1116
+ ```
1117
+ ClassAComonStock
1118
+ ```
1119
+
1120
+
1121
+ <a id="org2241c53"></a>
1122
+
1123
+ ## Symbol
1124
+
1125
+
1126
+ <a id="orgf2478cc"></a>
1127
+
1128
+ ### Method `#as_str`
1129
+
1130
+ A quasi-inverse of `String#as_sym`, convert a `Symbol` into a `String` by converting '<span class="underline">' to a hyphen, white-space into '</span>', and eliminate any non-alphanumeric characters.
1131
+
1132
+ ```ruby
1133
+ :hello_to_the_world.as_str
1134
+ ```
1135
+
1136
+ ```
1137
+ hello-to-the-world
1138
+ ```
1139
+
1140
+
1141
+ <a id="org5620bc3"></a>
1142
+
1143
+ ## TeX Quoting
1144
+
1145
+ The extensions for `String`, `Numeric`, `Range`, `Symbol`, and `NilClass` provide a `#tex_quote` method for quoting the string version of an object so as to allow its inclusion in a TeX document while quoting characters such as '\_', $' or '%' that have a special meaning for TeX. At the same time it deploys TeX notation when special notation is available, for example, a `Rational` is rendered as a fraction.
1146
+
1147
+ ```ruby
1148
+ require 'date'
1149
+
1150
+ result = []
1151
+ result << ['Class', 'Example', '#tex_quote']
1152
+ result << nil
1153
+ examples = [
1154
+ "Save $100 or 14% on this Friday_Black",
1155
+ 58743.44,
1156
+ Float::INFINITY,
1157
+ Math::PI,
1158
+ Complex(5, 3),
1159
+ Complex(5.0, 3.0),
1160
+ Rational(5, 3),
1161
+ Rational(8.0, 17.0),
1162
+ (Date.parse('2020-09-22')..Date.today),
1163
+ (Math::E..Math::PI),
1164
+ :four_score_and_7_years,
1165
+ nil
1166
+ ]
1167
+ examples.each do |ex|
1168
+ result << [ex.class, ex.to_s, ex.tex_quote.inspect]
1169
+ end
1170
+ result
1171
+ ```
1172
+
1173
+ ```
1174
+ | Class | Example | #tex_quote |
1175
+ |----------+---------------------------------------+-----------------------------------------------|
1176
+ | String | Save $100 or 14% on this Friday_Black | "Save \\$100 or 14\\% on this Friday\\_Black" |
1177
+ | Float | 58743.44 | "58743.44" |
1178
+ | Float | Infinity | "$\\infty$" |
1179
+ | Float | 3.141592653589793 | "$\\pi$" |
1180
+ | Complex | 5+3i | "$5+3i$" |
1181
+ | Complex | 5.0+3.0i | "$5+3i$" |
1182
+ | Rational | 5/3 | "$\\frac{5}{3}$" |
1183
+ | Rational | 8/17 | "$\\frac{8}{17}$" |
1184
+ | Range | 2020-09-22..2026-05-29 | "(2020-09-22..2026-05-29)" |
1185
+ | Range | 2.718281828459045..3.141592653589793 | "($e$..$\\pi$)" |
1186
+ | Symbol | four_score_and_7_years | "four\\_score\\_and\\_7\\_years" |
1187
+ | NilClass | | "" |
1188
+ ```
1189
+
1190
+
1191
+ <a id="orgfe2e72b"></a>
1192
+
1193
+ # Contributing
1194
+
1195
+ 1. Fork it (<http://github.com/ddoherty03/fat_core/fork> )
1196
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
1197
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
1198
+ 4. Push to the branch (`git push origin my-new-feature`)
1199
+ 5. Create new Pull Request