bblib 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +502 -8
  3. data/lib/bblib.rb +1 -28
  4. data/lib/bblib/all.rb +5 -0
  5. data/lib/{time → bblib/classes}/cron.rb +0 -0
  6. data/lib/{string → bblib/classes}/fuzzy_matcher.rb +0 -0
  7. data/lib/bblib/cli.rb +3 -0
  8. data/lib/bblib/cli/color.rb +51 -0
  9. data/lib/bblib/cli/exceptions/invalid_argument.rb +5 -0
  10. data/lib/bblib/cli/exceptions/missing_argument.rb +5 -0
  11. data/lib/bblib/cli/exceptions/missing_required_argument.rb +5 -0
  12. data/lib/bblib/cli/exceptions/opts_parser.rb +9 -0
  13. data/lib/bblib/cli/option.rb +116 -0
  14. data/lib/bblib/cli/options/basic_option.rb +19 -0
  15. data/lib/bblib/cli/options/bool.rb +19 -0
  16. data/lib/bblib/cli/options/command.rb +11 -0
  17. data/lib/bblib/cli/options/date.rb +14 -0
  18. data/lib/bblib/cli/options/float.rb +14 -0
  19. data/lib/bblib/cli/options/integer.rb +14 -0
  20. data/lib/bblib/cli/options/json.rb +16 -0
  21. data/lib/bblib/cli/options/regexp.rb +17 -0
  22. data/lib/bblib/cli/options/string.rb +13 -0
  23. data/lib/bblib/cli/options/symbol.rb +13 -0
  24. data/lib/bblib/cli/options/time.rb +14 -0
  25. data/lib/bblib/cli/options/toggle.rb +27 -0
  26. data/lib/bblib/cli/options/untoggle.rb +18 -0
  27. data/lib/bblib/cli/opts_parser.rb +65 -0
  28. data/lib/bblib/core.rb +37 -0
  29. data/lib/{hash → bblib/core/classes}/hash_struct.rb +9 -2
  30. data/lib/bblib/core/classes/splitter.rb +101 -0
  31. data/lib/{time → bblib/core/classes}/task_timer.rb +0 -0
  32. data/lib/{hash → bblib/core/classes}/tree_hash.rb +22 -22
  33. data/lib/bblib/core/exceptions/abstract.rb +3 -0
  34. data/lib/bblib/core/exceptions/exception.rb +5 -0
  35. data/lib/{hash_path → bblib/core/hash_path}/hash_path.rb +0 -2
  36. data/lib/{hash_path → bblib/core/hash_path}/part.rb +0 -0
  37. data/lib/{mixins → bblib/core/mixins}/attrs.rb +17 -7
  38. data/lib/{mixins → bblib/core/mixins}/bbmixins.rb +1 -0
  39. data/lib/{mixins → bblib/core/mixins}/bridge.rb +0 -0
  40. data/lib/bblib/core/mixins/delegator.rb +90 -0
  41. data/lib/{class → bblib/core/mixins}/effortless.rb +0 -0
  42. data/lib/{mixins → bblib/core/mixins}/family_tree.rb +1 -1
  43. data/lib/{mixins → bblib/core/mixins}/hooks.rb +0 -0
  44. data/lib/{mixins → bblib/core/mixins}/logger.rb +0 -0
  45. data/lib/{mixins → bblib/core/mixins}/prototype.rb +0 -0
  46. data/lib/{mixins → bblib/core/mixins}/serializer.rb +0 -0
  47. data/lib/{mixins → bblib/core/mixins}/simple_init.rb +41 -3
  48. data/lib/{mixins → bblib/core/mixins}/type_init.rb +0 -0
  49. data/lib/{array/bbarray.rb → bblib/core/util/array.rb} +0 -0
  50. data/lib/{string → bblib/core/util}/cases.rb +0 -0
  51. data/lib/{file/bbfile.rb → bblib/core/util/file.rb} +31 -7
  52. data/lib/{hash/bbhash.rb → bblib/core/util/hash.rb} +0 -3
  53. data/lib/{logging/bblogging.rb → bblib/core/util/logging.rb} +11 -2
  54. data/lib/{string → bblib/core/util}/matching.rb +0 -0
  55. data/lib/{number/bbnumber.rb → bblib/core/util/number.rb} +0 -0
  56. data/lib/{object/bbobject.rb → bblib/core/util/object.rb} +2 -0
  57. data/lib/{opal/bbopal.rb → bblib/core/util/opal.rb} +0 -0
  58. data/lib/{os/bbos.rb → bblib/core/util/os.rb} +0 -0
  59. data/lib/{string → bblib/core/util}/pluralization.rb +0 -0
  60. data/lib/{string → bblib/core/util}/regexp.rb +0 -0
  61. data/lib/{string → bblib/core/util}/roman.rb +0 -0
  62. data/lib/{string/bbstring.rb → bblib/core/util/string.rb} +18 -24
  63. data/lib/{time/bbtime.rb → bblib/core/util/time.rb} +1 -5
  64. data/lib/bblib/cron.rb +2 -0
  65. data/lib/bblib/fuzzy_matcher.rb +2 -0
  66. data/lib/bblib/html.rb +4 -0
  67. data/lib/{html → bblib/html}/builder.rb +0 -0
  68. data/lib/{html → bblib/html}/tag.rb +0 -0
  69. data/lib/{html → bblib/html}/tag_set.rb +0 -0
  70. data/lib/bblib/system.rb +3 -0
  71. data/lib/bblib/system/command.rb +7 -0
  72. data/lib/bblib/system/system.rb +39 -0
  73. data/lib/bblib/version.rb +1 -1
  74. metadata +71 -44
  75. data/lib/error/abstract.rb +0 -3
  76. data/lib/hash_path/path_hash.rb +0 -84
  77. data/lib/hash_path/proc.rb +0 -93
  78. data/lib/hash_path/processors.rb +0 -239
  79. data/lib/html/bbhtml.rb +0 -3
  80. data/lib/system/bbsystem.rb +0 -42
@@ -0,0 +1,18 @@
1
+ module BBLib
2
+ class OptsParser
3
+ class Untoggle < Toggle
4
+
5
+ def extract(index, args)
6
+ super
7
+ false
8
+ end
9
+
10
+ protected
11
+
12
+ def simple_setup
13
+ self.default = true
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -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
@@ -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
- define_singleton_method(method) do
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
@@ -22,10 +22,10 @@ class TreeHash
22
22
  end
23
23
 
24
24
  def child(key, symbol_sensitive = false)
25
- case [node_class]
26
- when [Hash]
25
+ case
26
+ when Hash >= node_class
27
27
  children[key] || (symbol_sensitive ? nil : children[key.to_s.to_sym])
28
- when [Array]
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
- !case [node_class]
37
- when [Hash]
38
- children[key] || (!symbol_sensitive && children[key.to_s.to_sym])
39
- when [Array]
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.nil?
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 [node_class]
210
- when [Array], [Hash]
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 [node_class]
262
- when [Hash]
263
- children.map { |k, v| [k, v.value] }.to_h
264
- when [Array]
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 [parent.node_class]
274
- when [Hash]
273
+ case
274
+ when Hash >= parent.node_class
275
275
  parent.keys[index]
276
- when [Array]
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 [node_class]
331
- when [Hash]
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 [Array]
334
+ when Array >= node_class
335
335
  children.delete(key.to_i)
336
336
  else
337
337
  nil
@@ -0,0 +1,3 @@
1
+ class AbstractError < BBLib::Exception
2
+ # Enhance at some point
3
+ end
@@ -0,0 +1,5 @@
1
+ module BBLib
2
+ class Exception < StandardError; end
3
+ end
4
+
5
+ require_relative 'abstract'
@@ -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.
@@ -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[:raise] == false
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
@@ -7,3 +7,4 @@ require_relative 'logger'
7
7
  require_relative 'bridge'
8
8
  require_relative 'prototype'
9
9
  require_relative 'type_init'
10
+ require_relative 'delegator'