bblib 1.0.2 → 2.0.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.
- checksums.yaml +4 -4
- data/README.md +502 -8
- data/lib/bblib.rb +1 -28
- data/lib/bblib/all.rb +5 -0
- data/lib/{time → bblib/classes}/cron.rb +0 -0
- data/lib/{string → bblib/classes}/fuzzy_matcher.rb +0 -0
- data/lib/bblib/cli.rb +3 -0
- data/lib/bblib/cli/color.rb +51 -0
- data/lib/bblib/cli/exceptions/invalid_argument.rb +5 -0
- data/lib/bblib/cli/exceptions/missing_argument.rb +5 -0
- data/lib/bblib/cli/exceptions/missing_required_argument.rb +5 -0
- data/lib/bblib/cli/exceptions/opts_parser.rb +9 -0
- data/lib/bblib/cli/option.rb +116 -0
- data/lib/bblib/cli/options/basic_option.rb +19 -0
- data/lib/bblib/cli/options/bool.rb +19 -0
- data/lib/bblib/cli/options/command.rb +11 -0
- data/lib/bblib/cli/options/date.rb +14 -0
- data/lib/bblib/cli/options/float.rb +14 -0
- data/lib/bblib/cli/options/integer.rb +14 -0
- data/lib/bblib/cli/options/json.rb +16 -0
- data/lib/bblib/cli/options/regexp.rb +17 -0
- data/lib/bblib/cli/options/string.rb +13 -0
- data/lib/bblib/cli/options/symbol.rb +13 -0
- data/lib/bblib/cli/options/time.rb +14 -0
- data/lib/bblib/cli/options/toggle.rb +27 -0
- data/lib/bblib/cli/options/untoggle.rb +18 -0
- data/lib/bblib/cli/opts_parser.rb +65 -0
- data/lib/bblib/core.rb +37 -0
- data/lib/{hash → bblib/core/classes}/hash_struct.rb +9 -2
- data/lib/bblib/core/classes/splitter.rb +101 -0
- data/lib/{time → bblib/core/classes}/task_timer.rb +0 -0
- data/lib/{hash → bblib/core/classes}/tree_hash.rb +22 -22
- data/lib/bblib/core/exceptions/abstract.rb +3 -0
- data/lib/bblib/core/exceptions/exception.rb +5 -0
- data/lib/{hash_path → bblib/core/hash_path}/hash_path.rb +0 -2
- data/lib/{hash_path → bblib/core/hash_path}/part.rb +0 -0
- data/lib/{mixins → bblib/core/mixins}/attrs.rb +17 -7
- data/lib/{mixins → bblib/core/mixins}/bbmixins.rb +1 -0
- data/lib/{mixins → bblib/core/mixins}/bridge.rb +0 -0
- data/lib/bblib/core/mixins/delegator.rb +90 -0
- data/lib/{class → bblib/core/mixins}/effortless.rb +0 -0
- data/lib/{mixins → bblib/core/mixins}/family_tree.rb +1 -1
- data/lib/{mixins → bblib/core/mixins}/hooks.rb +0 -0
- data/lib/{mixins → bblib/core/mixins}/logger.rb +0 -0
- data/lib/{mixins → bblib/core/mixins}/prototype.rb +0 -0
- data/lib/{mixins → bblib/core/mixins}/serializer.rb +0 -0
- data/lib/{mixins → bblib/core/mixins}/simple_init.rb +41 -3
- data/lib/{mixins → bblib/core/mixins}/type_init.rb +0 -0
- data/lib/{array/bbarray.rb → bblib/core/util/array.rb} +0 -0
- data/lib/{string → bblib/core/util}/cases.rb +0 -0
- data/lib/{file/bbfile.rb → bblib/core/util/file.rb} +31 -7
- data/lib/{hash/bbhash.rb → bblib/core/util/hash.rb} +0 -3
- data/lib/{logging/bblogging.rb → bblib/core/util/logging.rb} +11 -2
- data/lib/{string → bblib/core/util}/matching.rb +0 -0
- data/lib/{number/bbnumber.rb → bblib/core/util/number.rb} +0 -0
- data/lib/{object/bbobject.rb → bblib/core/util/object.rb} +2 -0
- data/lib/{opal/bbopal.rb → bblib/core/util/opal.rb} +0 -0
- data/lib/{os/bbos.rb → bblib/core/util/os.rb} +0 -0
- data/lib/{string → bblib/core/util}/pluralization.rb +0 -0
- data/lib/{string → bblib/core/util}/regexp.rb +0 -0
- data/lib/{string → bblib/core/util}/roman.rb +0 -0
- data/lib/{string/bbstring.rb → bblib/core/util/string.rb} +18 -24
- data/lib/{time/bbtime.rb → bblib/core/util/time.rb} +1 -5
- data/lib/bblib/cron.rb +2 -0
- data/lib/bblib/fuzzy_matcher.rb +2 -0
- data/lib/bblib/html.rb +4 -0
- data/lib/{html → bblib/html}/builder.rb +0 -0
- data/lib/{html → bblib/html}/tag.rb +0 -0
- data/lib/{html → bblib/html}/tag_set.rb +0 -0
- data/lib/bblib/system.rb +3 -0
- data/lib/bblib/system/command.rb +7 -0
- data/lib/bblib/system/system.rb +39 -0
- data/lib/bblib/version.rb +1 -1
- metadata +71 -44
- data/lib/error/abstract.rb +0 -3
- data/lib/hash_path/path_hash.rb +0 -84
- data/lib/hash_path/proc.rb +0 -93
- data/lib/hash_path/processors.rb +0 -239
- data/lib/html/bbhtml.rb +0 -3
- data/lib/system/bbsystem.rb +0 -42
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require_relative 'option'
|
|
2
|
+
require_relative 'exceptions/opts_parser'
|
|
3
|
+
require_relative 'options/basic_option'
|
|
4
|
+
|
|
5
|
+
BBLib.scan_files(File.expand_path('../options', __FILE__), '*.rb') do |file|
|
|
6
|
+
require_relative file
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module BBLib
|
|
10
|
+
class OptsParser
|
|
11
|
+
include BBLib::Effortless
|
|
12
|
+
|
|
13
|
+
attr_ary_of Option, :options, add_rem: true
|
|
14
|
+
attr_str :usage, default: nil, allow_nil: true
|
|
15
|
+
|
|
16
|
+
def usage(text = nil)
|
|
17
|
+
@usage = text unless text.nil?
|
|
18
|
+
@usage
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def on(*flags, **opts, &block)
|
|
22
|
+
opts[:type] = :string unless opts[:type]
|
|
23
|
+
add_options(opts.merge(flags: flags, processor: block))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def parse(args = ARGV)
|
|
27
|
+
parse!(args.dup)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def parse!(args = ARGV)
|
|
31
|
+
HashStruct.new.tap do |hash|
|
|
32
|
+
options.each do |option|
|
|
33
|
+
option.retrieve(args, hash)
|
|
34
|
+
end
|
|
35
|
+
end.merge(arguments: args)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def help
|
|
39
|
+
usage.to_s + "\n\t" +
|
|
40
|
+
options.join("\n\t")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def to_s
|
|
44
|
+
help
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
protected
|
|
48
|
+
|
|
49
|
+
def method_missing(method, *args, &block)
|
|
50
|
+
if Option.types.include?(method)
|
|
51
|
+
define_singleton_method(method) do |*flags, **opts, &block|
|
|
52
|
+
on(*flags, **opts.merge(type: method), &block)
|
|
53
|
+
end
|
|
54
|
+
send(method, *args, &block)
|
|
55
|
+
else
|
|
56
|
+
super
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def respond_to_missing?(method, include_private = false)
|
|
61
|
+
Option.types.include?(method) || super
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/bblib/core.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require_relative 'version'
|
|
2
|
+
|
|
3
|
+
require_relative 'core/exceptions/exception'
|
|
4
|
+
|
|
5
|
+
require_relative 'core/util/opal'
|
|
6
|
+
require_relative 'core/util/object'
|
|
7
|
+
require_relative 'core/util/hash'
|
|
8
|
+
|
|
9
|
+
require_relative 'core/mixins/simple_init'
|
|
10
|
+
require_relative 'core/mixins/attrs'
|
|
11
|
+
require_relative 'core/mixins/family_tree'
|
|
12
|
+
require_relative 'core/mixins/hooks'
|
|
13
|
+
require_relative 'core/mixins/serializer'
|
|
14
|
+
require_relative 'core/mixins/logger'
|
|
15
|
+
require_relative 'core/mixins/bridge'
|
|
16
|
+
require_relative 'core/mixins/effortless'
|
|
17
|
+
require_relative 'core/mixins/prototype'
|
|
18
|
+
require_relative 'core/mixins/type_init'
|
|
19
|
+
require_relative 'core/mixins/delegator'
|
|
20
|
+
|
|
21
|
+
require_relative 'core/hash_path/hash_path'
|
|
22
|
+
|
|
23
|
+
require_relative 'core/util/string'
|
|
24
|
+
require_relative 'core/util/file'
|
|
25
|
+
require_relative 'core/util/time'
|
|
26
|
+
require_relative 'core/util/number'
|
|
27
|
+
require_relative 'core/util/array'
|
|
28
|
+
require_relative 'core/util/logging'
|
|
29
|
+
require_relative 'core/util/os'
|
|
30
|
+
|
|
31
|
+
require_relative 'core/classes/hash_struct'
|
|
32
|
+
require_relative 'core/classes/task_timer'
|
|
33
|
+
require_relative 'core/classes/tree_hash'
|
|
34
|
+
require_relative 'core/classes/splitter'
|
|
35
|
+
|
|
36
|
+
require 'fileutils'
|
|
37
|
+
require 'time'
|
|
@@ -7,10 +7,17 @@ module BBLib
|
|
|
7
7
|
|
|
8
8
|
def method_missing(method, *args, &block)
|
|
9
9
|
if args.empty? && ![:to_ary].include?(method)
|
|
10
|
-
|
|
10
|
+
if method.to_s.end_with?('?')
|
|
11
|
+
define_singleton_method(method) do
|
|
12
|
+
self[method[0..-2].to_sym] ? true : false
|
|
13
|
+
end
|
|
14
|
+
send(method)
|
|
15
|
+
else
|
|
16
|
+
define_singleton_method(method) do
|
|
17
|
+
self[method]
|
|
18
|
+
end
|
|
11
19
|
self[method]
|
|
12
20
|
end
|
|
13
|
-
self[method]
|
|
14
21
|
elsif method.to_s.end_with?('=')
|
|
15
22
|
define_singleton_method(method) do |arg|
|
|
16
23
|
self[method[0..-2].to_sym] = arg
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module BBLib
|
|
2
|
+
class Splitter
|
|
3
|
+
include BBLib::Effortless
|
|
4
|
+
|
|
5
|
+
attr_hash :expressions, required: true, pre_proc: :process_expressions
|
|
6
|
+
attr_ary_of [String, Regexp], :delimiters, required: true
|
|
7
|
+
|
|
8
|
+
attr_bool :inside, default: false
|
|
9
|
+
attr_int :current_start, :current_depth, default: 0
|
|
10
|
+
attr_of [String, Symbol, Regexp], :current_expression, allow_nil: true
|
|
11
|
+
attr_str :current_match, :current_delimiter_match, :current_expression_match, allow_nil: true, default: nil
|
|
12
|
+
attr_str :part, default: ''
|
|
13
|
+
attr_bool :ignore_escaped_chars, default: true
|
|
14
|
+
attr_bool :escaped, default: false
|
|
15
|
+
attr_str :escape_char, default: '\\'
|
|
16
|
+
|
|
17
|
+
def self.split(string, *delimiters, **opts)
|
|
18
|
+
new(opts.except(:count).merge(delimiters: delimiters)).split(string, opts.delete(:count))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def split(string, count = nil)
|
|
22
|
+
return string if count == 1
|
|
23
|
+
index = 0
|
|
24
|
+
splits = 1
|
|
25
|
+
[].tap do |array|
|
|
26
|
+
until index >= string.size
|
|
27
|
+
sub_string = string[index..-1]
|
|
28
|
+
escaped = string[index - 1] == escape_char if ignore_escaped_chars?
|
|
29
|
+
|
|
30
|
+
if inside?
|
|
31
|
+
open_match = match(sub_string, current_expression)
|
|
32
|
+
close_match = match(sub_string, expressions[current_expression])
|
|
33
|
+
if current_start != index && close_match && !escaped
|
|
34
|
+
self.inside = false if (self.current_depth -= 1).zero?
|
|
35
|
+
elsif open_match && !escaped
|
|
36
|
+
self.current_depth += 1
|
|
37
|
+
self.part += open_match
|
|
38
|
+
index += open_match.size
|
|
39
|
+
next
|
|
40
|
+
end
|
|
41
|
+
elsif expression = check_expressions(sub_string)
|
|
42
|
+
self.inside = true
|
|
43
|
+
self.current_start = index
|
|
44
|
+
self.current_expression = expression
|
|
45
|
+
self.current_depth += 1
|
|
46
|
+
self.part += current_expression_match
|
|
47
|
+
index += current_expression_match.size
|
|
48
|
+
next
|
|
49
|
+
elsif !escaped? && (count.nil? || splits < count) && delimiter_check(sub_string)
|
|
50
|
+
array << self.part
|
|
51
|
+
splits += 1
|
|
52
|
+
self.part = ''
|
|
53
|
+
index += current_delimiter_match.size
|
|
54
|
+
next
|
|
55
|
+
end
|
|
56
|
+
self.part += string[index].to_s
|
|
57
|
+
index += 1
|
|
58
|
+
end
|
|
59
|
+
array << self.part
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
protected
|
|
64
|
+
|
|
65
|
+
def match(sub_string, expression)
|
|
66
|
+
case expression
|
|
67
|
+
when Regexp
|
|
68
|
+
(sub_string =~ expression)&.zero? ? sub_string.scan(expression).first : nil
|
|
69
|
+
when String, Symbol
|
|
70
|
+
sub_string.start_with?(expression.to_s) ? expression.to_s : nil
|
|
71
|
+
else
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def check_expressions(sub_string)
|
|
77
|
+
expressions.find do |open_expression, _close_expression|
|
|
78
|
+
self.current_expression_match = match(sub_string, open_expression)
|
|
79
|
+
end&.first
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def delimiter_check(sub_string)
|
|
83
|
+
delimiters.find do |delimiter|
|
|
84
|
+
self.current_delimiter_match = match(sub_string, delimiter)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def process_expressions(expressions)
|
|
89
|
+
case expressions
|
|
90
|
+
when Array
|
|
91
|
+
expressions.hmap { |exp| [exp, exp] }
|
|
92
|
+
when String, Symbol, Regexp
|
|
93
|
+
{ expressions => expressions }
|
|
94
|
+
when Hash
|
|
95
|
+
expressions
|
|
96
|
+
else
|
|
97
|
+
raise ArgumentError, "Unknown expression format: #{expressions.class}"
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
File without changes
|
|
@@ -22,10 +22,10 @@ class TreeHash
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def child(key, symbol_sensitive = false)
|
|
25
|
-
case
|
|
26
|
-
when
|
|
25
|
+
case
|
|
26
|
+
when Hash >= node_class
|
|
27
27
|
children[key] || (symbol_sensitive ? nil : children[key.to_s.to_sym])
|
|
28
|
-
when
|
|
28
|
+
when Array >= node_class
|
|
29
29
|
children[key.to_i]
|
|
30
30
|
else
|
|
31
31
|
nil
|
|
@@ -33,14 +33,14 @@ class TreeHash
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def child_exists?(key, symbol_sensitive = false)
|
|
36
|
-
|
|
37
|
-
when
|
|
38
|
-
children
|
|
39
|
-
when
|
|
36
|
+
case
|
|
37
|
+
when Hash >= node_class
|
|
38
|
+
children.include?(key) || (!symbol_sensitive && children.include?(key.to_s.to_sym))
|
|
39
|
+
when Array >= node_class
|
|
40
40
|
[0...children.size] === key.to_i
|
|
41
41
|
else
|
|
42
42
|
false
|
|
43
|
-
end
|
|
43
|
+
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def children?
|
|
@@ -197,8 +197,8 @@ class TreeHash
|
|
|
197
197
|
self
|
|
198
198
|
end
|
|
199
199
|
|
|
200
|
-
def process(processor)
|
|
201
|
-
|
|
200
|
+
def process(processor, &block)
|
|
201
|
+
# TODO Add ability to process values or keys in tree hashes
|
|
202
202
|
end
|
|
203
203
|
|
|
204
204
|
def size
|
|
@@ -206,8 +206,8 @@ class TreeHash
|
|
|
206
206
|
end
|
|
207
207
|
|
|
208
208
|
def paths
|
|
209
|
-
case
|
|
210
|
-
when
|
|
209
|
+
case
|
|
210
|
+
when Array >= node_class, Hash >= node_class
|
|
211
211
|
value.squish.keys
|
|
212
212
|
else
|
|
213
213
|
[]
|
|
@@ -258,10 +258,10 @@ class TreeHash
|
|
|
258
258
|
end
|
|
259
259
|
|
|
260
260
|
def value
|
|
261
|
-
case
|
|
262
|
-
when
|
|
263
|
-
children.
|
|
264
|
-
when
|
|
261
|
+
case
|
|
262
|
+
when Hash >= node_class
|
|
263
|
+
children.hmap { |k, v| [k, v.value] }
|
|
264
|
+
when Array >= node_class
|
|
265
265
|
children.values.map(&:value)
|
|
266
266
|
else
|
|
267
267
|
children
|
|
@@ -270,10 +270,10 @@ class TreeHash
|
|
|
270
270
|
|
|
271
271
|
def key
|
|
272
272
|
return nil if root?
|
|
273
|
-
case
|
|
274
|
-
when
|
|
273
|
+
case
|
|
274
|
+
when Hash >= parent.node_class
|
|
275
275
|
parent.keys[index]
|
|
276
|
-
when
|
|
276
|
+
when Array >= parent.node_class
|
|
277
277
|
index
|
|
278
278
|
else
|
|
279
279
|
nil
|
|
@@ -327,11 +327,11 @@ class TreeHash
|
|
|
327
327
|
end
|
|
328
328
|
|
|
329
329
|
def delete_child(key, symbol_sensitive = false)
|
|
330
|
-
case
|
|
331
|
-
when
|
|
330
|
+
case
|
|
331
|
+
when Hash >= node_class
|
|
332
332
|
child = symbol_sensitive ? nil : children.delete(key.to_s.to_sym)
|
|
333
333
|
child = children.delete(key) unless child
|
|
334
|
-
when
|
|
334
|
+
when Array >= node_class
|
|
335
335
|
children.delete(key.to_i)
|
|
336
336
|
else
|
|
337
337
|
nil
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require_relative 'part'
|
|
3
|
-
require_relative 'proc'
|
|
4
|
-
require_relative 'path_hash'
|
|
5
3
|
|
|
6
4
|
# This classes parses dot delimited hash path strings and wraps the corresponding parts. Then hashes or arrays can be
|
|
7
5
|
# passed to the find method to find all matching elements for the path.
|
|
File without changes
|
|
@@ -100,6 +100,14 @@ module BBLib
|
|
|
100
100
|
end
|
|
101
101
|
end
|
|
102
102
|
|
|
103
|
+
if opts[:aliases]
|
|
104
|
+
[opts[:aliases]].flatten.each do |als|
|
|
105
|
+
obj = opts[:singleton] ? self.singleton_class : self
|
|
106
|
+
obj.send(:alias_method, als, method)
|
|
107
|
+
obj.send(:alias_method, "#{als}=", "#{method}=")
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
103
111
|
unless opts[:singleton]
|
|
104
112
|
protected method if opts[:protected] || opts[:protected_reader]
|
|
105
113
|
protected "#{method}=".to_sym if opts[:protected] || opts[:protected_writer]
|
|
@@ -126,7 +134,7 @@ module BBLib
|
|
|
126
134
|
elsif arg && (!opts.include?(:pack) || opts[:pack]) && arg = _attr_pack(arg, klasses, opts)
|
|
127
135
|
arg
|
|
128
136
|
else
|
|
129
|
-
raise TypeError, "#{method} must be set to a class of #{allowed.join_terms(:or)}, not #{arg.class}" unless opts[:suppress]
|
|
137
|
+
raise TypeError, "#{method} must be set to a class of #{allowed.join_terms(:or)}, not #{arg.class} (#{self})" unless opts[:suppress]
|
|
130
138
|
end
|
|
131
139
|
end
|
|
132
140
|
end
|
|
@@ -208,9 +216,11 @@ module BBLib
|
|
|
208
216
|
def attr_element_of(list, *methods, **opts)
|
|
209
217
|
methods.each do |method|
|
|
210
218
|
attr_custom(method, opts.merge(list: list)) do |arg|
|
|
211
|
-
ls = list.is_a?(Proc) ? list.call : list
|
|
219
|
+
ls = list.is_a?(Proc) ? list.call(self) : list
|
|
212
220
|
if ls.include?(arg) || (opts[:allow_nil] && arg.nil?)
|
|
213
221
|
arg
|
|
222
|
+
elsif opts[:fallback]
|
|
223
|
+
opts[:fallback]
|
|
214
224
|
else
|
|
215
225
|
raise ArgumentError, "Invalid option '#{arg}' for #{method}." unless opts.include?(:raise) && !opts[:raise]
|
|
216
226
|
end
|
|
@@ -222,7 +232,7 @@ module BBLib
|
|
|
222
232
|
opts[:default] = [] unless opts.include?(:default) || opts.include?(:default_proc)
|
|
223
233
|
methods.each do |method|
|
|
224
234
|
attr_custom(method, opts.merge(list: list)) do |args|
|
|
225
|
-
ls = list.is_a?(Proc) ? list.call : list
|
|
235
|
+
ls = list.is_a?(Proc) ? list.call(self) : list
|
|
226
236
|
[].tap do |final|
|
|
227
237
|
[args].flatten(1).each do |arg|
|
|
228
238
|
if ls.include?(arg) || (opts[:allow_nil] && arg.nil?)
|
|
@@ -272,7 +282,7 @@ module BBLib
|
|
|
272
282
|
elsif arg && (!opts.include?(:pack) || opts[:pack]) && arg = _attr_pack(arg, klasses, opts)
|
|
273
283
|
array.push(arg)
|
|
274
284
|
else
|
|
275
|
-
raise TypeError, "Invalid class passed to #{method} on #{self}: #{arg.class}. Must be a #{klasses.join_terms(:or)}." unless opts[:
|
|
285
|
+
raise TypeError, "Invalid class passed to #{method} on #{self}: #{arg.class}. Must be a #{klasses.join_terms(:or)}." unless opts[:suppress]
|
|
276
286
|
end
|
|
277
287
|
end
|
|
278
288
|
end
|
|
@@ -397,7 +407,7 @@ module BBLib
|
|
|
397
407
|
elsif (opts.include?(:pack_key) && opts[:pack_key]) && new_key = _attr_pack(key, klasses, opts)
|
|
398
408
|
arg[new_key] = arg.delete(key)
|
|
399
409
|
else
|
|
400
|
-
raise ArgumentError, "Invalid key type for #{method}: #{key.class}. Must be #{opts[:keys].join_terms(:or)}."
|
|
410
|
+
raise ArgumentError, "Invalid key type for #{method}: #{key.class}. Must be #{[opts[:keys]].flatten.join_terms(:or)}."
|
|
401
411
|
end
|
|
402
412
|
end
|
|
403
413
|
end
|
|
@@ -418,10 +428,10 @@ module BBLib
|
|
|
418
428
|
end
|
|
419
429
|
end
|
|
420
430
|
|
|
421
|
-
def _attr_pack(arg, klasses, opts = {})
|
|
431
|
+
def _attr_pack(arg, klasses, opts = {}, &block)
|
|
422
432
|
klasses = [klasses].flatten
|
|
423
433
|
unless BBLib.is_any?(arg, *klasses)
|
|
424
|
-
return klasses.first.new(*[arg].flatten(1)) if klasses.first.respond_to?(:new)
|
|
434
|
+
return klasses.first.new(*[arg].flatten(1), &block) if klasses.first.respond_to?(:new)
|
|
425
435
|
end
|
|
426
436
|
nil
|
|
427
437
|
end
|