bblib 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +178 -20
- data/bblib.gemspec +1 -0
- data/lib/array/bbarray.rb +22 -13
- data/lib/bblib.rb +27 -17
- data/lib/bblib/version.rb +1 -1
- data/lib/file/bbfile.rb +20 -31
- data/lib/gem/bbgem.rb +28 -0
- data/lib/hash/bbhash.rb +26 -13
- data/lib/hash/hash_path.rb +214 -304
- data/lib/hash/hash_path_proc.rb +82 -82
- data/lib/hash/path_hash.rb +81 -0
- data/lib/object/attr.rb +182 -0
- data/lib/object/bbobject.rb +16 -0
- data/lib/object/hooks.rb +69 -0
- data/lib/object/lazy_class.rb +73 -0
- data/lib/opal/bbopal.rb +16 -0
- data/lib/os/bbos.rb +93 -0
- data/lib/os/bbsys.rb +238 -0
- data/lib/string/bbstring.rb +36 -6
- data/lib/string/cases.rb +1 -1
- data/lib/string/fuzzy_matcher.rb +14 -19
- data/lib/string/matching.rb +1 -1
- data/lib/string/roman.rb +5 -6
- data/lib/time/cron.rb +27 -27
- data/lib/time/task_timer.rb +34 -28
- metadata +24 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0877d2a3cdc6b8ce850cc65fc4996ac413f385b7
|
4
|
+
data.tar.gz: 3e6e7d62d8ec1ec1feec1deb6080ab079251e02b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f0bd38d8d3ea39e9a671f2e060ffe4e2c7342eec1b1751fcceb9e45c6f3792c61f27e55b75688531df083939f12d44e76f90fd3c7be310b2708c129bba2b0b3
|
7
|
+
data.tar.gz: e9e1f54e7b2e15bd184751dfd89190f7d50591c1b8aa14aac38af969a8424d33d075bb47024c06f274712e287816ba8545fe21a260a7cc5b6bf868995f700bf3
|
data/README.md
CHANGED
@@ -1,31 +1,44 @@
|
|
1
1
|
# BBLib
|
2
2
|
|
3
|
-
BBLib (Brandon-Black-Lib) is a collection of various reusable methods and classes to extend the Ruby language.
|
3
|
+
BBLib (Brandon-Black-Lib) is a collection of various reusable methods and classes to extend the Ruby language. One of the primary goals with the BBLib is to keep it as lightweight as possible. This means you will not find dependencies outside of the Ruby core libraries.
|
4
4
|
|
5
|
-
|
5
|
+
Good news! BBLib is now compatible with Opal! Well, like 90% compatible, but it can be 100% compiled into Javascript. Only very small tweaks were made to support this, so base functionality for the BBLib outside of Opal remains the same. But now it can coexist as both a Ruby gem, and an Opal library.
|
6
6
|
|
7
|
-
|
7
|
+
BBLib contains A LOT of functionality, but is a very small, lightweight library. As such, it can be hard to document everything that is included (and even harder to make a TL:DR version). Continue scrolling for a comprehensive view of what is offered, or take a look at the highlights below for the library's most significant features.
|
8
8
|
|
9
|
-
*
|
9
|
+
* __HashPath:__ Hash path is an XPath or JSONPath like navigation library for native Ruby hashes. It uses dot ('.') delimited path strings to navigate hash AND array objects. What makes hash path stand out is that it can navigate recursively within both hashes and arrays, including nested hashes/arrays (as deep as they can go!). It isn't only for navigating hashes; it can also copy, move, delete and run various methods using the same path notation.
|
10
10
|
|
11
11
|
```ruby
|
12
12
|
myhash = {a:1, b:2, c:{d:[3,4,{e:5},6]}, f:7}
|
13
13
|
p myhash.hash_path('c.d..e')
|
14
|
-
|
15
|
-
p myhash.hash_path('..
|
16
|
-
|
17
|
-
p myhash.hash_path('c.d[1]')
|
18
|
-
|
19
|
-
p myhash.hash_path('c.d[0..1]')
|
20
|
-
|
14
|
+
# => [5] - !!Hash Path always returns an array!!
|
15
|
+
p myhash.hash_path('..e')
|
16
|
+
# => [5]
|
17
|
+
p myhash.hash_path('c.d.[1]')
|
18
|
+
# => [4]
|
19
|
+
p myhash.hash_path('c.d.[0..1]')
|
20
|
+
# => [3, 4]
|
21
|
+
|
22
|
+
# Hash Path also supports formulas (evaluation statements)
|
23
|
+
# Formulas are surrounded in parenthesis following a path name
|
24
|
+
# A $ can be used to specify where in the eval statement to inject the variable
|
25
|
+
|
26
|
+
myarray = [
|
27
|
+
{title: 'Catan', cost: 41.99},
|
28
|
+
{title: 'Mouse Trap', cost: 5.50},
|
29
|
+
{title: 'Chess', cost: 25.99}
|
30
|
+
]
|
31
|
+
|
32
|
+
p myarray.hpath('[0..-1]($[:cost] > 10).title') # hpath is a shorter alias for hash_path
|
33
|
+
# => ["Catan", "Chess"]
|
21
34
|
|
22
35
|
# Move key/values
|
23
36
|
p myhash.hash_path_move('a' => 'c.g.h')
|
24
|
-
|
37
|
+
# => {:b=>2, :c=>{:d=>[3, 4, {:e=>5}, 6], :g=>{:h=>1}}, :f=>7}
|
25
38
|
|
26
39
|
# Copy key/values
|
27
40
|
p myhash.hash_path_copy('b' => 'z')
|
28
|
-
|
41
|
+
# => {:a=>1, :b=>2, :c=>{:d=>[3, 4, {:e=>5}, 6]}, :f=>7, :z=>2}
|
29
42
|
```
|
30
43
|
* __Deep Merge:__ A deep merge algorithm is included that can merge hashes with nested hashes or nested arrays or nested hashes with nested arrays with nested hashes and so on... It can also combine colliding values into arrays rather than overwriting using a toggle-able overwrite flag.
|
31
44
|
* __File & Time Parsing From Strings:__ Have a string such as '1MB 15KB' and want to make it numeric? Look no further. BBLib has methods to parse files size expressions and duration expressions from strings (like '1min 10sec'). Nearly any variant of size or duration expression is supported. For instance, '1sec', '1s', '1 s', '1 second', '1secs' are all properly parsed as 1 second.
|
@@ -210,9 +223,23 @@ h.reverse
|
|
210
223
|
#=> {:d=>4, :c=>3, :b=>2, :a=>1}
|
211
224
|
```
|
212
225
|
|
226
|
+
### Array
|
213
227
|
|
228
|
+
#### Interleave
|
214
229
|
|
215
|
-
|
230
|
+
Interleave takes two arrays and pieces them together by grabbing alternating elements from both arrays.
|
231
|
+
|
232
|
+
```ruby
|
233
|
+
a = ['This', 'a', '.']
|
234
|
+
b = ['is', 'test']
|
235
|
+
|
236
|
+
p BBLib.interleave a, b
|
237
|
+
# OR
|
238
|
+
p a.interleave b
|
239
|
+
#=> ["This", "is", "a", "test", "."]
|
240
|
+
```
|
241
|
+
|
242
|
+
### Numeric
|
216
243
|
|
217
244
|
#### Keep Between
|
218
245
|
|
@@ -286,7 +313,7 @@ fm.best_match 'Ruby', ['Ruby', 'Rails', 'Java', 'C++']
|
|
286
313
|
|
287
314
|
Implementations of the following algorithms are currently available. All algorithms are for calculating similarity between strings. Most are useful for fuzzy matching. All algorithms are available statically in the BBLib module but are also available as extensions to the String class. Most of these algorithms are case sensitive by default.
|
288
315
|
|
289
|
-
|
316
|
+
__1 - Levenshtein Distance__
|
290
317
|
|
291
318
|
A fairly simple rendition of the Levenshtein distance algorithm in Ruby. There are two functions available: **levenshtein_distance** and **levenshtein_similarity**. The former, calculates the number of additions, removals or substitutions needed to turn one string into another. The latter, uses the distance to calculate a percentage based match of two strings.
|
292
319
|
|
@@ -302,7 +329,7 @@ BBLib.levenshtein_distance 'Ruby is great', 'Rails is great'
|
|
302
329
|
#=> 71.42857142857143
|
303
330
|
```
|
304
331
|
|
305
|
-
|
332
|
+
__2 - String Composition__
|
306
333
|
|
307
334
|
Compares the character composition of two strings. The order of characters is not relevant, however, the number of occurrences is factored in.
|
308
335
|
|
@@ -311,7 +338,7 @@ Compares the character composition of two strings. The order of characters is no
|
|
311
338
|
#=> 71.42857142857143
|
312
339
|
```
|
313
340
|
|
314
|
-
|
341
|
+
__3 - Phrase Similarity__
|
315
342
|
|
316
343
|
Checks to see how many words in a string match another. Words must match exactly, including case. The results is the percentage of words that have an exact pair. The number of occurrences is also a factor.
|
317
344
|
|
@@ -323,7 +350,7 @@ Checks to see how many words in a string match another. Words must match exactly
|
|
323
350
|
#=> 66.66666666666666
|
324
351
|
```
|
325
352
|
|
326
|
-
|
353
|
+
__4 - Numeric Similarity _(In Progress)_ __
|
327
354
|
|
328
355
|
This algorithm is currently undergoing refactoring...
|
329
356
|
|
@@ -346,7 +373,7 @@ puts a.numeric_similarity b
|
|
346
373
|
```
|
347
374
|
This algorithm is generally only useful when combined with another algorithm, which is exactly what the FuzzyMatcher class does.
|
348
375
|
|
349
|
-
|
376
|
+
__5 - QWERTY Similarity__
|
350
377
|
|
351
378
|
A basic method that compares two strings by measuring the physical difference from one char to another on a QWERTY keyboard (alpha-numeric only). May be useful for detecting typos in words, but becomes less useful depending on the length of the string. This method is still in development and not yet in a final state. Currently a total distance is returned. Eventually, a percentage based match will replace this.
|
352
379
|
|
@@ -407,6 +434,51 @@ BBLib.from_roman "Toy Story III"
|
|
407
434
|
#=> 'Donkey Kong CountryIII'
|
408
435
|
```
|
409
436
|
|
437
|
+
#### Case Converters
|
438
|
+
|
439
|
+
Some basic case converters are now available. The majority of these are complete but not heavily tested, so some bugs or edge cases may exist.
|
440
|
+
|
441
|
+
Case supported:
|
442
|
+
* Title Case
|
443
|
+
* Start Case
|
444
|
+
* Camel Case
|
445
|
+
* Snake Case
|
446
|
+
* Spinal Case
|
447
|
+
* Train Case
|
448
|
+
* Delimited Case
|
449
|
+
|
450
|
+
Each case may be called directly on a string or using class methods in the BBLib module.
|
451
|
+
|
452
|
+
```ruby
|
453
|
+
sent = 'This is a casing-test. OK?'
|
454
|
+
|
455
|
+
puts sent.title_case
|
456
|
+
#=> This Is a Casing-Test. Ok?
|
457
|
+
|
458
|
+
puts sent.start_case
|
459
|
+
#=> This Is A Casing-Test. Ok?
|
460
|
+
|
461
|
+
puts sent.snake_case
|
462
|
+
#=> This_is_a_casing_test_OK
|
463
|
+
|
464
|
+
puts sent.spinal_case
|
465
|
+
#=> This-is-a-casing-test-OK
|
466
|
+
|
467
|
+
puts sent.train_case
|
468
|
+
#=> This-Is-A-Casing-Test-Ok
|
469
|
+
|
470
|
+
puts sent.delimited_case '+'
|
471
|
+
#=> This+is+a+casing+test+OK
|
472
|
+
|
473
|
+
# By default when title casing or start casing, the capitalize method is used on each word.
|
474
|
+
# This results in characters following the first to be downcased. To avoid this, the first_only param can be used.
|
475
|
+
# This param prevents all other chars in a word from being processed.
|
476
|
+
puts 'i like SQL'.title_case
|
477
|
+
#=> 'I Like Sql'
|
478
|
+
|
479
|
+
puts 'i like SQL'.title_case first_only: true
|
480
|
+
#=> I Like SQL
|
481
|
+
```
|
410
482
|
|
411
483
|
#### Other
|
412
484
|
|
@@ -507,7 +579,35 @@ puts BBLib::Cron.next('1-3,4,5,10-11 1-10 */5 * * *')
|
|
507
579
|
#=> 2016-04-06 01:01:00 -0600
|
508
580
|
```
|
509
581
|
|
510
|
-
|
582
|
+
Named days of the week and month are also supported in various formats and can be used in ranges or comma separated lists. They can even the intermingled with numbers such as 'Jun-9'.
|
583
|
+
|
584
|
+
```ruby
|
585
|
+
puts BBLib::Cron.next('* * * * sun *')
|
586
|
+
#=> 2016-04-10 00:00:00 -0600
|
587
|
+
|
588
|
+
puts BBLib::Cron.next('* * * * sunday *')
|
589
|
+
#=> 2016-04-10 00:00:00 -0600
|
590
|
+
|
591
|
+
puts BBLib::Cron.next('* * * * sun,sat *')
|
592
|
+
#=> 2016-04-09 00:00:00 -0600
|
593
|
+
|
594
|
+
puts BBLib::Cron.next('* * * Jun-Dec * *')
|
595
|
+
#=> 2016-06-01 00:00:00 -0600
|
596
|
+
|
597
|
+
# The next Friday the 13th in December
|
598
|
+
puts BBLib::Cron.next('* * 13 Dec Fri *')
|
599
|
+
#=> 2019-12-13 00:00:00 -0700
|
600
|
+
|
601
|
+
# The next leap year
|
602
|
+
puts BBLib::Cron.next('* * 29 February * *')
|
603
|
+
#=> 2020-02-29 00:00:00 -0700
|
604
|
+
|
605
|
+
# The next Feb 29th that also happens to be a Monday
|
606
|
+
puts BBLib::Cron.next('* * 29 February Monday *')
|
607
|
+
#=> 2044-02-29 00:00:00 -0700
|
608
|
+
```
|
609
|
+
|
610
|
+
Common Vixie-isms are also supported:
|
511
611
|
|
512
612
|
```ruby
|
513
613
|
puts BBLib::Cron.next('@daily')
|
@@ -517,6 +617,9 @@ puts BBLib::Cron.next('@weekly')
|
|
517
617
|
#=> 2016-04-10 00:00:00 -0600
|
518
618
|
```
|
519
619
|
|
620
|
+
_Supported list of Vixie-isms: @daily, @midnight, @noon, @weekly, @monthly, @yearly, @annually_
|
621
|
+
_Note: @reboot and @restart can be parsed but are inaccurate due to the fact that they have no way of knowing the next reboot._
|
622
|
+
|
520
623
|
#### Duration parser
|
521
624
|
|
522
625
|
**Parsing a duration from String**
|
@@ -584,6 +687,61 @@ There is also a method to turn a Numeric object into a string representation of
|
|
584
687
|
#=> '34h 12m 4s'
|
585
688
|
```
|
586
689
|
|
690
|
+
#### Task Timer
|
691
|
+
|
692
|
+
A very simple task timer is also included. It is not intended to replace benchmarking classes but rather to augment or be used for simplistic timing. You simply need to instantiate a timer and then call start with the name of the task. To stop the timer, call stop and pass in the same task name. Once a single time has been completed for any given task a few different metrics can be pulled on that task. These metrics may also be printed in bulk using the _stats_ method.
|
693
|
+
|
694
|
+
```ruby
|
695
|
+
# Generate a new timer object
|
696
|
+
t = BBLib::TaskTimer.new
|
697
|
+
|
698
|
+
# Call start right before initiating a task and stop immediately after.
|
699
|
+
5.times do
|
700
|
+
t.start :random_sleep
|
701
|
+
# Perform task...
|
702
|
+
sleep(rand())
|
703
|
+
t.stop :random_sleep
|
704
|
+
end
|
705
|
+
|
706
|
+
# Print out the stats from the task
|
707
|
+
puts t.stats :random_sleep
|
708
|
+
#=> random_sleep
|
709
|
+
#=> ------------------------------
|
710
|
+
#=> Count 5
|
711
|
+
#=> First 0.3134028911590576
|
712
|
+
#=> Last 0.5248761177062988
|
713
|
+
#=> Min 0.20781898498535156
|
714
|
+
#=> Max 0.9016561508178711
|
715
|
+
#=> Avg 0.4677897930145264
|
716
|
+
#=> Sum 2.338948965072632
|
717
|
+
|
718
|
+
# Same as above but cnverts seconds into human readable time durations.
|
719
|
+
# The pretty argument may also be applied to individual stat calls such as avg, sum, min, max, etc...
|
720
|
+
puts t.stats :random_sleep, pretty: true
|
721
|
+
#=> random_sleep
|
722
|
+
#=> ------------------------------
|
723
|
+
#=> Count 5
|
724
|
+
#=> First 313 mils
|
725
|
+
#=> Last 525 mils
|
726
|
+
#=> Min 208 mils
|
727
|
+
#=> Max 902 mils
|
728
|
+
#=> Avg 468 mils
|
729
|
+
#=> Sum 2 secs 339 mils
|
730
|
+
|
731
|
+
# Similar to the above task, this version uses a restart which stops the first start call and initiates a new timer
|
732
|
+
t.start :another_task
|
733
|
+
5.times do
|
734
|
+
sleep(rand())
|
735
|
+
t.restart :another_task
|
736
|
+
end
|
737
|
+
|
738
|
+
# Get the individual average stat for another task. Method calls are aliases so you could also use .average or .av to get the average.
|
739
|
+
puts t.avg :another_task
|
740
|
+
#=> 0.5790667057037353
|
741
|
+
```
|
742
|
+
|
743
|
+
By default the task timer will only keep the stats from 100 runs of each task it tracks. The retention can be increased or decreased using the _retention_ method. Also, call stop will return the total time the stopped task ran.
|
744
|
+
|
587
745
|
## Development
|
588
746
|
|
589
747
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/bblib.gemspec
CHANGED
data/lib/array/bbarray.rb
CHANGED
@@ -2,40 +2,49 @@
|
|
2
2
|
module BBLib
|
3
3
|
|
4
4
|
# Takes two arrays (can be of different length) and interleaves them like [a[0], b[0], a[1], b[1]...]
|
5
|
-
def self.interleave a, b
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
5
|
+
def self.interleave a, b
|
6
|
+
ary = Array.new
|
7
|
+
[a.size, b.size].max.times do |i|
|
8
|
+
ary.push(a[i]) if i < a.size
|
9
|
+
ary.push(b[i]) if i < b.size
|
11
10
|
end
|
12
|
-
|
11
|
+
ary
|
13
12
|
end
|
14
13
|
|
15
14
|
end
|
16
15
|
|
17
16
|
class Array
|
17
|
+
|
18
18
|
def msplit *delims, keep_empty: false
|
19
19
|
self.map{ |i| i.msplit(delims, keep_empty:keep_empty)}.flatten
|
20
20
|
end
|
21
|
+
alias_method :multi_split, :msplit
|
21
22
|
|
22
23
|
def keys_to_sym clean: false
|
23
|
-
self.map{ |v| Hash
|
24
|
+
self.map{ |v| v.is_a?(Hash) || v.is_a?(Array) ? v.keys_to_sym(clean:clean) : v }
|
24
25
|
end
|
25
26
|
|
26
27
|
def keys_to_s clean: false
|
27
|
-
self.map{ |v| Hash
|
28
|
+
self.map{ |v| v.is_a?(Hash) || v.is_a?(Array) ? v.keys_to_s : v }
|
28
29
|
end
|
29
30
|
|
30
31
|
def to_xml level: 0, key:nil
|
31
32
|
map do |v|
|
32
33
|
nested = v.respond_to?(:to_xml)
|
33
|
-
value = nested ? v.to_xml(level:level+1, key:key) : v
|
34
|
-
"\t"*level + "<#{key}>\n" +
|
34
|
+
value = nested ? v.to_xml(level:level + 1, key:key) : v
|
35
|
+
"\t" * level + "<#{key}>\n" +
|
36
|
+
(nested ? '' : "\t"*(level+1)) +
|
37
|
+
"#{value}\n" +
|
38
|
+
"\t"*level + "</#{key}>\n"
|
35
39
|
end.join
|
36
40
|
end
|
37
41
|
|
38
|
-
def interleave b
|
39
|
-
BBLib.interleave self, b
|
42
|
+
def interleave b
|
43
|
+
BBLib.interleave self, b
|
44
|
+
end
|
45
|
+
|
46
|
+
def diff b
|
47
|
+
(self-b) + (b-self)
|
40
48
|
end
|
49
|
+
|
41
50
|
end
|
data/lib/bblib.rb
CHANGED
@@ -1,17 +1,27 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
1
|
+
require_relative 'bblib/version'
|
2
|
+
require_relative 'opal/bbopal'
|
3
|
+
require_relative 'object/bbobject'
|
4
|
+
require_relative 'object/lazy_class'
|
5
|
+
require_relative 'string/bbstring'
|
6
|
+
require_relative 'file/bbfile'
|
7
|
+
require_relative 'time/bbtime'
|
8
|
+
require_relative 'hash/bbhash'
|
9
|
+
require_relative 'gem/bbgem'
|
10
|
+
require_relative 'number/bbnumber'
|
11
|
+
require_relative 'array/bbarray'
|
12
|
+
|
13
|
+
non_opal = ['os/bbos', 'gem/bbgem']
|
14
|
+
|
15
|
+
unless BBLib::in_opal?
|
16
|
+
non_opal.each{ |i| require_relative i }
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
require 'fileutils'
|
21
|
+
# require 'uri'
|
22
|
+
|
23
|
+
module BBLib
|
24
|
+
|
25
|
+
CONFIGS_PATH = 'config/'
|
26
|
+
|
27
|
+
end
|
data/lib/bblib/version.rb
CHANGED
data/lib/file/bbfile.rb
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
module BBLib
|
4
4
|
|
5
|
+
# Takes one or more strings and normalizes slashes to create a consistent file path
|
6
|
+
# Useful when concating two strings that when you don't know if one or both will end or begin with a slash
|
7
|
+
def self.pathify *strings
|
8
|
+
start = strings.first.start_with?('/') || strings.first.start_with?('\\')
|
9
|
+
(start ? '/' : '' ) + strings.map(&:to_s).msplit('/', '\\').map(&:strip).join('/')
|
10
|
+
end
|
11
|
+
|
5
12
|
# Scan for files and directories. Can be set to be recursive and can also have filters applied.
|
6
13
|
def self.scan_dir path = Dir.pwd, filter: nil, recursive: false
|
7
14
|
if !filter.nil?
|
@@ -22,7 +29,7 @@ module BBLib
|
|
22
29
|
BBLib.scan_dir(path, filter: filter, recursive: recursive).map{ |f| File.directory?(f) ? (mode == :dir ? Dir.new(f) : f ) : nil}.reject{ |r| r.nil? }
|
23
30
|
end
|
24
31
|
|
25
|
-
# Shorthand method to write a string to
|
32
|
+
# Shorthand method to write a string to disk. By default the path is created if it doesn't exist.
|
26
33
|
# Set mode to w to truncate file or leave at a to append.
|
27
34
|
def self.string_to_file path, str, mkpath = true, mode: 'a'
|
28
35
|
if !Dir.exists?(path) && mkpath
|
@@ -37,43 +44,21 @@ module BBLib
|
|
37
44
|
bytes = 0.0
|
38
45
|
FILE_SIZES.each do |k, v|
|
39
46
|
v[:exp].each do |e|
|
40
|
-
numbers = str.scan(/(?=\w|\D
|
47
|
+
numbers = str.scan(/(?=\w|\D|^)\d*\.?\d+\s*#{e}s?(?=\W|\d|$)/i)
|
41
48
|
numbers.each{ |n| bytes+= n.to_f * v[:mult] }
|
42
49
|
end
|
43
50
|
end
|
44
51
|
return bytes / FILE_SIZES[output][:mult]
|
45
52
|
end
|
46
53
|
|
47
|
-
# A mostly platform agnostic call to get root volumes
|
48
|
-
def self.root_dirs
|
49
|
-
begin # For windows
|
50
|
-
`wmic logicaldisk get name`.split("\n").map{ |m| m.strip }[1..-1].reject{ |r| r == '' }
|
51
|
-
rescue
|
52
|
-
begin # Windows attempt 2
|
53
|
-
`fsutil fsinfo drives`.scan(/(?<=\s)\w\:/)
|
54
|
-
rescue # Linux
|
55
|
-
begin
|
56
|
-
`ls /`.split("\n").map{ |m| m.strip }.reject{ |r| r == '' }
|
57
|
-
rescue # All attempts failed
|
58
|
-
nil
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# Windows only method to get the volume labels of disk drives
|
65
|
-
def self.root_volume_labels
|
66
|
-
`wmic logicaldisk get caption,volumename`.split("\n")[1..-1].map{ |m| [m.split(" ").first.to_s.strip, m.split(" ")[1..-1].to_a.join(' ').strip] }.reject{ |o,t| o == '' }.to_h
|
67
|
-
end
|
68
|
-
|
69
54
|
FILE_SIZES = {
|
70
|
-
byte:
|
71
|
-
kilobyte:
|
72
|
-
megabyte:
|
73
|
-
gigabyte:
|
74
|
-
terabyte:
|
75
|
-
petabyte:
|
76
|
-
exabyte:
|
55
|
+
byte: { mult: 1, exp: ['b', 'byt', 'byte'] },
|
56
|
+
kilobyte: { mult: 1024, exp: ['kb', 'kilo', 'k', 'kbyte', 'kilobyte'] },
|
57
|
+
megabyte: { mult: 1048576, exp: ['mb', 'mega', 'm', 'mib', 'mbyte', 'megabyte'] },
|
58
|
+
gigabyte: { mult: 1073741824, exp: ['gb', 'giga', 'g', 'gbyte', 'gigabyte'] },
|
59
|
+
terabyte: { mult: 1099511627776, exp: ['tb', 'tera', 't', 'tbyte', 'terabyte'] },
|
60
|
+
petabyte: { mult: 1125899906842624, exp: ['pb', 'peta', 'p', 'pbyte', 'petabyte'] },
|
61
|
+
exabyte: { mult: 1152921504606846976, exp: ['eb', 'exa', 'e', 'ebyte', 'exabyte'] },
|
77
62
|
zettabyte: { mult: 1180591620717411303424, exp: ['zb', 'zetta', 'z', 'zbyte', 'zettabyte'] },
|
78
63
|
yottabyte: { mult: 1208925819614629174706176, exp: ['yb', 'yotta', 'y', 'ybyte', 'yottabyte'] }
|
79
64
|
}
|
@@ -102,4 +87,8 @@ class String
|
|
102
87
|
def parse_file_size output: :byte
|
103
88
|
BBLib.parse_file_size(self, output:output)
|
104
89
|
end
|
90
|
+
|
91
|
+
def pathify
|
92
|
+
BBLib.pathify(self)
|
93
|
+
end
|
105
94
|
end
|