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,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