nrser 0.0.30 → 0.1.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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nrser.rb +56 -12
  3. data/lib/nrser/collection.rb +4 -7
  4. data/lib/nrser/ext.rb +5 -0
  5. data/lib/nrser/{refinements → ext}/enumerable.rb +11 -9
  6. data/lib/nrser/ext/pathname.rb +74 -0
  7. data/lib/nrser/{refinements → ext}/tree.rb +2 -26
  8. data/lib/nrser/functions.rb +18 -0
  9. data/lib/nrser/{array.rb → functions/array.rb} +2 -3
  10. data/lib/nrser/{binding.rb → functions/binding.rb} +0 -2
  11. data/lib/nrser/functions/enumerable.rb +355 -0
  12. data/lib/nrser/functions/enumerable/find_all_map.rb +33 -0
  13. data/lib/nrser/functions/enumerable/find_map.rb +53 -0
  14. data/lib/nrser/functions/exception.rb +17 -0
  15. data/lib/nrser/{hash.rb → functions/hash.rb} +0 -0
  16. data/lib/nrser/functions/hash/bury.rb +147 -0
  17. data/lib/nrser/{hash → functions/hash}/deep_merge.rb +5 -5
  18. data/lib/nrser/{hash → functions/hash}/except_keys.rb +2 -0
  19. data/lib/nrser/{hash → functions/hash}/guess_label_key_type.rb +3 -1
  20. data/lib/nrser/{hash → functions/hash}/slice_keys.rb +3 -1
  21. data/lib/nrser/{hash → functions/hash}/stringify_keys.rb +2 -0
  22. data/lib/nrser/{hash → functions/hash}/symbolize_keys.rb +3 -1
  23. data/lib/nrser/{hash → functions/hash}/transform_keys.rb +3 -1
  24. data/lib/nrser/functions/merge_by.rb +29 -0
  25. data/lib/nrser/{object.rb → functions/object.rb} +0 -0
  26. data/lib/nrser/{object → functions/object}/as_array.rb +2 -0
  27. data/lib/nrser/{object → functions/object}/as_hash.rb +7 -5
  28. data/lib/nrser/{object → functions/object}/truthy.rb +46 -7
  29. data/lib/nrser/{open_struct.rb → functions/open_struct.rb} +0 -0
  30. data/lib/nrser/functions/path.rb +150 -0
  31. data/lib/nrser/{proc.rb → functions/proc.rb} +1 -22
  32. data/lib/nrser/functions/string.rb +297 -0
  33. data/lib/nrser/functions/string/looks_like.rb +44 -0
  34. data/lib/nrser/{text.rb → functions/text.rb} +0 -0
  35. data/lib/nrser/{text → functions/text}/indentation.rb +2 -16
  36. data/lib/nrser/{text → functions/text}/lines.rb +1 -2
  37. data/lib/nrser/{text → functions/text}/word_wrap.rb +2 -4
  38. data/lib/nrser/{tree.rb → functions/tree.rb} +0 -0
  39. data/lib/nrser/{tree → functions/tree}/each_branch.rb +6 -7
  40. data/lib/nrser/functions/tree/leaves.rb +92 -0
  41. data/lib/nrser/{tree → functions/tree}/map_branches.rb +31 -32
  42. data/lib/nrser/functions/tree/map_leaves.rb +56 -0
  43. data/lib/nrser/{tree → functions/tree}/map_tree.rb +9 -20
  44. data/lib/nrser/{tree → functions/tree}/transform.rb +0 -10
  45. data/lib/nrser/logger.rb +9 -10
  46. data/lib/nrser/message.rb +3 -7
  47. data/lib/nrser/meta.rb +2 -0
  48. data/lib/nrser/meta/class_attrs.rb +3 -9
  49. data/lib/nrser/meta/props.rb +19 -19
  50. data/lib/nrser/meta/props/base.rb +4 -10
  51. data/lib/nrser/meta/props/prop.rb +12 -28
  52. data/lib/nrser/no_arg.rb +1 -3
  53. data/lib/nrser/refinements.rb +5 -0
  54. data/lib/nrser/refinements/array.rb +5 -17
  55. data/lib/nrser/refinements/enumerator.rb +1 -3
  56. data/lib/nrser/refinements/hash.rb +3 -15
  57. data/lib/nrser/refinements/object.rb +2 -2
  58. data/lib/nrser/refinements/open_struct.rb +0 -2
  59. data/lib/nrser/refinements/pathname.rb +3 -46
  60. data/lib/nrser/refinements/set.rb +2 -6
  61. data/lib/nrser/refinements/string.rb +2 -2
  62. data/lib/nrser/rspex.rb +16 -13
  63. data/lib/nrser/types.rb +6 -20
  64. data/lib/nrser/types/any.rb +0 -1
  65. data/lib/nrser/types/booleans.rb +1 -1
  66. data/lib/nrser/types/combinators.rb +5 -5
  67. data/lib/nrser/types/in.rb +0 -21
  68. data/lib/nrser/types/responds.rb +1 -0
  69. data/lib/nrser/types/trees.rb +1 -0
  70. data/lib/nrser/version.rb +2 -3
  71. data/spec/nrser/{template_spec.rb → functions/binding/template_spec.rb} +0 -0
  72. data/spec/nrser/functions/enumerable/find_all_map_spec.rb +28 -0
  73. data/spec/nrser/functions/enumerable/find_bounded_spec.rb +70 -0
  74. data/spec/nrser/functions/enumerable/find_map_spec.rb +38 -0
  75. data/spec/nrser/functions/enumerable/find_only_spec.rb +25 -0
  76. data/spec/nrser/functions/enumerable/to_h_by_spec.rb +28 -0
  77. data/spec/nrser/{format_exception_spec.rb → functions/exception/format_exception_spec.rb} +0 -0
  78. data/spec/nrser/{hash → functions/hash}/bury_spec.rb +0 -0
  79. data/spec/nrser/{hash → functions/hash}/guess_label_key_type_spec.rb +0 -0
  80. data/spec/nrser/{hash_spec.rb → functions/hash_spec.rb} +0 -7
  81. data/spec/nrser/{merge_by_spec.rb → functions/merge_by_spec.rb} +0 -0
  82. data/spec/nrser/{truthy_spec.rb → functions/object/truthy_spec.rb} +0 -0
  83. data/spec/nrser/{open_struct_spec.rb → functions/open_struct_spec.rb} +0 -0
  84. data/spec/nrser/{string → functions/string}/common_prefix_spec.rb +0 -0
  85. data/spec/nrser/{string → functions/string}/looks_like_spec.rb +0 -0
  86. data/spec/nrser/{truncate_spec.rb → functions/string/truncate_spec.rb} +0 -0
  87. data/spec/nrser/{text → functions/text}/dedent/gotchas_spec.rb +0 -0
  88. data/spec/nrser/{text → functions/text}/dedent_spec.rb +0 -0
  89. data/spec/nrser/{indent_spec.rb → functions/text/indent_spec.rb} +0 -0
  90. data/spec/nrser/{tree → functions/tree}/each_branch_spec.rb +0 -0
  91. data/spec/nrser/{tree → functions/tree}/leaves_spec.rb +0 -0
  92. data/spec/nrser/{tree → functions/tree}/map_branch_spec.rb +0 -0
  93. data/spec/nrser/{tree → functions/tree}/map_tree_spec.rb +0 -0
  94. data/spec/nrser/{tree → functions/tree}/transform_spec.rb +0 -0
  95. data/spec/nrser/{tree → functions/tree}/transformer_spec.rb +0 -0
  96. data/spec/nrser/meta/class_attrs_spec.rb +12 -14
  97. data/spec/spec_helper.rb +2 -3
  98. metadata +136 -110
  99. data/lib/nrser/enumerable.rb +0 -288
  100. data/lib/nrser/exception.rb +0 -7
  101. data/lib/nrser/hash/bury.rb +0 -154
  102. data/lib/nrser/merge_by.rb +0 -26
  103. data/lib/nrser/string.rb +0 -294
  104. data/lib/nrser/string/looks_like.rb +0 -51
  105. data/lib/nrser/tree/leaves.rb +0 -92
  106. data/lib/nrser/tree/map_leaves.rb +0 -63
  107. data/spec/nrser/enumerable_spec.rb +0 -111
@@ -1,288 +0,0 @@
1
- require 'pp'
2
-
3
- require_relative './errors'
4
-
5
- module NRSER
6
-
7
- # Eigenclass (Singleton Class)
8
- # ========================================================================
9
- #
10
- class << self
11
- # Maps an enumerable object to a *new* hash with the same keys and values
12
- # obtained by calling `block` with the current key and value.
13
- #
14
- # If `enumerable` *does not* respond to `#to_pairs` then it's
15
- # treated as a hash where the elements iterated by `#each` are it's keys
16
- # and all it's values are `nil`.
17
- #
18
- # In this way, {NRSER.map_values} handles Hash, Array, Set, OpenStruct,
19
- # and probably pretty much anything else reasonable you may throw at it.
20
- #
21
- # @param [#each_pair, #each] enumerable
22
- #
23
- # @yieldparam [Object] key
24
- # The key that will be used for whatever value the block returns in the
25
- # new hash.
26
- #
27
- # @yieldparam [nil, Object] value
28
- # If `enumerable` responds to `#each_pair`, the second parameter it yielded
29
- # along with `key`. Otherwise `nil`.
30
- #
31
- # @yieldreturn [Object]
32
- # Value for the new hash.
33
- #
34
- # @return [Hash]
35
- #
36
- # @raise [TypeError]
37
- # If `enumerable` does not respond to `#each_pair` or `#each`.
38
- #
39
- def map_values enumerable, &block
40
- result = {}
41
-
42
- if enumerable.respond_to? :each_pair
43
- enumerable.each_pair { |key, value|
44
- result[key] = block.call key, value
45
- }
46
- elsif enumerable.respond_to? :each
47
- enumerable.each { |key|
48
- result[key] = block.call key, nil
49
- }
50
- else
51
- raise TypeError.new NRSER.squish <<-END
52
- First argument must respond to #each_pair or #each
53
- (found #{ enumerable.inspect })
54
- END
55
- end
56
-
57
- result
58
- end # #map_values
59
-
60
-
61
-
62
- # Find all entries in an {Enumerable} for which `&block` returns a truthy
63
- # value, then check the amount of results found against the
64
- # {NRSER::Types.length} created from `bounds`, raising a {TypeError} if
65
- # the results' length doesn't satisfy the bounds type.
66
- #
67
- # @param [Enumerable] enum
68
- # The entries to search and check.
69
- #
70
- # @param []
71
- #
72
- # @return [return_type]
73
- # @todo Document return value.
74
- #
75
- # @raise
76
- #
77
- def find_bounded enum, bounds, &block
78
- NRSER::Types.
79
- length(bounds).
80
- check(enum.find_all &block) { |type:, value:|
81
- NRSER.dedent <<-END
82
-
83
- Length of found elements (#{ value.length }) FAILED to
84
- satisfy #{ type.to_s }
85
-
86
- Found:
87
- #{ NRSER.indent value.pretty_inspect }
88
-
89
- Enumerable:
90
- #{ NRSER.indent enum.pretty_inspect }
91
-
92
- END
93
- }
94
- end # #find_bounded
95
-
96
-
97
- # @todo Document find_only method.
98
- #
99
- # @param [type] arg_name
100
- # @todo Add name param description.
101
- #
102
- # @return [return_type]
103
- # @todo Document return value.
104
- #
105
- def find_only enum, &block
106
- find_bounded(enum, 1, &block).first
107
- end # #find_only
108
-
109
-
110
- # Return the only entry if the enumerable has `#count` one. Otherwise,
111
- # return `default` (which defaults to `nil`).
112
- #
113
- # @param [Enumerable] enum
114
- # Enumerable in question.
115
- #
116
- # @param [Object] default:
117
- # Value to return if `enum` does not have only one entry.
118
- #
119
- # @return [Object]
120
- # The only entry in `enum` if it has only one, else `default`.
121
- #
122
- def only enum, default: nil
123
- if enum.count == 1
124
- enum.first
125
- else
126
- default
127
- end
128
- end
129
-
130
-
131
- # @todo Document only method.
132
- #
133
- # @param [type] arg_name
134
- # @todo Add name param description.
135
- #
136
- # @return [return_type]
137
- # @todo Document return value.
138
- #
139
- def only! enum
140
- unless enum.count == 1
141
- raise TypeError.new squish <<-END
142
- Expected enumerable #{ enum.inspect } to have exactly one entry.
143
- END
144
- end
145
-
146
- enum.first
147
- end # #only
148
-
149
-
150
-
151
- # @todo Document to_h_by method.
152
- #
153
- # @param [type] arg_name
154
- # @todo Add name param description.
155
- #
156
- # @return [return_type]
157
- # @todo Document return value.
158
- #
159
- def to_h_by enum, &block
160
- {}.tap { |result|
161
- enum.each { |element|
162
- key = block.call element
163
-
164
- if result.key? key
165
- raise NRSER::ConflictError.new NRSER.dedent <<-END
166
- Key #{ key.inspect } is already in results with value:
167
-
168
- #{ result[key].pretty_inspect }
169
- END
170
- end
171
-
172
- result[key] = element
173
- }
174
- }
175
- end # #to_h_by
176
-
177
-
178
- # Create an {Enumerator} that iterates over the "values" of an
179
- # {Enumerable} `enum`. If `enum` responds to `#each_value` than we return
180
- # that. Otherwise, we return `#each_entry`.
181
- #
182
- # @param [Enumerable] enum
183
- #
184
- # @return [Enumerator]
185
- #
186
- # @raise [TypeError]
187
- # If `enum` doesn't respond to `#each_value` or `#each_entry`.
188
- #
189
- def enumerate_as_values enum
190
- # NRSER.match enum,
191
- # t.respond_to(:each_value), :each_value.to_proc,
192
- # t.respond_to(:each_entry), :each_entry.to_proc
193
- #
194
- if enum.respond_to? :each_value
195
- enum.each_value
196
- elsif enum.respond_to? :each_entry
197
- enum.each_entry
198
- else
199
- raise TypeError.squished <<-END
200
- Expected `enum` arg to respond to :each_value or :each_entry,
201
- found #{ enum.inspect }
202
- END
203
- end
204
- end # #enumerate_as_values
205
-
206
-
207
- # Count entries in an {Enumerable} by the value returned when they are
208
- # passed to the block.
209
- #
210
- # @example Count array entries by class
211
- #
212
- # [1, 2, :three, 'four', 5, :six].count_by &:class
213
- # # => {Fixnum=>3, Symbol=>2, String=>1}
214
- #
215
- # @param [Enumerable<E>] enum
216
- # {Enumerable} (or other object with compatible `#each_with_object` and
217
- # `#to_enum` methods) you want to count.
218
- #
219
- # @param [Proc<(E)=>C>] &block
220
- # Block mapping entries in `enum` to the group to count them in.
221
- #
222
- # @return [Hash{C=>Integer}]
223
- # Hash mapping groups to positive integer counts.
224
- #
225
- def count_by enum, &block
226
- enum.each_with_object( Hash.new 0 ) do |entry, hash|
227
- hash[block.call entry] += 1
228
- end
229
- end
230
-
231
-
232
- # Like `Enumerable#find`, but wraps each call to `&block` in a
233
- # `begin` / `rescue`, returning the result of the first call that doesn't
234
- # raise an error.
235
- #
236
- # If no calls succeed, raises a {NRSER::MultipleErrors} containing the
237
- # errors from the block calls.
238
- #
239
- # @param [Enumerable<E>] enum
240
- # Values to call `&block` with.
241
- #
242
- # @param [Proc<E=>V>] &block
243
- # Block to call, which is expected to raise an error if it fails.
244
- #
245
- # @return [V]
246
- # Result of first call to `&block` that doesn't raise.
247
- #
248
- # @raise [ArgumentError]
249
- # If `enum` was empty (`enum#each` never yielded).
250
- #
251
- # @raise [NRSER::MultipleErrors]
252
- # If all calls to `&block` failed.
253
- #
254
- def try_find enum, &block
255
- errors = []
256
-
257
- enum.each do |*args|
258
- begin
259
- result = block.call *args
260
- rescue Exception => error
261
- errors << error
262
- else
263
- return result
264
- end
265
- end
266
-
267
- if errors.empty?
268
- raise ArgumentError,
269
- "Appears that enumerable was empty: #{ enum.inspect }"
270
- else
271
- raise NRSER::MultipleErrors.new errors
272
- end
273
- end
274
-
275
-
276
- # TODO It would be nice for this to work...
277
- #
278
- # def to_enum object, meth, *args
279
- # unless object.respond_to?( meth )
280
- # object = NRSER::Enumerable.new object
281
- # end
282
- #
283
- # object.to_enum meth, *args
284
- # end
285
-
286
-
287
- end # class << self (Eigenclass)
288
- end # module NRSER
@@ -1,7 +0,0 @@
1
- module NRSER
2
- class << self
3
- def format_exception e
4
- "#{ e.message } (#{ e.class }):\n #{ e.backtrace.join("\n ") }"
5
- end
6
- end # class << self
7
- end # module NRSER
@@ -1,154 +0,0 @@
1
- # Definitions
2
- # =======================================================================
3
-
4
- module NRSER
5
-
6
- # Eigenclass (Singleton Class)
7
- # ========================================================================
8
- #
9
- class << self
10
-
11
- # The opposite of `#dig` - set a value at a deep key path, creating
12
- # necessary structures along the way and optionally clobbering whatever's
13
- # in the way to achieve success.
14
- #
15
- # @param [Hash] hash
16
- # Hash to bury the value in.
17
- #
18
- # @param [Array | #to_s] key_path
19
- # - When an {Array}, each entry is used exactly as-is for each key.
20
- #
21
- # - Otherwise, the `key_path` is converted to a string and split by
22
- # `.` to produce the key array, and the actual keys used depend on
23
- # the `parsed_key_type` option.
24
- #
25
- # @param [Object] value
26
- # The value to set at the end of the path.
27
- #
28
- # @param [Class | :guess] parsed_key_type:
29
- # How to handle parsed key path segments:
30
- #
31
- # - `String` - use the strings that naturally split from a parsed
32
- # key path.
33
- #
34
- # Note that this is the *String class itself, **not** a value that
35
- # is a String*.
36
- #
37
- # - `Symbol` - convert the strings that are split from the key path
38
- # to symbols.
39
- #
40
- # Note that this is the *Symbol class itself, **not** a value that
41
- # is a Symbol*.``
42
- #
43
- # - `:guess` (default) -
44
- #
45
- # @return [return_type]
46
- # @todo Document return value.
47
- #
48
- def bury! hash,
49
- key_path,
50
- value,
51
- parsed_key_type: :guess,
52
- clobber: false,
53
- create_arrays_for_unsigned_keys: false
54
-
55
- # Parse the key if it's not an array
56
- unless key_path.is_a?( Array )
57
- key_path = key_path.to_s.split '.'
58
-
59
- # Convert the keys to symbols now if that's what we want to use
60
- if parsed_key_type == Symbol
61
- key_path.map! &:to_sym
62
- end
63
- end
64
-
65
- _internal_bury! \
66
- hash,
67
- key_path,
68
- value,
69
- guess_key_type: ( parsed_key_type == :guess ),
70
- clobber: clobber,
71
- create_arrays_for_unsigned_keys: create_arrays_for_unsigned_keys
72
- end # #bury
73
-
74
-
75
- private
76
- # ========================================================================
77
-
78
-
79
- # @todo Document _internal_bury! method.
80
- #
81
- # @param [type] arg_name
82
- # @todo Add name param description.
83
- #
84
- # @return [return_type]
85
- # @todo Document return value.
86
- #
87
- def _internal_bury! tree,
88
- key_path,
89
- value,
90
- guess_key_type:,
91
- clobber:,
92
- create_arrays_for_unsigned_keys:
93
-
94
- # Split the key path into the current key and the rest of the keys
95
- key, *rest = key_path
96
-
97
- # If we are
98
- #
99
- # - Guessing the key type
100
- # - The tree is keyed
101
- # - The tree uses some {Symbol} (and no {String}) keys
102
- #
103
- # then convert the key to a symbol.
104
- #
105
- if guess_key_type &&
106
- tree.respond_to?( :keys ) &&
107
- guess_label_key_type( tree ) == Symbol
108
- key = key.to_sym
109
- end
110
-
111
- # Terminating case: we're at the last segment
112
- if rest.empty?
113
- # Set the value
114
- tree[key] = value
115
-
116
- else
117
- # Go deeper...
118
-
119
- # See if there is a hash in place
120
- unless NRSER::Types.tree.test tree[key]
121
- # There is not... so we need to do some figurin'
122
-
123
- # If we're clobbering or the hash has no value, we're good:
124
- # assign a new hash to set in
125
- if clobber || tree[key].nil?
126
- if create_arrays_for_unsigned_keys &&
127
- NRSER::Types.unsigned.test( key )
128
- tree[key] = []
129
- else
130
- tree[key] = {}
131
- end
132
-
133
- else
134
- # We've got an intractable state conflict; raise
135
- raise NRSER::ConflictError.new squish <<-END
136
- can not set key #{ key.inspect } due to conflicting value
137
- #{ tree[key].inspect } in tree #{ tree.inspect } (:clobber
138
- option not set)
139
- END
140
-
141
- end
142
- end # unless hash[key].is_a?( Hash )
143
-
144
- # Dive in...
145
- bury! tree[key], rest, value
146
-
147
- end # if rest.empty? / else
148
- end # #_internal_bury!
149
-
150
- # end private
151
-
152
- end # class << self (Eigenclass)
153
-
154
- end # module NRSER