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.
- checksums.yaml +4 -4
- data/lib/nrser.rb +56 -12
- data/lib/nrser/collection.rb +4 -7
- data/lib/nrser/ext.rb +5 -0
- data/lib/nrser/{refinements → ext}/enumerable.rb +11 -9
- data/lib/nrser/ext/pathname.rb +74 -0
- data/lib/nrser/{refinements → ext}/tree.rb +2 -26
- data/lib/nrser/functions.rb +18 -0
- data/lib/nrser/{array.rb → functions/array.rb} +2 -3
- data/lib/nrser/{binding.rb → functions/binding.rb} +0 -2
- data/lib/nrser/functions/enumerable.rb +355 -0
- data/lib/nrser/functions/enumerable/find_all_map.rb +33 -0
- data/lib/nrser/functions/enumerable/find_map.rb +53 -0
- data/lib/nrser/functions/exception.rb +17 -0
- data/lib/nrser/{hash.rb → functions/hash.rb} +0 -0
- data/lib/nrser/functions/hash/bury.rb +147 -0
- data/lib/nrser/{hash → functions/hash}/deep_merge.rb +5 -5
- data/lib/nrser/{hash → functions/hash}/except_keys.rb +2 -0
- data/lib/nrser/{hash → functions/hash}/guess_label_key_type.rb +3 -1
- data/lib/nrser/{hash → functions/hash}/slice_keys.rb +3 -1
- data/lib/nrser/{hash → functions/hash}/stringify_keys.rb +2 -0
- data/lib/nrser/{hash → functions/hash}/symbolize_keys.rb +3 -1
- data/lib/nrser/{hash → functions/hash}/transform_keys.rb +3 -1
- data/lib/nrser/functions/merge_by.rb +29 -0
- data/lib/nrser/{object.rb → functions/object.rb} +0 -0
- data/lib/nrser/{object → functions/object}/as_array.rb +2 -0
- data/lib/nrser/{object → functions/object}/as_hash.rb +7 -5
- data/lib/nrser/{object → functions/object}/truthy.rb +46 -7
- data/lib/nrser/{open_struct.rb → functions/open_struct.rb} +0 -0
- data/lib/nrser/functions/path.rb +150 -0
- data/lib/nrser/{proc.rb → functions/proc.rb} +1 -22
- data/lib/nrser/functions/string.rb +297 -0
- data/lib/nrser/functions/string/looks_like.rb +44 -0
- data/lib/nrser/{text.rb → functions/text.rb} +0 -0
- data/lib/nrser/{text → functions/text}/indentation.rb +2 -16
- data/lib/nrser/{text → functions/text}/lines.rb +1 -2
- data/lib/nrser/{text → functions/text}/word_wrap.rb +2 -4
- data/lib/nrser/{tree.rb → functions/tree.rb} +0 -0
- data/lib/nrser/{tree → functions/tree}/each_branch.rb +6 -7
- data/lib/nrser/functions/tree/leaves.rb +92 -0
- data/lib/nrser/{tree → functions/tree}/map_branches.rb +31 -32
- data/lib/nrser/functions/tree/map_leaves.rb +56 -0
- data/lib/nrser/{tree → functions/tree}/map_tree.rb +9 -20
- data/lib/nrser/{tree → functions/tree}/transform.rb +0 -10
- data/lib/nrser/logger.rb +9 -10
- data/lib/nrser/message.rb +3 -7
- data/lib/nrser/meta.rb +2 -0
- data/lib/nrser/meta/class_attrs.rb +3 -9
- data/lib/nrser/meta/props.rb +19 -19
- data/lib/nrser/meta/props/base.rb +4 -10
- data/lib/nrser/meta/props/prop.rb +12 -28
- data/lib/nrser/no_arg.rb +1 -3
- data/lib/nrser/refinements.rb +5 -0
- data/lib/nrser/refinements/array.rb +5 -17
- data/lib/nrser/refinements/enumerator.rb +1 -3
- data/lib/nrser/refinements/hash.rb +3 -15
- data/lib/nrser/refinements/object.rb +2 -2
- data/lib/nrser/refinements/open_struct.rb +0 -2
- data/lib/nrser/refinements/pathname.rb +3 -46
- data/lib/nrser/refinements/set.rb +2 -6
- data/lib/nrser/refinements/string.rb +2 -2
- data/lib/nrser/rspex.rb +16 -13
- data/lib/nrser/types.rb +6 -20
- data/lib/nrser/types/any.rb +0 -1
- data/lib/nrser/types/booleans.rb +1 -1
- data/lib/nrser/types/combinators.rb +5 -5
- data/lib/nrser/types/in.rb +0 -21
- data/lib/nrser/types/responds.rb +1 -0
- data/lib/nrser/types/trees.rb +1 -0
- data/lib/nrser/version.rb +2 -3
- data/spec/nrser/{template_spec.rb → functions/binding/template_spec.rb} +0 -0
- data/spec/nrser/functions/enumerable/find_all_map_spec.rb +28 -0
- data/spec/nrser/functions/enumerable/find_bounded_spec.rb +70 -0
- data/spec/nrser/functions/enumerable/find_map_spec.rb +38 -0
- data/spec/nrser/functions/enumerable/find_only_spec.rb +25 -0
- data/spec/nrser/functions/enumerable/to_h_by_spec.rb +28 -0
- data/spec/nrser/{format_exception_spec.rb → functions/exception/format_exception_spec.rb} +0 -0
- data/spec/nrser/{hash → functions/hash}/bury_spec.rb +0 -0
- data/spec/nrser/{hash → functions/hash}/guess_label_key_type_spec.rb +0 -0
- data/spec/nrser/{hash_spec.rb → functions/hash_spec.rb} +0 -7
- data/spec/nrser/{merge_by_spec.rb → functions/merge_by_spec.rb} +0 -0
- data/spec/nrser/{truthy_spec.rb → functions/object/truthy_spec.rb} +0 -0
- data/spec/nrser/{open_struct_spec.rb → functions/open_struct_spec.rb} +0 -0
- data/spec/nrser/{string → functions/string}/common_prefix_spec.rb +0 -0
- data/spec/nrser/{string → functions/string}/looks_like_spec.rb +0 -0
- data/spec/nrser/{truncate_spec.rb → functions/string/truncate_spec.rb} +0 -0
- data/spec/nrser/{text → functions/text}/dedent/gotchas_spec.rb +0 -0
- data/spec/nrser/{text → functions/text}/dedent_spec.rb +0 -0
- data/spec/nrser/{indent_spec.rb → functions/text/indent_spec.rb} +0 -0
- data/spec/nrser/{tree → functions/tree}/each_branch_spec.rb +0 -0
- data/spec/nrser/{tree → functions/tree}/leaves_spec.rb +0 -0
- data/spec/nrser/{tree → functions/tree}/map_branch_spec.rb +0 -0
- data/spec/nrser/{tree → functions/tree}/map_tree_spec.rb +0 -0
- data/spec/nrser/{tree → functions/tree}/transform_spec.rb +0 -0
- data/spec/nrser/{tree → functions/tree}/transformer_spec.rb +0 -0
- data/spec/nrser/meta/class_attrs_spec.rb +12 -14
- data/spec/spec_helper.rb +2 -3
- metadata +136 -110
- data/lib/nrser/enumerable.rb +0 -288
- data/lib/nrser/exception.rb +0 -7
- data/lib/nrser/hash/bury.rb +0 -154
- data/lib/nrser/merge_by.rb +0 -26
- data/lib/nrser/string.rb +0 -294
- data/lib/nrser/string/looks_like.rb +0 -51
- data/lib/nrser/tree/leaves.rb +0 -92
- data/lib/nrser/tree/map_leaves.rb +0 -63
- data/spec/nrser/enumerable_spec.rb +0 -111
data/lib/nrser/merge_by.rb
DELETED
|
@@ -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
|
-
|
data/lib/nrser/tree/leaves.rb
DELETED
|
@@ -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
|