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,26 +0,0 @@
1
-
2
-
3
- module NRSER
4
-
5
- # Eigenclass (Singleton Class)
6
- # ========================================================================
7
- #
8
- class << self
9
-
10
- # @todo Document merge_by method.
11
- #
12
- # @param [type] arg_name
13
- # @todo Add name param description.
14
- #
15
- # @return [return_type]
16
- # @todo Document return value.
17
- #
18
- def merge_by current, *updates, &getter
19
- updates.reduce( to_h_by current, &getter ) { |result, update|
20
- deep_merge! result, to_h_by(update, &getter)
21
- }.values
22
- end # #merge_by
23
-
24
- end # class << self (Eigenclass)
25
-
26
- end # module NRSER
data/lib/nrser/string.rb DELETED
@@ -1,294 +0,0 @@
1
- require_relative './string/looks_like'
2
-
3
- module NRSER
4
- # @!group String Functions
5
-
6
- WHITESPACE_RE = /\A[[:space:]]*\z/
7
-
8
- UNICODE_ELLIPSIS = '…'
9
-
10
-
11
- def self.whitespace? string
12
- string =~ WHITESPACE_RE
13
- end
14
-
15
-
16
- class << self
17
-
18
- # Functions the operate on strings.
19
-
20
- # turn a multi-line string into a single line, collapsing whitespace
21
- # to a single space.
22
- #
23
- # same as ActiveSupport's String.squish, adapted from there.
24
- def squish str
25
- str.gsub(/[[:space:]]+/, ' ').strip
26
- end # squish
27
-
28
- alias_method :unblock, :squish
29
-
30
-
31
- def common_prefix strings
32
- raise ArgumentError.new("argument can't be empty") if strings.empty?
33
-
34
- sorted = strings.sort
35
-
36
- i = 0
37
-
38
- while sorted.first[i] == sorted.last[i] &&
39
- i < [sorted.first.length, sorted.last.length].min
40
- i = i + 1
41
- end
42
-
43
- sorted.first[0...i]
44
- end # common_prefix
45
-
46
-
47
- def filter_repeated_blank_lines str, remove_leading: false
48
- out = []
49
- lines = str.lines
50
- skipping = remove_leading
51
- str.lines.each do |line|
52
- if line =~ /^\s*$/
53
- unless skipping
54
- out << line
55
- end
56
- skipping = true
57
- else
58
- skipping = false
59
- out << line
60
- end
61
- end
62
- out.join
63
- end # filter_repeated_blank_lines
64
-
65
-
66
- def lazy_filter_repeated_blank_lines source, remove_leading: false
67
- skipping = remove_leading
68
-
69
- source = source.each_line if source.is_a? String
70
-
71
- Enumerator::Lazy.new source do |yielder, line|
72
- if line =~ /^\s*$/
73
- unless skipping
74
- yielder << line
75
- end
76
- skipping = true
77
- else
78
- skipping = false
79
- yielder << line
80
- end
81
- end
82
-
83
- end # filter_repeated_blank_lines
84
-
85
-
86
- # Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>:
87
- #
88
- # 'Once upon a time in a world far far away'.truncate(27)
89
- # # => "Once upon a time in a wo..."
90
- #
91
- # Pass a string or regexp <tt>:separator</tt> to truncate +text+ at a natural break:
92
- #
93
- # 'Once upon a time in a world far far away'.truncate(27, separator: ' ')
94
- # # => "Once upon a time in a..."
95
- #
96
- # 'Once upon a time in a world far far away'.truncate(27, separator: /\s/)
97
- # # => "Once upon a time in a..."
98
- #
99
- # The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
100
- # for a total length not exceeding <tt>length</tt>:
101
- #
102
- # 'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
103
- # # => "And they f... (continued)"
104
- #
105
- # adapted from
106
- #
107
- # <https://github.com/rails/rails/blob/7847a19f476fb9bee287681586d872ea43785e53/activesupport/lib/active_support/core_ext/string/filters.rb#L46>
108
- #
109
- def truncate(str, truncate_at, options = {})
110
- return str.dup unless str.length > truncate_at
111
-
112
- omission = options[:omission] || '...'
113
- length_with_room_for_omission = truncate_at - omission.length
114
- stop = \
115
- if options[:separator]
116
- str.rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
117
- else
118
- length_with_room_for_omission
119
- end
120
-
121
- "#{str[0, stop]}#{omission}"
122
- end
123
-
124
-
125
- # Cut the middle out of a string and stick an ellipsis in there instead.
126
- #
127
- # @param [String] string
128
- # Source string.
129
- #
130
- # @param [Fixnum] max
131
- # Max length to allow for the output string.
132
- #
133
- # @param [String] omission:
134
- # The string to stick in the middle where original contents were
135
- # removed. Defaults to the unicode ellipsis since I'm targeting the CLI
136
- # at the moment and it saves precious characters.
137
- #
138
- # @return [String]
139
- # String of at most `max` length with the middle chopped out if needed
140
- # to do so.
141
- def ellipsis string, max, omission: UNICODE_ELLIPSIS
142
- return string unless string.length > max
143
-
144
- trim_to = max - omission.length
145
-
146
- start = string[0, (trim_to / 2) + (trim_to % 2)]
147
- finish = string[-( (trim_to / 2) - (trim_to % 2) )..-1]
148
-
149
- start + omission + finish
150
- end
151
-
152
-
153
- # **EXPERIMENTAL!**
154
- #
155
- # Try to do "smart" job adding ellipsis to the middle of strings by
156
- # splitting them by a separator `split` - that defaults to `, ` - then
157
- # building the result up by bouncing back and forth between tokens at the
158
- # beginning and end of the string until we reach the `max` length limit.
159
- #
160
- # Intended to be used with possibly long single-line strings like
161
- # `#inspect` returns for complex objects, where tokens are commonly
162
- # separated by `, `, and producing a reasonably nice result that will fit
163
- # in a reasonable amount of space, like `rspec` output (which was the
164
- # motivation).
165
- #
166
- # If `string` is already less than `max` then it is just returned.
167
- #
168
- # If `string` doesn't contain `split` or just the first and last tokens
169
- # alone would push the result over `max` then falls back to
170
- # {NRSER.ellipsis}.
171
- #
172
- # If `max` is too small it's going to fall back nearly always... around
173
- # `64` has seemed like a decent place to start from screwing around on
174
- # the REPL a bit.
175
- #
176
- # @param [String] string
177
- # Source string.
178
- #
179
- # @param [Fixnum] max
180
- # Max length to allow for the output string. Result will usually be
181
- # *less* than this unless the fallback to {NRSER.ellipsis} kicks in.
182
- #
183
- # @param [String] omission:
184
- # The string to stick in the middle where original contents were
185
- # removed. Defaults to the unicode ellipsis since I'm targeting the CLI
186
- # at the moment and it saves precious characters.
187
- #
188
- # @param [String] split:
189
- # The string to tokenize the `string` parameter by. If you pass a
190
- # {Regexp} here it might work, it might loop out, maybe.
191
- #
192
- # @return [String]
193
- # String of at most `max` length with the middle chopped out if needed
194
- # to do so.
195
- #
196
- def smart_ellipsis string, max, omission: UNICODE_ELLIPSIS, split: ', '
197
- return string unless string.length > max
198
-
199
- unless string.include? split
200
- return ellipsis string, max, omission: omission
201
- end
202
-
203
- tokens = string.split split
204
-
205
- char_budget = max - omission.length
206
- start = tokens[0] + split
207
- finish = tokens[tokens.length - 1]
208
-
209
- if start.length + finish.length > char_budget
210
- return ellipsis string, max, omission: omission
211
- end
212
-
213
- next_start_index = 1
214
- next_finish_index = tokens.length - 2
215
- next_index_is = :start
216
- next_index = next_start_index
217
-
218
- while (
219
- start.length +
220
- finish.length +
221
- tokens[next_index].length +
222
- split.length
223
- ) <= char_budget do
224
- if next_index_is == :start
225
- start += tokens[next_index] + split
226
- next_start_index += 1
227
- next_index = next_finish_index
228
- next_index_is = :finish
229
- else # == :finish
230
- finish = tokens[next_index] + split + finish
231
- next_finish_index -= 1
232
- next_index = next_start_index
233
- next_index_is = :start
234
- end
235
- end
236
-
237
- start + omission + finish
238
-
239
- end # #method_name
240
-
241
-
242
-
243
- # Get the constant identified by a string.
244
- #
245
- # @example
246
- #
247
- # SomeClass == NRSER.constantize(SomeClass.name)
248
- #
249
- # Lifted from ActiveSupport.
250
- #
251
- # @param [String] camel_cased_word
252
- # The constant's camel-cased, double-colon-separated "name",
253
- # like "NRSER::Types::Array".
254
- #
255
- # @return [Object]
256
- #
257
- # @raise [NameError]
258
- # When the name is not in CamelCase or is not initialized.
259
- #
260
- def constantize(camel_cased_word)
261
- names = camel_cased_word.split('::')
262
-
263
- # Trigger a built-in NameError exception including the ill-formed constant in the message.
264
- Object.const_get(camel_cased_word) if names.empty?
265
-
266
- # Remove the first blank element in case of '::ClassName' notation.
267
- names.shift if names.size > 1 && names.first.empty?
268
-
269
- names.inject(Object) do |constant, name|
270
- if constant == Object
271
- constant.const_get(name)
272
- else
273
- candidate = constant.const_get(name)
274
- next candidate if constant.const_defined?(name, false)
275
- next candidate unless Object.const_defined?(name)
276
-
277
- # Go down the ancestors to check if it is owned directly. The check
278
- # stops when we reach Object or the end of ancestors tree.
279
- constant = constant.ancestors.inject do |const, ancestor|
280
- break const if ancestor == Object
281
- break ancestor if ancestor.const_defined?(name, false)
282
- const
283
- end
284
-
285
- # owner is in Object, so raise
286
- constant.const_get(name, false)
287
- end
288
- end
289
- end # constantize
290
-
291
- alias_method :to_const, :constantize
292
-
293
- end # class << self
294
- end # module NRSER
@@ -1,51 +0,0 @@
1
- ##
2
- # Functional methods that try to tell what format a string that
3
- # is presumed to encode structural data is encoded in.
4
- ##
5
-
6
- # Requirements
7
- # =======================================================================
8
-
9
- # Stdlib
10
- # -----------------------------------------------------------------------
11
-
12
- # Deps
13
- # -----------------------------------------------------------------------
14
-
15
- # Project / Package
16
- # -----------------------------------------------------------------------
17
-
18
-
19
- # Definitions
20
- # =======================================================================
21
-
22
- module NRSER
23
-
24
- # Constants
25
- # =====================================================================
26
-
27
- JSON_ARRAY_RE = /\A\s*\[.*\]\s*\z/m
28
-
29
- # Eigenclass (Singleton Class)
30
- # ========================================================================
31
- #
32
- class << self
33
-
34
- # Test if a string looks like it might encode an array in JSON format by
35
- # seeing if it's first non-whitespace character is `[` and last
36
- # non-whitespace character is `]`.
37
- #
38
- # @param [String] string
39
- # String to test.
40
- #
41
- # @return [Boolean]
42
- # `true` if we think `string` encodes a JSON array.
43
- #
44
- def looks_like_json_array? string
45
- !!( string =~ JSON_ARRAY_RE )
46
- end # #looks_like_json_array
47
-
48
- end # class << self (Eigenclass)
49
-
50
- end # module NRSER
51
-
@@ -1,92 +0,0 @@
1
- module NRSER
2
-
3
- # Eigenclass (Singleton Class)
4
- # ========================================================================
5
- #
6
- class << self
7
-
8
- # Create a new hash where all the values are the scalar "leaves" of the
9
- # possibly nested `hash` param. Leaves are keyed by "key path" arrays
10
- # representing the sequence of keys to dig that leaf out of the has param.
11
- #
12
- # In abstract, if `h` is the `hash` param and
13
- #
14
- # l = NRSER.leaves h
15
- #
16
- # then for each key `k` and corresponding value `v` in `l`
17
- #
18
- # h.dig( *k ) == v
19
- #
20
- # @example Simple "flat" hash
21
- #
22
- # NRSER.leaves( {a: 1, b: 2} )
23
- # => {
24
- # [:a] => 1,
25
- # [:b] => 2,
26
- # }
27
- #
28
- # @example Nested hash
29
- #
30
- # NRSER.leaves(
31
- # 1 => {
32
- # name: 'Neil',
33
- # fav_color: 'blue',
34
- # },
35
- # 2 => {
36
- # name: 'Mica',
37
- # fav_color: 'red',
38
- # }
39
- # )
40
- # # => {
41
- # # [1, :name] => 'Neil',
42
- # # [1, :fav_color] => 'blue',
43
- # # [2, :name] => 'Mica',
44
- # # [2, :fav_color] => 'red',
45
- # # }
46
- #
47
- # @param [#each_pair | (#each_index & #each_with_index)] tree
48
- #
49
- # @return [Hash<Array, Object>]
50
- #
51
- def leaves tree
52
- {}.tap { |results|
53
- _internal_leaves tree, path: [], results: results
54
- }
55
- end # #leaves
56
-
57
-
58
- private
59
- # ========================================================================
60
-
61
- # Internal recursive implementation for {NRSER.leaves}.
62
- #
63
- # @param [#each_pair | (#each_index & #each_with_index)] tree
64
- # Tree to walk.
65
- #
66
- # @param [Array] path
67
- # Key path down to `tree`.
68
- #
69
- # @param [Hash<Array, Object>] results
70
- # New hash to stick results in.
71
- #
72
- # @return [nil]
73
- #
74
- def _internal_leaves tree, path:, results:
75
- NRSER.each_branch( tree ) { |key, value|
76
- new_path = [*path, key]
77
-
78
- if NRSER::Types.tree.test value
79
- _internal_leaves value, path: new_path, results: results
80
- else
81
- results[new_path] = value
82
- end
83
- }
84
-
85
- nil
86
- end # #_internal_leaves
87
-
88
- # end private
89
-
90
- end # class << self (Eigenclass)
91
-
92
- end # module NRSER