bblib 2.0.3 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/bblib/cli/option.rb +9 -9
- data/lib/bblib/cli/options/basic_option.rb +3 -3
- data/lib/bblib/cli/options/command.rb +1 -1
- data/lib/bblib/cli/options/element_of.rb +24 -0
- data/lib/bblib/cli/options/toggle.rb +2 -2
- data/lib/bblib/cli/opts_parser.rb +2 -1
- data/lib/bblib/core.rb +2 -0
- data/lib/bblib/core/classes/hash_struct.rb +3 -2
- data/lib/bblib/core/hash_path/hash_path.rb +1 -1
- data/lib/bblib/core/hash_path/part.rb +8 -0
- data/lib/bblib/core/mixins/numeric_enhancements.rb +42 -0
- data/lib/bblib/core/util/number.rb +2 -22
- data/lib/bblib/core/util/object.rb +56 -4
- data/lib/bblib/core/util/time.rb +1 -1
- data/lib/bblib/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2470d8a875c6066b41bcb55d580db671e5569cfe69c13241f46a7015a4f87d5
|
4
|
+
data.tar.gz: 797a23d1cc99ec3bab8d6945cd03137c1889b96a1ff5279feb07c3e4e445f4a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdbf6f7993ad6eea502e05d30d4d97a7997d815459b5816164d2d080d6292f7c3b80c31a04916785ea3afd29e92c45a797dcb728dbbe00c7fa62d26436220149
|
7
|
+
data.tar.gz: 27bfbbc391b6bd4dc92c6681fc239b7350848be6d1c0f6731a384bab266335058909fe19e9463e8c528eb77d24359580652e5f7182e232d2c51467c43ab848c4
|
data/lib/bblib/cli/option.rb
CHANGED
@@ -19,7 +19,6 @@ module BBLib
|
|
19
19
|
attr_of [Integer, Range], :position, default: nil, allow_nil: true
|
20
20
|
attr_hash :sub_commands, keys: String, values: OptsParser, aliases: [:sub_cmds, :subcommands], default: nil, allow_nil: true, pre_proc: proc { |hash| hash.is_a?(Hash) ? hash.keys_to_s : hash }
|
21
21
|
|
22
|
-
|
23
22
|
def to_s
|
24
23
|
(flags.sort_by(&:size).join(', ') + " #{placeholder}").strip.ljust(40, ' ') + "\t#{description}"
|
25
24
|
end
|
@@ -29,35 +28,36 @@ module BBLib
|
|
29
28
|
end
|
30
29
|
|
31
30
|
def retrieve(args, parsed)
|
32
|
-
result =
|
31
|
+
result = multi_value? ? [] : nil
|
33
32
|
index = 0
|
34
33
|
until index >= args.size
|
35
34
|
begin
|
36
|
-
|
35
|
+
if args[index].nil? || !flag_match?(args[index].to_s, index)
|
37
36
|
index += 1
|
38
37
|
next
|
39
38
|
end
|
40
39
|
values = split(extract(index, args))
|
41
40
|
values.each do |value|
|
42
41
|
valid!(value)
|
43
|
-
if
|
44
|
-
result = value
|
45
|
-
index = args.size
|
46
|
-
else
|
42
|
+
if multi_value?
|
47
43
|
result << value
|
44
|
+
else
|
45
|
+
result = value
|
48
46
|
end
|
47
|
+
index = args.size if singular?
|
49
48
|
end
|
50
49
|
rescue OptsParserException => e
|
51
50
|
raise e if raise_errors?
|
52
51
|
end
|
52
|
+
index += 1
|
53
53
|
end
|
54
54
|
raise MissingArgumentException, "A required argument is missing: #{name}" if required? && result.nil?
|
55
55
|
result = processor.call(result) if !result.nil? && processor
|
56
56
|
process_result(result.nil? ? default : result, args, parsed)
|
57
57
|
end
|
58
58
|
|
59
|
-
def
|
60
|
-
singular
|
59
|
+
def multi_value?
|
60
|
+
!singular || delimiter
|
61
61
|
end
|
62
62
|
|
63
63
|
def flag_match?(str, index = 0)
|
@@ -3,9 +3,9 @@ module BBLib
|
|
3
3
|
class BasicOption < Option
|
4
4
|
|
5
5
|
def extract(index, args)
|
6
|
-
args
|
7
|
-
raise MissingArgumentException, "No argument was provided for #{name}" if args[index].nil?
|
8
|
-
format_value(args.
|
6
|
+
args[index] = nil
|
7
|
+
raise MissingArgumentException, "No argument was provided for #{name}" if args[index + 1].nil?
|
8
|
+
format_value(args[index + 1].tap { args[index + 1] = nil })
|
9
9
|
end
|
10
10
|
|
11
11
|
protected
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module BBLib
|
2
|
+
class OptsParser
|
3
|
+
class ElementOf < BasicOption
|
4
|
+
|
5
|
+
attr_ary :options, aliases: :opts
|
6
|
+
attr_of Proc, :comparitor, default: proc { |opt, val| opt == val }
|
7
|
+
|
8
|
+
def valid?(value)
|
9
|
+
return false unless options.any? { |opt| comparitor.call(opt, value) }
|
10
|
+
return true if validators.empty?
|
11
|
+
validators.all? do |validator|
|
12
|
+
validator.call(value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def format_value(value)
|
19
|
+
value.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -4,8 +4,8 @@ module BBLib
|
|
4
4
|
|
5
5
|
def extract(index, args)
|
6
6
|
value = args[index].to_s
|
7
|
-
if value =~ /^\-[\w\d]
|
8
|
-
args
|
7
|
+
if value =~ /^\-[\w\d]$|^\-{2}/ || flags.include?(value)
|
8
|
+
args[index] = nil
|
9
9
|
elsif value =~ /^\-[\w\d]+$/
|
10
10
|
flag = flags.find do |flag|
|
11
11
|
next unless flag =~ /^\-[\w\d]$/
|
@@ -13,6 +13,7 @@ require_relative 'options/regexp'
|
|
13
13
|
require_relative 'options/symbol'
|
14
14
|
require_relative 'options/toggle'
|
15
15
|
require_relative 'options/untoggle'
|
16
|
+
require_relative 'options/element_of'
|
16
17
|
|
17
18
|
module BBLib
|
18
19
|
class OptsParser
|
@@ -49,7 +50,7 @@ module BBLib
|
|
49
50
|
options.sort_by { |opt| opt.position || 10**100 }.each do |option|
|
50
51
|
option.retrieve(args, hash)
|
51
52
|
end
|
52
|
-
end.merge(arguments: args)
|
53
|
+
end.merge(arguments: args.compact)
|
53
54
|
end
|
54
55
|
|
55
56
|
def help
|
data/lib/bblib/core.rb
CHANGED
@@ -28,6 +28,8 @@ require_relative 'core/util/array'
|
|
28
28
|
require_relative 'core/util/logging'
|
29
29
|
require_relative 'core/util/os'
|
30
30
|
|
31
|
+
require_relative 'core/mixins/numeric_enhancements'
|
32
|
+
|
31
33
|
require_relative 'core/classes/hash_struct'
|
32
34
|
require_relative 'core/classes/task_timer'
|
33
35
|
require_relative 'core/classes/tree_hash'
|
@@ -35,7 +35,8 @@ module BBLib
|
|
35
35
|
end
|
36
36
|
|
37
37
|
class Hash
|
38
|
-
def to_hash_struct
|
39
|
-
|
38
|
+
def to_hash_struct(recursive = true)
|
39
|
+
hash = recursive ? self.hmap { |k, v| [k, v.respond_to?(:to_hash_struct) ? v.to_hash_struct(recursive) : v] } : self
|
40
|
+
BBLib::HashStruct.new.merge(hash)
|
40
41
|
end
|
41
42
|
end
|
@@ -44,7 +44,7 @@ end
|
|
44
44
|
|
45
45
|
module BBLib
|
46
46
|
def self.hash_path(hash, *paths, multi_path: false, multi_join: false, multi_join_hash: false)
|
47
|
-
tree = TreeHash.new(hash
|
47
|
+
tree = TreeHash.new(hash)
|
48
48
|
if multi_path
|
49
49
|
tree.find_multi(*paths).map { |r| r.map { |sr| sr.value } }
|
50
50
|
elsif multi_join
|
@@ -47,6 +47,14 @@ class HashPath
|
|
47
47
|
matches << v if key_match?(k, object) && evaluates?(v)
|
48
48
|
matches += matches(v) if recursive? && v.children?
|
49
49
|
end
|
50
|
+
else
|
51
|
+
casted = case
|
52
|
+
when !object.value.is_a?(Hash) && !object.value.is_a?(Array) && object.value.respond_to?(:to_tree_hash) && object.method(:to_tree_hash).arity <= 0
|
53
|
+
object.value.to_tree_hash
|
54
|
+
when object.value.is_a?(BBLib::Effortless)
|
55
|
+
object.value.serialize.to_tree_hash
|
56
|
+
end
|
57
|
+
matches += matches(casted) if casted
|
50
58
|
end
|
51
59
|
matches
|
52
60
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module BBLib
|
2
|
+
# This module contains methods that are intended to be mixed in to
|
3
|
+
# Integer and Float classes. They mostly provide convenience methods.
|
4
|
+
module NumericEnhancements
|
5
|
+
|
6
|
+
# Create a method for all types of times. Makes it easy
|
7
|
+
# to convert to any range of seconds. e.g. 5.hours returns 3600
|
8
|
+
TIME_EXPS.each do |name, data|
|
9
|
+
[name, name.to_s.pluralize].each do |method|
|
10
|
+
define_method(method) {
|
11
|
+
(self * data[:mult]) / 1000
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Converts a number to english (only language supported currently)
|
17
|
+
# For example, 501.spell_out returns 'five hundred and one'
|
18
|
+
def spell_out(include_and: true)
|
19
|
+
BBLib.number_spelled_out(self, include_and: include_and)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Convert this integer into a string with every three digits separated by a delimiter
|
23
|
+
# on the left side of the decimal
|
24
|
+
def to_delimited_s(delim = ',')
|
25
|
+
split = self.to_s.split('.')
|
26
|
+
split[0] = split.first.reverse.gsub(/(\d{3})/, "\\1#{delim}").reverse
|
27
|
+
split.join('.').uncapsulate(',')
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the time x seconds ago from now (x == this number)
|
31
|
+
def ago
|
32
|
+
Time.now - self
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the time x seconds ago from now (x == this number)
|
36
|
+
def from_now
|
37
|
+
Time.now + self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Numeric.send(:include, NumericEnhancements)
|
42
|
+
end
|
@@ -57,6 +57,7 @@ module BBLib
|
|
57
57
|
]
|
58
58
|
}
|
59
59
|
|
60
|
+
# TODO: Support floats eventually?
|
60
61
|
def self.number_spelled_out(number, range = 0, include_and: true)
|
61
62
|
number = number.to_i
|
62
63
|
negative = number.negative?
|
@@ -73,7 +74,7 @@ module BBLib
|
|
73
74
|
when 100..999
|
74
75
|
str << NUMBER_WORDS[:special][three_digit.to_s[0].to_i]
|
75
76
|
str << 'hundred'
|
76
|
-
str << 'and' if include_and
|
77
|
+
str << 'and' if include_and && !three_digit.to_s.end_with?('00')
|
77
78
|
if three_digit.to_s[-2].to_i == 1
|
78
79
|
str << NUMBER_WORDS[:special][three_digit.to_s[-2..-1].to_i]
|
79
80
|
else
|
@@ -87,24 +88,3 @@ module BBLib
|
|
87
88
|
str.compact.join(' ')).gsub(/\s+/, ' ')
|
88
89
|
end
|
89
90
|
end
|
90
|
-
|
91
|
-
class Integer
|
92
|
-
# Convert this integer into a string with every three digits separated by a delimiter
|
93
|
-
def to_delimited_s(delim = ',')
|
94
|
-
self.to_s.reverse.gsub(/(\d{3})/, "\\1#{delim}").reverse.uncapsulate(',')
|
95
|
-
end
|
96
|
-
|
97
|
-
def spell_out
|
98
|
-
BBLib.number_spelled_out(self)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
class Float
|
103
|
-
# Convert this integer into a string with every three digits separated by a delimiter
|
104
|
-
# on the left side of the decimal
|
105
|
-
def to_delimited_s(delim = ',')
|
106
|
-
split = self.to_s.split('.')
|
107
|
-
split[0] = split.first.reverse.gsub(/(\d{3})/, "\\1#{delim}").reverse
|
108
|
-
split.join('.').uncapsulate(',')
|
109
|
-
end
|
110
|
-
end
|
@@ -1,10 +1,17 @@
|
|
1
1
|
module BBLib
|
2
|
-
|
3
|
-
|
2
|
+
# Easy way to see if all objects in an array are of a given class.
|
3
|
+
def self.are_all?(klass, *objects)
|
4
|
+
objects.all? { |object| object.is_a?(klass) }
|
4
5
|
end
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
# Easy way to see if any of the passed objects are of the given class.
|
8
|
+
def self.are_any?(klass, *objects)
|
9
|
+
objects.any? { |object| object.is_a?(klass) }
|
10
|
+
end
|
11
|
+
|
12
|
+
# Checks to see if an object is of any of the given classes.
|
13
|
+
def self.is_any?(object, *klasses)
|
14
|
+
klasses.any? { |klass| object.is_a?(klass) }
|
8
15
|
end
|
9
16
|
|
10
17
|
# Takes any type of object and converts it into a hash based on its instance
|
@@ -34,10 +41,14 @@ module BBLib
|
|
34
41
|
hash
|
35
42
|
end
|
36
43
|
|
44
|
+
# Extracts all hash based arguments from an ary of arguments. Only hash pairs with
|
45
|
+
# a symbol as the key are returned. Use hash_args if you also want to treat
|
46
|
+
# String keys as named arguments.
|
37
47
|
def self.named_args(*args)
|
38
48
|
args.last.is_a?(Hash) && args.last.keys.all? { |k| k.is_a?(Symbol) } ? args.last : {}
|
39
49
|
end
|
40
50
|
|
51
|
+
# Same as standard named_args but removes the named arguments from the array.
|
41
52
|
def self.named_args!(*args)
|
42
53
|
if args.last.is_a?(Hash) && args.last.keys.all? { |k| k.is_a?(Symbol) }
|
43
54
|
args.delete_at(-1)
|
@@ -46,10 +57,12 @@ module BBLib
|
|
46
57
|
end
|
47
58
|
end
|
48
59
|
|
60
|
+
# Similar to named_args but also treats String keys as named arguments.
|
49
61
|
def self.hash_args(*args)
|
50
62
|
args.find_all { |a| a.is_a?(Hash) }.each_with_object({}) { |a, h| h.merge!(a) }
|
51
63
|
end
|
52
64
|
|
65
|
+
# Send a chain of methods to an object and each result of the previous method.
|
53
66
|
def self.recursive_send(obj, *methods)
|
54
67
|
methods.each do |args|
|
55
68
|
obj = obj.send(*args)
|
@@ -57,13 +70,52 @@ module BBLib
|
|
57
70
|
obj
|
58
71
|
end
|
59
72
|
|
73
|
+
# Returns the encapsulating object space of a given class.
|
74
|
+
# Ex: For a class called BBLib::String, this method will return BBLib as the namespace.
|
75
|
+
# Ex2: For a class BBLib::String::Char, this method will return BBLib::String as the namespace.
|
60
76
|
def self.namespace_of(klass)
|
61
77
|
split = klass.to_s.split('::')
|
62
78
|
return klass if split.size == 1
|
63
79
|
Object.const_get(split[0..-2].join('::'))
|
64
80
|
end
|
65
81
|
|
82
|
+
# Returns the root namespace of a given class if it is nested.
|
66
83
|
def self.root_namespace_of(klass)
|
67
84
|
Object.const_get(klass.to_s.gsub(/::.*/, ''))
|
68
85
|
end
|
86
|
+
|
87
|
+
# Create a new class or module recursively within a provided namespace. If a
|
88
|
+
# constant matching the requested one already exist it is returned. Any
|
89
|
+
# block passed to this method will be evaled in the created/found constant.
|
90
|
+
def self.const_create(name, value, strict: true, base: Object, type_of_missing: nil, &block)
|
91
|
+
namespace = base
|
92
|
+
unless base.const_defined?(name)
|
93
|
+
type_of_missing = Module unless type_of_missing
|
94
|
+
name = name.uncapsulate('::')
|
95
|
+
if name.include?('::')
|
96
|
+
namespaces = name.split('::')
|
97
|
+
name = namespaces.pop
|
98
|
+
namespaces.each do |constant|
|
99
|
+
unless namespace.const_defined?(constant)
|
100
|
+
match = namespace.const_set(constant, type_of_missing.new)
|
101
|
+
end
|
102
|
+
namespace = namespace.const_get(constant)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
namespace.const_set(name, value)
|
106
|
+
end
|
107
|
+
object = namespace.const_get(name)
|
108
|
+
raise TypeError, "Expected a #{value.class} but #{namespace}::#{name} is a #{object.class}" if strict && object.class != value.class
|
109
|
+
object.tap do |constant|
|
110
|
+
constant.send(:class_exec, &block) if block
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.class_create(name, *args, **opts, &block)
|
115
|
+
const_create(name, Class.new(*args), **opts, &block)
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.module_create(name, *args, **opts, &block)
|
119
|
+
const_create(name, Module.new(*args), **opts, &block)
|
120
|
+
end
|
69
121
|
end
|
data/lib/bblib/core/util/time.rb
CHANGED
data/lib/bblib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bblib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Black
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -99,6 +99,7 @@ files:
|
|
99
99
|
- lib/bblib/cli/options/bool.rb
|
100
100
|
- lib/bblib/cli/options/command.rb
|
101
101
|
- lib/bblib/cli/options/date.rb
|
102
|
+
- lib/bblib/cli/options/element_of.rb
|
102
103
|
- lib/bblib/cli/options/float.rb
|
103
104
|
- lib/bblib/cli/options/integer.rb
|
104
105
|
- lib/bblib/cli/options/json.rb
|
@@ -127,6 +128,7 @@ files:
|
|
127
128
|
- lib/bblib/core/mixins/family_tree.rb
|
128
129
|
- lib/bblib/core/mixins/hooks.rb
|
129
130
|
- lib/bblib/core/mixins/logger.rb
|
131
|
+
- lib/bblib/core/mixins/numeric_enhancements.rb
|
130
132
|
- lib/bblib/core/mixins/prototype.rb
|
131
133
|
- lib/bblib/core/mixins/serializer.rb
|
132
134
|
- lib/bblib/core/mixins/simple_init.rb
|