nrser 0.0.30 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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