rafini 2.0.0 → 3.1.221212
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +112 -74
- data/lib/rafini/array.rb +41 -40
- data/lib/rafini/empty.rb +6 -5
- data/lib/rafini/exception.rb +2 -2
- data/lib/rafini/hash.rb +18 -37
- data/lib/rafini/integer.rb +15 -11
- data/lib/rafini/odometers.rb +106 -78
- data/lib/rafini/requires.rb +42 -0
- data/lib/rafini/string.rb +13 -6
- data/lib/rafini.rb +13 -8
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8daaac2f079c639abaa892b634f6400f1b0e75ffead282c4551dc8fb7fe45fda
|
4
|
+
data.tar.gz: a383dca85331bc2cf43e443fc909a9612044ea2c0f73a33a7bc9c568f2db0370
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b169dce8d8edd85971c8e62c433b3485a863fa8327e84430e253d660dbc0ca5a89c0106830ecedbfdb52103fd12bfb0193b07504dbc50b2812ced3a12096595c
|
7
|
+
data.tar.gz: c62702b40d3f826f4a63828e3122dada54376c8cd23f358b17a1c6650e6fc79bec2914f706c55d61c2ba0a087e88c2a848cdaec7410bda5b238d44b33f6b4f9d
|
data/README.md
CHANGED
@@ -1,101 +1,139 @@
|
|
1
|
-
#
|
1
|
+
# Rafini
|
2
|
+
|
3
|
+
* [VERSION 3.1.221212](https://github.com/carlosjhr64/rafini/releases)
|
4
|
+
* [github](https://github.com/carlosjhr64/rafini)
|
5
|
+
* [rubygems](https://rubygems.org/gems/rafini)
|
2
6
|
|
3
7
|
## DESCRIPTION:
|
4
8
|
|
5
9
|
Just a collection of useful refinements.
|
6
10
|
|
11
|
+
## INSTALL:
|
12
|
+
```shell
|
13
|
+
$ gem install rafini
|
14
|
+
```
|
7
15
|
## SYNOPSIS:
|
8
|
-
|
16
|
+
```ruby
|
17
|
+
require 'rafini'
|
18
|
+
```
|
19
|
+
### include Rafini::Empty
|
20
|
+
```ruby
|
21
|
+
include Rafini::Empty
|
22
|
+
|
23
|
+
s0 #=> ""
|
24
|
+
a0 #=> []
|
25
|
+
h0 #=> {}
|
26
|
+
[s0,a0,h0].all?(&:frozen?) #=> true
|
27
|
+
```
|
9
28
|
### using Rafini::Array
|
29
|
+
```ruby
|
30
|
+
using Rafini::Array
|
10
31
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# per
|
15
|
-
h={}
|
16
|
-
['a','b','c'].per(['A','B','C']){|l,u| h[l]=u}
|
17
|
-
h #=> {'a'=>'A','b'=>'B','c'=>'C'}
|
18
|
-
|
19
|
-
# which
|
20
|
-
['dog','cat','bunny'].which{|a|a=~/c/} #=> "cat"
|
21
|
-
|
22
|
-
# is
|
23
|
-
[:a,:b,:c].is(true) #=> {a: true, b: true, c: true}
|
32
|
+
# classify(like Set#classify)
|
33
|
+
[1, 2.0, 'Three', 4.0].classify #=> {Integer=>[1], Float=>[2.0, 4.0], String=>["Three"]}
|
24
34
|
|
25
|
-
|
26
|
-
|
27
|
-
# $!.puts
|
28
|
-
begin
|
29
|
-
raise 'Ugly Message'
|
30
|
-
rescue RuntimeError
|
31
|
-
$!.puts 'Nice Message'
|
32
|
-
end
|
33
|
-
|
34
|
-
# Rafini.bang!
|
35
|
-
value = Rafini.bang!('Nice Message') do
|
36
|
-
raise 'Ugly Message'
|
37
|
-
end
|
38
|
-
value #=> return value of block or error object
|
39
|
-
|
40
|
-
# Rafini.thread_bang!
|
41
|
-
Rafini.thread_bang!('Nice Message') do
|
42
|
-
# this is in a thread
|
43
|
-
raise 'Ugly Message'
|
44
|
-
end
|
35
|
+
# is
|
36
|
+
[:a,:b,:c].is(true) #=> {:a=>true, :b=>true, :c=>true}
|
45
37
|
|
38
|
+
# joins
|
39
|
+
['Y','M','D','h','m','s'].joins('-','-',' '){':'}
|
40
|
+
#=> "Y-M-D h:m:s"
|
41
|
+
[1,9,2,8,3,7,4,6,5,5].joins{|a,b|a>b ? '>': a<b ? '<': '='}
|
42
|
+
#=> "1<9>2<8>3<7>4<6>5=5"
|
43
|
+
```
|
46
44
|
### using Rafini::Hash
|
45
|
+
```ruby
|
46
|
+
using Rafini::Hash
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
struct
|
51
|
-
|
52
|
-
|
53
|
-
{a:'A',b:'B'}.modify({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X',c:'Y',d:'D'}
|
48
|
+
# to_struc
|
49
|
+
struct = {a:'A',b:'C',c:'C'}.to_struct{ def ok = "OK" }
|
50
|
+
struct #=> #<struct a="A", b="C", c="C">
|
51
|
+
struct.a #=> "A"
|
52
|
+
struct.ok #=> "OK"
|
54
53
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
# amend
|
59
|
-
{a:'A',b:'B'}.amend({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X'}
|
60
|
-
|
61
|
-
# maps
|
62
|
-
{a:'A',b:'B',c:'C',c:'D'}.maps(:c,:a,:b) #=> ['C','A','B']
|
54
|
+
# supplement
|
55
|
+
{a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {:a=>"A", :b=>"B", :c=>"C", :d=>"D"}
|
63
56
|
|
57
|
+
# amend
|
58
|
+
{a:'A',b:'B'}.amend({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {:a=>"A", :b=>"X"}
|
59
|
+
```
|
64
60
|
### using Rafini::Integer
|
61
|
+
```ruby
|
62
|
+
using Rafini::Integer
|
65
63
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
### using Rafini::Odometers
|
71
|
-
|
72
|
-
# sec2time
|
73
|
-
12501.sec2time.to_s #=> "3 hours and 28 minutes"
|
74
|
-
|
75
|
-
# illion
|
76
|
-
3_512_325.illion.to_s #=> "3.51M"
|
77
|
-
|
64
|
+
# odometer
|
65
|
+
123.odometer(10,10) #=> [3, 2, 1]
|
66
|
+
30.odometer(2,3,5) #=> [0, 0, 0, 1]
|
67
|
+
```
|
78
68
|
### using Rafini::String
|
69
|
+
```ruby
|
70
|
+
using Rafini::String
|
79
71
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
# semantic
|
84
|
-
'1.2.3'.semantic(0..1) #=> '1.2'
|
85
|
-
|
86
|
-
### Rafini::Empty
|
72
|
+
# camelize
|
73
|
+
'a_camel_kick'.camelize #=> "ACamelKick"
|
87
74
|
|
88
|
-
|
89
|
-
|
90
|
-
## INSTALL:
|
91
|
-
|
92
|
-
$ gem install rafini
|
75
|
+
# semantic
|
76
|
+
'1.2.3'.semantic(0..1) #=> "1.2"
|
93
77
|
|
78
|
+
# shellescape(like Shellwords.escape)
|
79
|
+
'Hello World!'.shellescape #=> "Hello\\ World\\!"
|
80
|
+
```
|
81
|
+
### using Rafini::Exception
|
82
|
+
```ruby
|
83
|
+
using Rafini::Exception
|
84
|
+
|
85
|
+
# $!.puts
|
86
|
+
# Normally stderr.puts your "Nice" message.
|
87
|
+
# Additionally puts your "Ugly" message when $VERBOSE.
|
88
|
+
# Additionally puts backtrace when $DEBUG
|
89
|
+
# No output when $VERBOSE is nil.
|
90
|
+
begin
|
91
|
+
raise 'Ugly Message'
|
92
|
+
rescue RuntimeError
|
93
|
+
$!.puts 'Nice Message'
|
94
|
+
end
|
95
|
+
|
96
|
+
# Rafini.bang!
|
97
|
+
error = Rafini.bang!('Nice Message') do
|
98
|
+
raise 'Ugly Message'
|
99
|
+
# Outputs as $!.puts "Nice Message"
|
100
|
+
end
|
101
|
+
error.class #=> RuntimeError
|
102
|
+
error.to_s #=> "Ugly Message"
|
103
|
+
|
104
|
+
# Rafini.thread_bang!
|
105
|
+
thread = Rafini.thread_bang!('Nice Message') do
|
106
|
+
# this is in a thread
|
107
|
+
raise 'Ugly Message' # outputs as $!.puts 'Nice Message'
|
108
|
+
end
|
109
|
+
# The returned value joined from the thread
|
110
|
+
# will not re-raise the error(but gives the error).
|
111
|
+
thread.value.class #=> RuntimeError
|
112
|
+
```
|
113
|
+
### using Rafini::Odometers
|
114
|
+
```ruby
|
115
|
+
using Rafini::Odometers
|
116
|
+
|
117
|
+
# sec2time
|
118
|
+
12501.sec2time.to_s #=> "3 hours and 28 minutes"
|
119
|
+
|
120
|
+
# illion
|
121
|
+
3_512_325.illion.to_s #=> "3.51M"
|
122
|
+
```
|
123
|
+
### using Rafini::Requires
|
124
|
+
```ruby
|
125
|
+
using Rafini::Requires
|
126
|
+
|
127
|
+
requires'
|
128
|
+
ruby ~>3.0
|
129
|
+
rafini ~>3.1
|
130
|
+
json ~>2.0' #=> ["json"]
|
131
|
+
```
|
94
132
|
## LICENSE:
|
95
133
|
|
96
134
|
(The MIT License)
|
97
135
|
|
98
|
-
Copyright (c)
|
136
|
+
Copyright (c) 2022 CarlosJHR64
|
99
137
|
|
100
138
|
Permission is hereby granted, free of charge, to any person obtaining
|
101
139
|
a copy of this software and associated documentation files (the
|
data/lib/rafini/array.rb
CHANGED
@@ -1,54 +1,55 @@
|
|
1
1
|
module Rafini
|
2
2
|
module Array
|
3
3
|
refine ::Array do
|
4
|
-
#
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# Note that the iteration number starts at 1.
|
11
|
-
# Lastly it uses an empty string.
|
12
|
-
# ['a','b','c','d','e','f'].joins('-', '-', ' '){':'} #=> 'a-b-c d:e:f'
|
13
|
-
# ['a','b','c'].joins{','} #=> 'a,b,c'
|
14
|
-
# ['1','2','3'].joins('.') #=> '1.23'
|
15
|
-
# ['a','b','c'].joins{|i|i} #=> 'a1b2c'
|
16
|
-
def joins(*p, &block)
|
17
|
-
str = ''
|
18
|
-
if length > 0
|
19
|
-
str << self[0]
|
20
|
-
1.upto(length-1) do |i|
|
21
|
-
str << (p.empty? ? (block ? block.call(i).to_s : '') : p.shift.to_s)
|
22
|
-
str << self[i]
|
23
|
-
end
|
24
|
-
end
|
25
|
-
return str
|
26
|
-
end
|
27
|
-
|
28
|
-
# array1.per(array2){|obj1, obj2| ... }
|
29
|
-
#
|
30
|
-
# Gives the block each two elements of two array respectively.
|
31
|
-
# If the second array is not given, it passes the block the index number instead.
|
32
|
-
# h={} # say you have a hash h, then
|
33
|
-
# ['a','b','c'].per(['A','B','C']){|l,n| h[l]=n} # h=={'a'=>'A','b'=>'B','c'=>'C'}
|
34
|
-
# ['a','b','c'].per{|l,i| h[l]=i} # h=={'a'=>0,'b'=>1,'c'=>2}
|
35
|
-
def per(b=nil)
|
36
|
-
0.upto(length-1){|i| yield self[i], (b)? b[i] : i}
|
4
|
+
# classify:
|
5
|
+
# Like Set#classify
|
6
|
+
def classify(hash: ::Hash.new{|h,k|h[k]=[]}, &block)
|
7
|
+
block ||= lambda{|v|v.class}
|
8
|
+
self.each{|v| hash[block[v]] << v}
|
9
|
+
return hash
|
37
10
|
end
|
38
11
|
|
39
|
-
#
|
40
|
-
#
|
41
|
-
# Returns first object for which block is true.
|
42
|
-
# ['dog','cat','bunny'].which{|a|a=~/c/} #=> "cat"
|
43
|
-
alias which detect
|
44
|
-
|
12
|
+
# is:
|
45
13
|
# [:a,:b,:c].is(true) #=> {:a=>true,:b=>true,:c=>true}
|
46
14
|
#
|
47
15
|
# Updates a hash with the keys given by the array to the given value.
|
48
16
|
def is(value, hash={})
|
49
|
-
|
17
|
+
each{|key| hash[key]=value}
|
50
18
|
return hash
|
51
19
|
end
|
20
|
+
|
21
|
+
# joins:
|
22
|
+
# type _AToS = ::Array[(_AToS|_ToS)]
|
23
|
+
# _AToS#joins(*_AToS seps)?{(_ToS,_ToS)->_ToS}
|
24
|
+
#
|
25
|
+
# Returns a string created by joining the elements of the (flatten) array,
|
26
|
+
# separated by the given (flatten) separators.
|
27
|
+
# If no separators are given or are used up,
|
28
|
+
# it uses the value of the executed block,
|
29
|
+
# which is passed the next neigboring iteration items.
|
30
|
+
# Else, it just joins the items.
|
31
|
+
# ['2021','Jan','09','07','29','05'].joins('-', '-', ' '){':'}
|
32
|
+
# #=> "2021-Jan-09 07:29:05"
|
33
|
+
# [:a,[1,2],:b].joins{','} #=> 'a,1,2,b'
|
34
|
+
# [3,1,4,1,5,9].joins('.') #=> '3.14159'
|
35
|
+
# [1,9,2,8,3,7,4,6,5,5].joins{|a,b|a>b ? '>': a<b ? '<': '='}
|
36
|
+
# #=> "1<9>2<8>3<7>4<6>5=5"
|
37
|
+
def joins(*seps, &block)
|
38
|
+
return '' if length < 1
|
39
|
+
items = flatten
|
40
|
+
previous = items.shift
|
41
|
+
string = ::String.new previous.to_s
|
42
|
+
return string if items.empty?
|
43
|
+
seps.flatten!
|
44
|
+
while item = items.shift
|
45
|
+
if sep = seps.shift&.to_s || block&.call(previous,item)&.to_s
|
46
|
+
string << sep
|
47
|
+
end
|
48
|
+
string << item.to_s
|
49
|
+
previous = item
|
50
|
+
end
|
51
|
+
return string
|
52
|
+
end
|
52
53
|
end
|
53
54
|
end
|
54
55
|
end
|
data/lib/rafini/empty.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module Rafini
|
2
|
-
# In a world where objects are allowed to represent infinities,
|
3
|
-
# Rafini dares to introduce empty sets. But WHY!???
|
4
|
-
# Ta-ta-TUM...
|
5
2
|
module Empty
|
6
|
-
ARRAY
|
7
|
-
HASH
|
3
|
+
ARRAY = [].freeze
|
4
|
+
HASH = {}.freeze
|
8
5
|
STRING = ''.freeze
|
6
|
+
|
7
|
+
def a0 = ARRAY
|
8
|
+
def h0 = HASH
|
9
|
+
def s0 = STRING
|
9
10
|
end
|
10
11
|
end
|
data/lib/rafini/exception.rb
CHANGED
@@ -29,7 +29,7 @@ using Rafini::Exception
|
|
29
29
|
# value = Rafini.bang!('Ooops! Not perfect?') do
|
30
30
|
# # Perfect code here...
|
31
31
|
# end
|
32
|
-
def Rafini.bang!(message=nil, bang
|
32
|
+
def Rafini.bang!(message=nil, bang=::Exception, &block)
|
33
33
|
value = nil
|
34
34
|
begin
|
35
35
|
value = block.call
|
@@ -52,6 +52,6 @@ end
|
|
52
52
|
# end
|
53
53
|
# With the following below, I'll be able to say
|
54
54
|
# Rafini.thread_bang!('blah blah...'){ ...stuff... }
|
55
|
-
def Rafini.thread_bang!(header=nil, bang
|
55
|
+
def Rafini.thread_bang!(header=nil, bang=::Exception, &block)
|
56
56
|
Thread.new{Rafini.bang!(header, bang, &block)}
|
57
57
|
end
|
data/lib/rafini/hash.rb
CHANGED
@@ -3,30 +3,17 @@ module Rafini
|
|
3
3
|
refine ::Hash do
|
4
4
|
# struct = hash.to_struct
|
5
5
|
# Why not?
|
6
|
-
def to_struct
|
7
|
-
Struct.new(*
|
6
|
+
def to_struct(&blk)
|
7
|
+
Struct.new(*keys, &blk).new(*values)
|
8
8
|
end
|
9
9
|
|
10
|
-
# hash0.
|
11
|
-
#
|
12
|
-
# Updates hash with hashes.
|
13
|
-
# Overwrites existing elements and adds elements.
|
14
|
-
# {a:'A',b:'B'}.modify({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X',c:'Y',d:'D'}
|
15
|
-
def modify(*hashes)
|
16
|
-
hashes.each do |hash|
|
17
|
-
hash.each do |key, value|
|
18
|
-
self[key] = value
|
19
|
-
end
|
20
|
-
end
|
21
|
-
self
|
22
|
-
end
|
23
|
-
|
24
|
-
# hash0.supplement(hash1,...) #=> hash
|
10
|
+
# hash0.supplement!(hash1,...) #=> hash
|
25
11
|
#
|
26
12
|
# Supplements hash with hashes.
|
27
13
|
# Adds missing elements only.
|
28
|
-
# {a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'})
|
29
|
-
|
14
|
+
# {a:'A',b:'B'}.supplement({b:'X',c:'C'},{c:'Y',d:'D'})
|
15
|
+
# #=> {a:'A',b:'B',c:'C',d:'D'}
|
16
|
+
def supplement!(*hashes)
|
30
17
|
hashes.each do |hash|
|
31
18
|
hash.each do |key, value|
|
32
19
|
self[key] = value unless self.has_key?(key)
|
@@ -34,30 +21,24 @@ module Rafini
|
|
34
21
|
end
|
35
22
|
self
|
36
23
|
end
|
24
|
+
def supplement(...)
|
25
|
+
self.dup.supplement!(...)
|
26
|
+
end
|
37
27
|
|
38
|
-
# hash0.
|
28
|
+
# hash0.amend(hash1,...)
|
39
29
|
#
|
40
30
|
# Ammends hash with hashes.
|
41
|
-
# Overwrites existing
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
self[key] = hash[key]
|
48
|
-
break
|
49
|
-
end
|
50
|
-
end
|
31
|
+
# Overwrites existing keys
|
32
|
+
# only with first key value found in amending hashes.
|
33
|
+
# {a:'A',b:'B'}.amend({b:'X',c:'C'},{c:'Y',d:'D'}) #=> {a:'A',b:'X'}
|
34
|
+
def amend!(*hashes)
|
35
|
+
self.each_key do |key|
|
36
|
+
value=hashes.find{_1.has_key? key}&.fetch(key) and self[key]=value
|
51
37
|
end
|
52
38
|
self
|
53
39
|
end
|
54
|
-
|
55
|
-
|
56
|
-
#
|
57
|
-
# Maps parameters list with hash.
|
58
|
-
# {a:'A",b:'B',c:'C'}.maps(:c,:a,:b) #=> ['C','A','B']
|
59
|
-
def maps(*keys)
|
60
|
-
keys.map{|_|self[_]}
|
40
|
+
def amend(...)
|
41
|
+
self.dup.amend!(...)
|
61
42
|
end
|
62
43
|
end
|
63
44
|
end
|
data/lib/rafini/integer.rb
CHANGED
@@ -5,21 +5,25 @@ module Rafini
|
|
5
5
|
# Kinda hard to explain...
|
6
6
|
# 123.odometer(10,10) #=> [3,2,1]
|
7
7
|
# 30.odometer(2,3,5) #=> [0,0,0,1]
|
8
|
-
# ((60*60*24)*3 + (60*60)*12 + 60*15 + 30).odometer(60,60,24)
|
8
|
+
# ((60*60*24)*3 + (60*60)*12 + 60*15 + 30).odometer(60,60,24)
|
9
|
+
# #=> [30, 15, 12, 3]
|
9
10
|
# Useful for making clocks, number scales, mayan long count... etc.
|
10
|
-
def odometer(*
|
11
|
-
|
12
|
-
|
13
|
-
r = []
|
11
|
+
def odometer(*levels, factors: true)
|
12
|
+
raise RangeError, 'negative odometer' if self < 0
|
13
|
+
readings, remainder = [], self
|
14
14
|
|
15
|
-
(
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
levels = levels.inject([1]){|m, f| m.push(m.last*f)} if factors
|
16
|
+
levels.shift
|
17
|
+
|
18
|
+
levels.reverse_each do |level|
|
19
|
+
# in case of a float, floor
|
20
|
+
reading = (remainder/level).floor
|
21
|
+
readings.unshift reading
|
22
|
+
remainder = remainder%level
|
19
23
|
end
|
20
|
-
r.unshift n
|
21
24
|
|
22
|
-
|
25
|
+
# in case of a float, round
|
26
|
+
readings.unshift remainder.round
|
23
27
|
end
|
24
28
|
end
|
25
29
|
end
|
data/lib/rafini/odometers.rb
CHANGED
@@ -1,78 +1,101 @@
|
|
1
|
+
require 'rafini/integer'
|
2
|
+
require 'rafini/hash'
|
3
|
+
|
1
4
|
module Rafini
|
2
5
|
module Odometers
|
3
|
-
|
4
|
-
|
6
|
+
# Sidereal Year: https://en.wikipedia.org/wiki/Year
|
7
|
+
year = 365*24*60*60 + 6*60*60 + 9*60 + 9.76
|
8
|
+
SEC2TIME = { # levels
|
9
|
+
second: 1,
|
5
10
|
minute: 60,
|
6
|
-
hour:
|
7
|
-
day:
|
8
|
-
week:
|
9
|
-
month:
|
10
|
-
year:
|
11
|
-
decade: 10,
|
12
|
-
centurie:
|
13
|
-
millennium:
|
14
|
-
age:
|
15
|
-
epoch:
|
16
|
-
era:
|
17
|
-
eon:
|
18
|
-
gigaannum:
|
11
|
+
hour: 60*60,
|
12
|
+
day: 24*60*60,
|
13
|
+
week: 7*24*60*60,
|
14
|
+
month: year/12.0,
|
15
|
+
year: year,
|
16
|
+
decade: 10*year,
|
17
|
+
centurie: 100*year,
|
18
|
+
millennium: 1_000*year,
|
19
|
+
age: 10_000*year,
|
20
|
+
epoch: 100_000*year,
|
21
|
+
era: 1_000_000*year,
|
22
|
+
eon: 5_000_000*year,
|
23
|
+
gigaannum: 10_000_000*year,
|
19
24
|
}
|
20
25
|
|
21
|
-
SCALE = {
|
26
|
+
SCALE = { # levels
|
22
27
|
base: {
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
28
|
+
one: 1,
|
29
|
+
ten: 10,
|
30
|
+
hundred: 100,
|
31
|
+
thousand: 10**3,
|
32
|
+
million: 10**6,
|
27
33
|
},
|
28
34
|
short: {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
quadrillions: nil,
|
35
|
+
billion: 10**9,
|
36
|
+
trillion: 10**12,
|
37
|
+
quadrillion: 10**15,
|
33
38
|
},
|
34
39
|
long: {
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
quadrillions: nil,
|
40
|
+
billion: 10**12,
|
41
|
+
trillion: 10**18,
|
42
|
+
quadrillion: 10**24,
|
39
43
|
},
|
40
44
|
}
|
41
45
|
|
42
|
-
refine ::
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
values = scale.values
|
50
|
-
keys = scale.keys;
|
51
|
-
counts = self.odometer(*values[0..-2])
|
52
|
-
|
53
|
-
string = "#{counts[0]} #{keys[0]}#{(counts[0]==1)? '' : 's'}"
|
54
|
-
(keys.length-1).downto(1) do |i|
|
55
|
-
if counts[i] > 0
|
56
|
-
string = "#{counts[i]} #{keys[i]}#{(counts[i]>1)? 's' : ''}"
|
57
|
-
string << " and #{counts[i-1]} #{keys[i-1]}#{(counts[i-1]>1)? 's' : ''}" if counts[i-1]>0
|
46
|
+
refine ::Hash do
|
47
|
+
def description
|
48
|
+
string = ''
|
49
|
+
reverse_each do |key, count|
|
50
|
+
s = (count==1)? '' : 's'
|
51
|
+
unless string.empty?
|
52
|
+
string << " and #{count} #{key}#{s}" if count > 0
|
58
53
|
break
|
59
54
|
end
|
55
|
+
next if count == 0
|
56
|
+
string << "#{count} #{key}#{s}"
|
60
57
|
end
|
58
|
+
return string
|
59
|
+
end
|
60
|
+
end
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
refine ::Integer do
|
63
|
+
using Rafini::Integer # Need Rafini::Integer for #odometer
|
64
|
+
using Rafini::Hash # Need Rafini::Hash for #to_struct
|
65
65
|
|
66
|
-
|
66
|
+
def odoread(scale, **kw, &blk)
|
67
|
+
counts = odometer(*scale.values, **kw)
|
68
|
+
::Hash[scale.keys.zip(counts)].to_struct(&blk)
|
67
69
|
end
|
68
70
|
|
69
71
|
# Integer#sec2time
|
70
72
|
# Returns a struct with the different time scales for number of seconds.
|
71
|
-
# Note that the month(4 weeks)/year(13 months) are not meant to be exact.
|
72
73
|
# 10_000.sec2time.to_s #=> "2 hours and 46 minutes"
|
73
74
|
# 10_000.sec2time.hour #=> 2
|
74
75
|
def sec2time
|
75
|
-
|
76
|
+
odoread(SEC2TIME, factors:false) do
|
77
|
+
def to_s
|
78
|
+
string = nil
|
79
|
+
SEC2TIME.keys.reverse_each do |key|
|
80
|
+
count=self[key]
|
81
|
+
if string
|
82
|
+
if count > 0
|
83
|
+
string << " and #{count} #{key}"
|
84
|
+
string << 's' if count > 1
|
85
|
+
end
|
86
|
+
break
|
87
|
+
end
|
88
|
+
next if count==0
|
89
|
+
string = "#{count} #{key}"
|
90
|
+
string << 's' if count > 1
|
91
|
+
end
|
92
|
+
string = "0 #{SEC2TIME.first[0]}s" unless string
|
93
|
+
string
|
94
|
+
end
|
95
|
+
def to_i
|
96
|
+
SEC2TIME.to_a.map{|k,v|v*self[k]}.sum.round
|
97
|
+
end
|
98
|
+
end
|
76
99
|
end
|
77
100
|
|
78
101
|
# 1_230.illion.to_s #=> "1.23k"
|
@@ -91,37 +114,42 @@ module Rafini
|
|
91
114
|
# m.quadrillions #=> 888
|
92
115
|
# m.to_s #=> "888Q" It rounds up 888.7!
|
93
116
|
def illion(type=:short)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
n = counts[i]
|
109
|
-
if n < 1_000
|
110
|
-
d = (n<10)? 2 : (n<100)? 1 : 0
|
111
|
-
n = (n + counts[i-1]/values[i-1].to_f).round(d)
|
112
|
-
else
|
113
|
-
n = n.illion
|
117
|
+
scale = SCALE[:base].merge SCALE[type]
|
118
|
+
struct = odoread(scale, factors:false) do
|
119
|
+
def scale=(scale)
|
120
|
+
@scale=scale
|
121
|
+
end
|
122
|
+
def type=(type)
|
123
|
+
@type=type
|
124
|
+
end
|
125
|
+
def to_s
|
126
|
+
number = to_i
|
127
|
+
return number.to_s if number < 1_000
|
128
|
+
if number < 1_000_000
|
129
|
+
precision = (number<10_000)? 2 : (number<100_000)? 1 : 0
|
130
|
+
return "#{(number/1000.0).round(precision)}K"
|
114
131
|
end
|
115
|
-
|
116
|
-
|
132
|
+
keys = @scale.keys.reverse_each
|
133
|
+
loop do
|
134
|
+
key = keys.next
|
135
|
+
n = self[key]
|
136
|
+
next if n == 0
|
137
|
+
if n < 1_000
|
138
|
+
precision = (n<10)? 2 : (n<100)? 1 : 0
|
139
|
+
scale = @scale[key].to_f
|
140
|
+
f = (number/scale).round(precision)
|
141
|
+
return "#{f}#{key[0].upcase}"
|
142
|
+
end
|
143
|
+
return "#{n.illion}#{key[0].upcase}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
def to_i
|
147
|
+
@scale.to_a.map{|k,v|v*self[k]}.sum
|
117
148
|
end
|
118
149
|
end
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
hash[:to_s] = string
|
123
|
-
|
124
|
-
return hash.to_struct
|
150
|
+
struct.type = type
|
151
|
+
struct.scale = scale
|
152
|
+
return struct
|
125
153
|
end
|
126
154
|
end
|
127
155
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Rafini
|
2
|
+
module Requires
|
3
|
+
refine ::String do
|
4
|
+
# satisfies?:
|
5
|
+
# "1.2.3".satisfies?('~>1.1') #=> true
|
6
|
+
# "1.2.3".satisfies?('~>2.3') #=> false
|
7
|
+
def satisfies?(*reqs)
|
8
|
+
Gem::Requirement.new(*reqs).satisfied_by? Gem::Version.new(self)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
refine ::Kernel do
|
13
|
+
def requires(*list)
|
14
|
+
loaded = []
|
15
|
+
list.each do |gems|
|
16
|
+
gems.lines.each do |gemname_reqs|
|
17
|
+
gemname, *reqs = gemname_reqs.split
|
18
|
+
next unless gemname
|
19
|
+
unless reqs.empty?
|
20
|
+
case gemname
|
21
|
+
when 'rafini'
|
22
|
+
unless VERSION.satisfies?(*reqs)
|
23
|
+
raise "helpema #{VERSION} not #{reqs.join(', ')}"
|
24
|
+
end
|
25
|
+
next
|
26
|
+
when 'ruby'
|
27
|
+
unless RUBY_VERSION.satisfies?(*reqs)
|
28
|
+
raise "ruby #{RUBY_VERSION} not #{reqs.join(', ')}"
|
29
|
+
end
|
30
|
+
next
|
31
|
+
else
|
32
|
+
gem gemname, *reqs
|
33
|
+
end
|
34
|
+
end
|
35
|
+
require gemname and loaded.push gemname
|
36
|
+
end
|
37
|
+
end
|
38
|
+
return loaded
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/rafini/string.rb
CHANGED
@@ -4,17 +4,24 @@ module Rafini
|
|
4
4
|
# camelize:
|
5
5
|
# 1) A camel kick, as in "I gotz camelized".
|
6
6
|
# 2) "a_camel_kick" => "ACamelKick"
|
7
|
-
def camelize(sep
|
8
|
-
self.split(sep).map
|
7
|
+
def camelize(sep='_')
|
8
|
+
self.split(sep).map(&:capitalize).join
|
9
9
|
end
|
10
10
|
|
11
11
|
# semantic:
|
12
12
|
# 'a.b.c'.semantic(1) #=> 'b'
|
13
13
|
# 'a.b.c'.semantic(0..1) #=> 'a.b'
|
14
|
-
# 'a.b.c'.semantic(0..2, '/') #=> 'b/c'
|
15
|
-
# 'a/b/c'.semantic(0..2, '
|
16
|
-
def semantic(v,
|
17
|
-
[*self.split(
|
14
|
+
# 'a.b.c'.semantic(0..2, join:'/') #=> 'b/c'
|
15
|
+
# 'a/b/c'.semantic(0..2, split:'/', join:'.') #=> 'a.b.c'
|
16
|
+
def semantic(v=(0..2), split:'.', join:'.')
|
17
|
+
[*self.split(split)[v]].join(join)
|
18
|
+
end
|
19
|
+
|
20
|
+
# shellescape:
|
21
|
+
# Same funtionality as Shellword's String#shellescape
|
22
|
+
def shellescape
|
23
|
+
# This is a contraction of Shellwords.escape function
|
24
|
+
self.gsub(/[^\w\-.,:+\/@\n]/,'\\\\\\&').gsub(/\n/,"'\n'")
|
18
25
|
end
|
19
26
|
end
|
20
27
|
end
|
data/lib/rafini.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
module Rafini
|
2
|
-
VERSION = '
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
VERSION = '3.1.221212'
|
3
|
+
# Constants
|
4
|
+
autoload :Empty, 'rafini/empty'
|
5
|
+
# Pure
|
6
|
+
autoload :Array, 'rafini/array'
|
7
|
+
autoload :Hash, 'rafini/hash'
|
8
|
+
autoload :Integer, 'rafini/integer'
|
9
|
+
autoload :String, 'rafini/string'
|
10
|
+
# Hybrid
|
11
|
+
autoload :Exception, 'rafini/exception'
|
12
|
+
# Mix
|
13
|
+
autoload :Odometers, 'rafini/odometers'
|
14
|
+
autoload :Requires, 'rafini/requires'
|
10
15
|
end
|
11
16
|
# Requires:
|
12
17
|
#`ruby`
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rafini
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.1.221212
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- CarlosJHR64
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 'Just a collection of useful refinements.
|
14
14
|
|
@@ -26,6 +26,7 @@ files:
|
|
26
26
|
- lib/rafini/hash.rb
|
27
27
|
- lib/rafini/integer.rb
|
28
28
|
- lib/rafini/odometers.rb
|
29
|
+
- lib/rafini/requires.rb
|
29
30
|
- lib/rafini/string.rb
|
30
31
|
homepage: https://github.com/carlosjhr64/rafini
|
31
32
|
licenses:
|
@@ -46,8 +47,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
47
|
- !ruby/object:Gem::Version
|
47
48
|
version: '0'
|
48
49
|
requirements:
|
49
|
-
- 'ruby: ruby
|
50
|
-
rubygems_version: 3.
|
50
|
+
- 'ruby: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [aarch64-linux]'
|
51
|
+
rubygems_version: 3.3.7
|
51
52
|
signing_key:
|
52
53
|
specification_version: 4
|
53
54
|
summary: Just a collection of useful refinements.
|