lx 1.0 → 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.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/lib/lx.rb +351 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0129287631d7874f63195026285a321e29b8beb2ed2959a02d6ed59a7edda3ba'
|
4
|
+
data.tar.gz: 3b2ce691ff835795825aae039084bfa68a908b275028d3d4ec5a58b37d26c16b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5b6723a4103a00ba8769c6a60d696481d3048e5359b7448ab3afa5d35d5ded07f6d271b214a67eead90ce9c62718245b48d851b4f49d47a31ead16175bf1bcc
|
7
|
+
data.tar.gz: e06b0f7724126c604993825f5640f5fcd18cbbbf7526282a17f745e82a912c68602f052f4d3aca2d8998ef62538e1b416830b73e5a6540f1ceb17857adcc4ca5
|
data/README.md
CHANGED
@@ -25,10 +25,11 @@ mike@idocs.com
|
|
25
25
|
## Name
|
26
26
|
|
27
27
|
"LX" doesn't mean anything in particular. It's concise and it was available on
|
28
|
-
rubygems.
|
28
|
+
rubygems.
|
29
29
|
|
30
30
|
## History
|
31
31
|
|
32
32
|
| version | date | notes |
|
33
33
|
|---------|--------------|-------------------------------|
|
34
|
-
| 1.0 | May 29, 2020 | Initial upload. |
|
34
|
+
| 1.0 | May 29, 2020 | Initial upload. |
|
35
|
+
| 1.1 | January 3, 2021 | Added deep_dup for arrays and hashes, LX.randstr, File.lx.atomic_write(), and File.lx.temp_path. |
|
data/lib/lx.rb
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
# The LX module is the home for utilities that don't particularly fit in one
|
6
6
|
# class. For now, it only contains the randstr method.
|
7
7
|
module LX
|
8
|
-
# version
|
9
|
-
VERSION = '1.
|
8
|
+
# version
|
9
|
+
VERSION = '1.1'
|
10
10
|
|
11
11
|
#---------------------------------------------------------------------------
|
12
12
|
# verbose
|
@@ -62,6 +62,109 @@ module LX
|
|
62
62
|
#
|
63
63
|
# randstr
|
64
64
|
#---------------------------------------------------------------------------
|
65
|
+
|
66
|
+
|
67
|
+
#---------------------------------------------------------------------------
|
68
|
+
# scope
|
69
|
+
#
|
70
|
+
|
71
|
+
# A little method that does nothing more than allow you to create a 'do'
|
72
|
+
# block.
|
73
|
+
def self.scope
|
74
|
+
yield
|
75
|
+
end
|
76
|
+
|
77
|
+
# Same as LX::scope.
|
78
|
+
def self.block
|
79
|
+
yield
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# scope
|
84
|
+
#---------------------------------------------------------------------------
|
85
|
+
|
86
|
+
|
87
|
+
#---------------------------------------------------------------------------
|
88
|
+
# deep_dup
|
89
|
+
#
|
90
|
+
|
91
|
+
# Deep suplicates a hash or array. Don't call this method directly. Call
|
92
|
+
# Array#lx#deep_dup or Hash#lx#deep_dup.
|
93
|
+
|
94
|
+
def self.deep_dup(obj, opts={})
|
95
|
+
# $tm.hrm
|
96
|
+
rv = nil
|
97
|
+
|
98
|
+
# default options
|
99
|
+
opts = {'done'=>{}}.merge(opts)
|
100
|
+
|
101
|
+
# error if object has already been cloned
|
102
|
+
if obj.is_a?(::Array) or obj.is_a?(::Hash)
|
103
|
+
if opts['done'][obj.object_id]
|
104
|
+
raise "object #{obj.object_id} has already been dupped"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
if obj.is_a?(::Array)
|
109
|
+
rv = deep_dup_array(obj, opts)
|
110
|
+
elsif obj.is_a?(::Hash)
|
111
|
+
rv = deep_dup_hash(obj, opts)
|
112
|
+
else
|
113
|
+
begin
|
114
|
+
rv = obj.dup
|
115
|
+
rescue
|
116
|
+
rv = obj
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# note object as done
|
121
|
+
opts['done'][obj.object_id] = true
|
122
|
+
|
123
|
+
# return rv
|
124
|
+
return rv
|
125
|
+
end
|
126
|
+
#
|
127
|
+
# deep_dup
|
128
|
+
#---------------------------------------------------------------------------
|
129
|
+
|
130
|
+
|
131
|
+
#---------------------------------------------------------------------------
|
132
|
+
# deep_dup_hash
|
133
|
+
#
|
134
|
+
def self.deep_dup_hash(hsh, opts)
|
135
|
+
# $tm.hrm
|
136
|
+
rv = {}
|
137
|
+
|
138
|
+
hsh.each do |key, val|
|
139
|
+
rv[key.dup] = self.deep_dup(val, opts)
|
140
|
+
end
|
141
|
+
|
142
|
+
return rv
|
143
|
+
end
|
144
|
+
|
145
|
+
private_class_method :deep_dup_hash
|
146
|
+
#
|
147
|
+
# deep_dup_hash
|
148
|
+
#---------------------------------------------------------------------------
|
149
|
+
|
150
|
+
|
151
|
+
#---------------------------------------------------------------------------
|
152
|
+
# deep_dup_array
|
153
|
+
#
|
154
|
+
def self.deep_dup_array(arr, opts)
|
155
|
+
rv = []
|
156
|
+
|
157
|
+
arr.each do |val|
|
158
|
+
rv.push self.deep_dup(val, opts)
|
159
|
+
end
|
160
|
+
|
161
|
+
return rv
|
162
|
+
end
|
163
|
+
|
164
|
+
private_class_method :deep_dup_array
|
165
|
+
#
|
166
|
+
# deep_dup_array
|
167
|
+
#---------------------------------------------------------------------------
|
65
168
|
end
|
66
169
|
#
|
67
170
|
# LX
|
@@ -89,7 +192,7 @@ end
|
|
89
192
|
# A helper class to add methods to the Array class. When you use the Array::lx
|
90
193
|
# you're creating an instance of LX::Array.
|
91
194
|
class LX::Array
|
92
|
-
#
|
195
|
+
# initialize a LX::Array object. The only param is the array itself.
|
93
196
|
def initialize(p_arr)
|
94
197
|
@arr = p_arr
|
95
198
|
end
|
@@ -130,12 +233,59 @@ class LX::Array
|
|
130
233
|
# return
|
131
234
|
return rv
|
132
235
|
end
|
236
|
+
|
237
|
+
# draw
|
238
|
+
def draw
|
239
|
+
rv = @arr[0]
|
240
|
+
@arr.rotate!
|
241
|
+
return rv
|
242
|
+
end
|
243
|
+
|
244
|
+
# deep_dup
|
245
|
+
def deep_dup
|
246
|
+
return LX.deep_dup(@arr)
|
247
|
+
end
|
133
248
|
end
|
134
249
|
#
|
135
250
|
# Array
|
136
251
|
#===============================================================================
|
137
252
|
|
138
253
|
|
254
|
+
#===============================================================================
|
255
|
+
# Hash
|
256
|
+
#
|
257
|
+
|
258
|
+
# Adds a single method to the Hash class. This is the only method that is
|
259
|
+
# added to the Hash class itself. Access LX utilities through the array's new
|
260
|
+
# +lx+ method.
|
261
|
+
#
|
262
|
+
# For example, the use the move method, call the method like this:
|
263
|
+
# hsh = {'a'=>1, 'b'=>2, 'c'=>3}
|
264
|
+
class Hash
|
265
|
+
# Creates a LX::Array object and returns it.
|
266
|
+
def lx
|
267
|
+
return LX::Hash.new(self)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# A helper class to add methods to the Hash class. When you use the Hash::lx
|
272
|
+
# you're creating an instance of LX::Hash.
|
273
|
+
class LX::Hash
|
274
|
+
# initialize a LX::Array object. The only param is the array itself.
|
275
|
+
def initialize(p_hsh)
|
276
|
+
@hsh = p_hsh
|
277
|
+
end
|
278
|
+
|
279
|
+
# deep_dup
|
280
|
+
def deep_dup
|
281
|
+
return LX.deep_dup(@hsh)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
#
|
285
|
+
# Hash
|
286
|
+
#===============================================================================
|
287
|
+
|
288
|
+
|
139
289
|
#===============================================================================
|
140
290
|
# String
|
141
291
|
#
|
@@ -191,7 +341,205 @@ class LX::String
|
|
191
341
|
#
|
192
342
|
# collapse
|
193
343
|
#---------------------------------------------------------------------------
|
344
|
+
|
345
|
+
|
346
|
+
#---------------------------------------------------------------------------
|
347
|
+
# inner_collapse
|
348
|
+
#
|
349
|
+
def inner_collapse
|
350
|
+
rv = @str.clone
|
351
|
+
rv.gsub!(/[\u00A0\s]+/imu, ' ')
|
352
|
+
return rv
|
353
|
+
end
|
354
|
+
#
|
355
|
+
# inner_collapse
|
356
|
+
#---------------------------------------------------------------------------
|
357
|
+
|
358
|
+
|
359
|
+
#---------------------------------------------------------------------------
|
360
|
+
# content?, no_content?, nocontent?
|
361
|
+
#
|
362
|
+
|
363
|
+
# Returns true if the string contains a non-whitespace character.
|
364
|
+
def hascontent?
|
365
|
+
return @str.match(/\S/mu) ? true : false
|
366
|
+
end
|
367
|
+
|
368
|
+
# Same as hascontent?
|
369
|
+
def has_content?
|
370
|
+
return hascontent?
|
371
|
+
end
|
372
|
+
|
373
|
+
# Return true if the string does *not* have any non-whitespace characters.
|
374
|
+
def nocontent?
|
375
|
+
return !hascontent?
|
376
|
+
end
|
377
|
+
|
378
|
+
# Same as no_content?
|
379
|
+
def no_content?
|
380
|
+
return nocontent?
|
381
|
+
end
|
382
|
+
|
383
|
+
#
|
384
|
+
# content?, no_content?, nocontent?
|
385
|
+
#---------------------------------------------------------------------------
|
386
|
+
|
387
|
+
|
388
|
+
#---------------------------------------------------------------------------
|
389
|
+
# tmp_untaint
|
390
|
+
#
|
391
|
+
def tmp_untaint(rx)
|
392
|
+
# dangerous
|
393
|
+
if rx == LX::String::Dangerous
|
394
|
+
tmp = @str.dup.untaint
|
395
|
+
else
|
396
|
+
if @str.match(rx)
|
397
|
+
tmp = @str.dup.untaint
|
398
|
+
else
|
399
|
+
raise 'string-does-not-match-untaint-pattern'
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
# yield
|
404
|
+
yield tmp
|
405
|
+
end
|
406
|
+
#
|
407
|
+
# tmp_untaint
|
408
|
+
#---------------------------------------------------------------------------
|
409
|
+
end
|
410
|
+
|
411
|
+
module LX::String::Dangerous
|
194
412
|
end
|
195
413
|
#
|
196
414
|
# String
|
415
|
+
#===============================================================================
|
416
|
+
|
417
|
+
|
418
|
+
#===============================================================================
|
419
|
+
# Integer
|
420
|
+
#
|
421
|
+
class Integer
|
422
|
+
# Creates a LX::Array object and returns it.
|
423
|
+
def lx
|
424
|
+
return LX::Integer.new(self)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
class LX::Integer
|
429
|
+
def initialize(int)
|
430
|
+
@int = int
|
431
|
+
end
|
432
|
+
|
433
|
+
def multiple_of?(number)
|
434
|
+
number != 0 ? @int % number == 0 : @int.zero?
|
435
|
+
end
|
436
|
+
end
|
437
|
+
#
|
438
|
+
# Integer
|
439
|
+
#===============================================================================
|
440
|
+
|
441
|
+
|
442
|
+
#===============================================================================
|
443
|
+
# File
|
444
|
+
#
|
445
|
+
class File
|
446
|
+
def self.lx
|
447
|
+
return LX::File::Class.new(self)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
module LX::File
|
452
|
+
end
|
453
|
+
|
454
|
+
class LX::File::Class
|
455
|
+
def initialize(clss)
|
456
|
+
end
|
457
|
+
|
458
|
+
# Atomically writes content to the given path. Does so by creating a temp
|
459
|
+
# file, writing to it, then renaming the temp file to the final destination.
|
460
|
+
def atomic_write(path_final, content)
|
461
|
+
# $tm.hrm
|
462
|
+
temp_path do |path_tmp|
|
463
|
+
File.write path_tmp, content
|
464
|
+
File.rename path_tmp, path_final
|
465
|
+
end
|
466
|
+
|
467
|
+
# path_tmp = path_final + '.' + rand.to_s.sub(/\A.*\./mu, '')
|
468
|
+
end
|
469
|
+
|
470
|
+
# Creates a temporary path. Does *not* create a file. If, after the `do`
|
471
|
+
# block, a file exists at that path, that file is deleted.
|
472
|
+
def temp_path(opts = {})
|
473
|
+
opts = {'delete'=>true}.merge(opts)
|
474
|
+
|
475
|
+
# root
|
476
|
+
if opts['root']
|
477
|
+
root = opts['root'].sub(/\/*\z/mu, '/')
|
478
|
+
else
|
479
|
+
root = './'
|
480
|
+
end
|
481
|
+
|
482
|
+
# full path
|
483
|
+
path = root + LX.randstr
|
484
|
+
|
485
|
+
# add extension
|
486
|
+
if opts['ext']
|
487
|
+
ext = opts['ext']
|
488
|
+
ext = ext.sub(/\A\.*/mu, '.')
|
489
|
+
path += ext
|
490
|
+
end
|
491
|
+
|
492
|
+
if block_given?
|
493
|
+
begin
|
494
|
+
yield path
|
495
|
+
ensure
|
496
|
+
if opts['delete'] and File.exist?(path)
|
497
|
+
File.delete path
|
498
|
+
end
|
499
|
+
end
|
500
|
+
else
|
501
|
+
return path
|
502
|
+
end
|
503
|
+
end
|
504
|
+
end
|
505
|
+
#
|
506
|
+
# File
|
507
|
+
#===============================================================================
|
508
|
+
|
509
|
+
|
510
|
+
#===============================================================================
|
511
|
+
# NilClass
|
512
|
+
#
|
513
|
+
class NilClass
|
514
|
+
def lx
|
515
|
+
return LX::NilClass.new(self)
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
class LX::NilClass
|
520
|
+
def initialize(obj)
|
521
|
+
end
|
522
|
+
|
523
|
+
# Always returns false.
|
524
|
+
def hascontent?
|
525
|
+
return false
|
526
|
+
end
|
527
|
+
|
528
|
+
# Always returns false.
|
529
|
+
def has_content?
|
530
|
+
return false
|
531
|
+
end
|
532
|
+
|
533
|
+
# Always returns true.
|
534
|
+
def nocontent?
|
535
|
+
return true
|
536
|
+
end
|
537
|
+
|
538
|
+
# Always returns true.
|
539
|
+
def no_content?
|
540
|
+
return true
|
541
|
+
end
|
542
|
+
end
|
543
|
+
#
|
544
|
+
# NilClass
|
197
545
|
#===============================================================================
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '1.
|
4
|
+
version: '1.1'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike O'Sullivan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: Misc utilities for
|
13
|
+
description: Misc utilities, mostly for use in other libraries that I'm uploading.
|
14
14
|
email: mike@idocs.com
|
15
15
|
executables: []
|
16
16
|
extensions: []
|