psychgus 1.3.3 → 1.3.4
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/.yardopts +4 -0
- data/CHANGELOG.md +22 -7
- data/Gemfile +0 -18
- data/README.md +27 -28
- data/Rakefile +20 -42
- data/lib/psychgus.rb +169 -179
- data/lib/psychgus/blueberry.rb +28 -39
- data/lib/psychgus/ext.rb +6 -17
- data/lib/psychgus/ext/core_ext.rb +17 -28
- data/lib/psychgus/ext/node_ext.rb +13 -24
- data/lib/psychgus/ext/yaml_tree_ext.rb +23 -34
- data/lib/psychgus/stylables.rb +78 -89
- data/lib/psychgus/styled_document_stream.rb +14 -25
- data/lib/psychgus/styled_tree_builder.rb +90 -101
- data/lib/psychgus/styler.rb +33 -44
- data/lib/psychgus/stylers.rb +67 -78
- data/lib/psychgus/super_sniffer.rb +111 -123
- data/lib/psychgus/super_sniffer/parent.rb +42 -51
- data/lib/psychgus/version.rb +4 -16
- data/psychgus.gemspec +39 -43
- data/test/blueberry_test.rb +30 -41
- data/test/psychgus_test.rb +51 -60
- data/test/psychgus_tester.rb +23 -31
- data/test/sniffer_test.rb +18 -32
- data/test/styler_test.rb +20 -31
- data/test/stylers_test.rb +32 -43
- metadata +15 -14
@@ -1,22 +1,11 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
1
|
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
3
|
|
4
4
|
#--
|
5
5
|
# This file is part of Psychgus.
|
6
|
-
# Copyright (c) 2019 Jonathan Bradley Whited
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# it under the terms of the GNU Lesser General Public License as published by
|
10
|
-
# the Free Software Foundation, either version 3 of the License, or
|
11
|
-
# (at your option) any later version.
|
12
|
-
#
|
13
|
-
# Psychgus is distributed in the hope that it will be useful,
|
14
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
-
# GNU Lesser General Public License for more details.
|
17
|
-
#
|
18
|
-
# You should have received a copy of the GNU Lesser General Public License
|
19
|
-
# along with Psychgus. If not, see <http://www.gnu.org/licenses/>.
|
6
|
+
# Copyright (c) 2019-2021 Jonathan Bradley Whited
|
7
|
+
#
|
8
|
+
# SPDX-License-Identifier: LGPL-3.0-or-later
|
20
9
|
#++
|
21
10
|
|
22
11
|
|
@@ -26,12 +15,11 @@ module Psychgus
|
|
26
15
|
class SuperSniffer
|
27
16
|
###
|
28
17
|
# An empty {SuperSniffer} used for speed when you don't need sniffing in {StyledTreeBuilder}.
|
29
|
-
#
|
30
|
-
# @author Jonathan Bradley Whited
|
18
|
+
#
|
19
|
+
# @author Jonathan Bradley Whited
|
31
20
|
# @since 1.0.0
|
32
21
|
###
|
33
22
|
class Empty < SuperSniffer
|
34
|
-
def initialize(*) end
|
35
23
|
def add_alias(*) end
|
36
24
|
def add_scalar(*) end
|
37
25
|
def end_document(*) end
|
@@ -44,12 +32,12 @@ module Psychgus
|
|
44
32
|
def start_stream(*) end
|
45
33
|
end
|
46
34
|
end
|
47
|
-
|
35
|
+
|
48
36
|
###
|
49
37
|
# This is used in {StyledTreeBuilder} to "sniff" information about the YAML.
|
50
|
-
#
|
38
|
+
#
|
51
39
|
# Then this information can be used in a {Styler} and/or a {Blueberry}.
|
52
|
-
#
|
40
|
+
#
|
53
41
|
# Most information is straightforward:
|
54
42
|
# - {#aliases} # Array of Psych::Nodes::Alias processed so far
|
55
43
|
# - {#documents} # Array of Psych::Nodes::Document processed so far
|
@@ -58,17 +46,17 @@ module Psychgus
|
|
58
46
|
# - {#scalars} # Array of Psych::Nodes::Scalar processed so far
|
59
47
|
# - {#sequences} # Array of Psych::Nodes::Sequence processed so far
|
60
48
|
# - {#streams} # Array of Psych::Nodes::Stream processed so far
|
61
|
-
#
|
49
|
+
#
|
62
50
|
# {#parent} is the current {SuperSniffer::Parent} of the node being processed,
|
63
51
|
# which is an empty Parent for the first node (not nil).
|
64
|
-
#
|
52
|
+
#
|
65
53
|
# {#parents} are all of the (grand){SuperSniffer::Parent}(s) for the current node,
|
66
54
|
# which is an Array that just contains an empty Parent for the first node.
|
67
|
-
#
|
55
|
+
#
|
68
56
|
# A parent is a Mapping or Sequence, or a Key (Scalar) in a Mapping.
|
69
|
-
#
|
57
|
+
#
|
70
58
|
# {#level} and {#position} can be best understood by an example.
|
71
|
-
#
|
59
|
+
#
|
72
60
|
# If you have this YAML:
|
73
61
|
# Burgers:
|
74
62
|
# Classic:
|
@@ -87,10 +75,10 @@ module Psychgus
|
|
87
75
|
# - Mushrooms
|
88
76
|
# - [Lettuce, Onions, Pickles, Tomatoes]
|
89
77
|
# - [[Ketchup,Mustard], [Salt,Pepper]]
|
90
|
-
#
|
78
|
+
#
|
91
79
|
# Then the levels and positions will be as follows:
|
92
80
|
# # (level:position):current_node - <parent:(parent_level:parent_position)>
|
93
|
-
#
|
81
|
+
#
|
94
82
|
# (1:1):Psych::Nodes::Stream - <root:(0:0)>
|
95
83
|
# (1:1):Psych::Nodes::Document - <stream:(1:1)>
|
96
84
|
# (1:1):Psych::Nodes::Mapping - <doc:(1:1)>
|
@@ -137,23 +125,23 @@ module Psychgus
|
|
137
125
|
# (5:2):Psych::Nodes::Sequence - <seq:(4:3)>
|
138
126
|
# (6:1):Salt - <seq:(5:2)>
|
139
127
|
# (6:2):Pepper - <seq:(5:2)>
|
140
|
-
#
|
128
|
+
#
|
141
129
|
# "The Super Sniffer" is the nickname for Gus's nose from the TV show Psych
|
142
130
|
# because he has a very refined sense of smell.
|
143
|
-
#
|
131
|
+
#
|
144
132
|
# @note You should never call the methods that are not readers, like {#add_alias}, {#start_mapping}, etc.
|
145
133
|
# unless you are extending this class (creating a subclass).
|
146
|
-
#
|
147
|
-
# @author Jonathan Bradley Whited
|
134
|
+
#
|
135
|
+
# @author Jonathan Bradley Whited
|
148
136
|
# @since 1.0.0
|
149
|
-
#
|
137
|
+
#
|
150
138
|
# @see StyledTreeBuilder
|
151
139
|
# @see Styler
|
152
140
|
# @see Blueberry#psychgus_stylers
|
153
141
|
###
|
154
142
|
class SuperSniffer
|
155
|
-
EMPTY = Empty.new
|
156
|
-
|
143
|
+
EMPTY = Empty.new.freeze
|
144
|
+
|
157
145
|
attr_reader :aliases # @return [Array<Psych::Nodes::Alias>] the aliases processed so far
|
158
146
|
attr_reader :documents # @return [Array<Psych::Nodes::Document>] the documents processed so far
|
159
147
|
attr_reader :level # @return [Integer] the current level
|
@@ -165,9 +153,9 @@ module Psychgus
|
|
165
153
|
attr_reader :scalars # @return [Array<Psych::Nodes::Scalar>] the scalars processed so far
|
166
154
|
attr_reader :sequences # @return [Array<Psych::Nodes::Sequence>] the sequences processed so far
|
167
155
|
attr_reader :streams # @return [Array<Psych::Nodes::Stream>] the streams processed so far
|
168
|
-
|
156
|
+
|
169
157
|
# Initialize this class for sniffing.
|
170
|
-
def initialize
|
158
|
+
def initialize
|
171
159
|
@aliases = []
|
172
160
|
@documents = []
|
173
161
|
@level = 0
|
@@ -179,240 +167,240 @@ module Psychgus
|
|
179
167
|
@scalars = []
|
180
168
|
@sequences = []
|
181
169
|
@streams = []
|
182
|
-
|
170
|
+
|
183
171
|
# Do not pass in "top_level: true"
|
184
172
|
start_parent(nil,debug_tag: :root)
|
185
173
|
end
|
186
|
-
|
174
|
+
|
187
175
|
# Add a Psych::Nodes::Alias to this class only (not to the YAML).
|
188
|
-
#
|
176
|
+
#
|
189
177
|
# A {Styler} should probably never call this.
|
190
|
-
#
|
178
|
+
#
|
191
179
|
# @param node [Psych::Nodes::Alias] the alias to add
|
192
|
-
#
|
180
|
+
#
|
193
181
|
# @see add_child
|
194
182
|
def add_alias(node)
|
195
183
|
add_child(node)
|
196
184
|
@aliases.push(node)
|
197
185
|
end
|
198
|
-
|
186
|
+
|
199
187
|
# Add a Psych::Nodes::Scalar to this class only (not to the YAML).
|
200
|
-
#
|
188
|
+
#
|
201
189
|
# A {Styler} should probably never call this.
|
202
|
-
#
|
190
|
+
#
|
203
191
|
# @param node [Psych::Nodes::Scalar] the scalar to add
|
204
|
-
#
|
192
|
+
#
|
205
193
|
# @see add_child
|
206
194
|
def add_scalar(node)
|
207
195
|
add_child(node)
|
208
196
|
@scalars.push(node)
|
209
197
|
end
|
210
|
-
|
198
|
+
|
211
199
|
# End a Psych::Nodes::Document started with {#start_document}.
|
212
|
-
#
|
200
|
+
#
|
213
201
|
# Pops off a parent from {#parents} and sets {#parent} to the last one.
|
214
202
|
# {#level} and {#position} are reset according to the last parent.
|
215
|
-
#
|
203
|
+
#
|
216
204
|
# A {Styler} should probably never call this.
|
217
|
-
def end_document
|
205
|
+
def end_document
|
218
206
|
end_parent(top_level: true)
|
219
207
|
end
|
220
|
-
|
208
|
+
|
221
209
|
# End a Psych::Nodes::Mapping started with {#start_mapping}.
|
222
|
-
#
|
210
|
+
#
|
223
211
|
# Pops off a parent from {#parents} and sets {#parent} to the last one.
|
224
212
|
# {#level} and {#position} are reset according to the last parent.
|
225
|
-
#
|
213
|
+
#
|
226
214
|
# A {Styler} should probably never call this.
|
227
|
-
#
|
215
|
+
#
|
228
216
|
# @see end_parent
|
229
|
-
def end_mapping
|
217
|
+
def end_mapping
|
230
218
|
end_parent(mapping_value: true)
|
231
219
|
end
|
232
|
-
|
220
|
+
|
233
221
|
# End a Psych::Nodes::Sequence started with {#start_sequence}.
|
234
|
-
#
|
222
|
+
#
|
235
223
|
# Pops off a parent from {#parents} and sets {#parent} to the last one.
|
236
224
|
# {#level} and {#position} are reset according to the last parent.
|
237
|
-
#
|
225
|
+
#
|
238
226
|
# A {Styler} should probably never call this.
|
239
|
-
#
|
227
|
+
#
|
240
228
|
# @see end_parent
|
241
|
-
def end_sequence
|
229
|
+
def end_sequence
|
242
230
|
end_parent(mapping_value: true)
|
243
231
|
end
|
244
|
-
|
232
|
+
|
245
233
|
# End a Psych::Nodes::Stream started with {#start_stream}.
|
246
|
-
#
|
234
|
+
#
|
247
235
|
# Pops off a parent from {#parents} and sets {#parent} to the last one.
|
248
236
|
# {#level} and {#position} are reset according to the last parent.
|
249
|
-
#
|
237
|
+
#
|
250
238
|
# A {Styler} should probably never call this.
|
251
|
-
def end_stream
|
239
|
+
def end_stream
|
252
240
|
end_parent(top_level: true)
|
253
241
|
end
|
254
|
-
|
242
|
+
|
255
243
|
# Start a Psych::Nodes::Document.
|
256
|
-
#
|
244
|
+
#
|
257
245
|
# Creates a {SuperSniffer::Parent}, sets {#parent} to it, and adds it to {#parents}.
|
258
246
|
# {#level} and {#position} are incremented/set accordingly.
|
259
|
-
#
|
247
|
+
#
|
260
248
|
# A {Styler} should probably never call this.
|
261
|
-
#
|
249
|
+
#
|
262
250
|
# @param node [Psych::Nodes::Document] the Document to start
|
263
|
-
#
|
251
|
+
#
|
264
252
|
# @see start_parent
|
265
253
|
def start_document(node)
|
266
254
|
start_parent(node,debug_tag: :doc,top_level: true)
|
267
255
|
@documents.push(node)
|
268
256
|
end
|
269
|
-
|
257
|
+
|
270
258
|
# Start a Psych::Nodes::Mapping.
|
271
|
-
#
|
259
|
+
#
|
272
260
|
# Creates a {SuperSniffer::Parent}, sets {#parent} to it, and adds it to {#parents}.
|
273
261
|
# {#level} and {#position} are incremented/set accordingly.
|
274
|
-
#
|
262
|
+
#
|
275
263
|
# A {Styler} should probably never call this.
|
276
|
-
#
|
264
|
+
#
|
277
265
|
# @param node [Psych::Nodes::Mapping] the Mapping to start
|
278
|
-
#
|
266
|
+
#
|
279
267
|
# @see start_parent
|
280
268
|
def start_mapping(node)
|
281
269
|
start_parent(node,debug_tag: :map,child_type: :key)
|
282
270
|
@mappings.push(node)
|
283
271
|
end
|
284
|
-
|
272
|
+
|
285
273
|
# Start a Psych::Nodes::Sequence.
|
286
|
-
#
|
274
|
+
#
|
287
275
|
# Creates a {SuperSniffer::Parent}, sets {#parent} to it, and adds it to {#parents}.
|
288
276
|
# {#level} and {#position} are incremented/set accordingly.
|
289
|
-
#
|
277
|
+
#
|
290
278
|
# A {Styler} should probably never call this.
|
291
|
-
#
|
279
|
+
#
|
292
280
|
# @param node [Psych::Nodes::Sequence] the Sequence to start
|
293
|
-
#
|
281
|
+
#
|
294
282
|
# @see start_parent
|
295
283
|
def start_sequence(node)
|
296
284
|
start_parent(node,debug_tag: :seq)
|
297
285
|
@sequences.push(node)
|
298
286
|
end
|
299
|
-
|
287
|
+
|
300
288
|
# Start a Psych::Nodes::Stream.
|
301
|
-
#
|
289
|
+
#
|
302
290
|
# Creates a {SuperSniffer::Parent}, sets {#parent} to it, and adds it to {#parents}.
|
303
291
|
# {#level} and {#position} are incremented/set accordingly.
|
304
|
-
#
|
292
|
+
#
|
305
293
|
# A {Styler} should probably never call this.
|
306
|
-
#
|
294
|
+
#
|
307
295
|
# @param node [Psych::Nodes::Stream] the Stream to start
|
308
|
-
#
|
296
|
+
#
|
309
297
|
# @see start_parent
|
310
298
|
def start_stream(node)
|
311
299
|
start_parent(node,debug_tag: :stream,top_level: true)
|
312
300
|
@streams.push(node)
|
313
301
|
end
|
314
|
-
|
302
|
+
|
315
303
|
protected
|
316
|
-
|
304
|
+
|
317
305
|
# Add a non-parent node.
|
318
|
-
#
|
306
|
+
#
|
319
307
|
# This will increment {#position} accordingly, and if the child is a Key to a Mapping,
|
320
308
|
# create a fake "{SuperSniffer::Parent}".
|
321
|
-
#
|
309
|
+
#
|
322
310
|
# @param node [Psych::Nodes::Node] the non-parent Node to add
|
323
|
-
#
|
311
|
+
#
|
324
312
|
# @see end_mapping_value
|
325
313
|
def add_child(node)
|
326
|
-
if !@parent.nil?
|
314
|
+
if !@parent.nil?
|
327
315
|
# Fake a "parent" if necessary
|
328
316
|
case @parent.child_type
|
329
317
|
when :key
|
330
318
|
start_mapping_key(node)
|
331
319
|
return
|
332
320
|
when :value
|
333
|
-
end_mapping_value
|
321
|
+
end_mapping_value
|
334
322
|
return
|
335
323
|
else
|
336
324
|
@parent.child_position += 1
|
337
325
|
end
|
338
326
|
end
|
339
|
-
|
327
|
+
|
340
328
|
@position += 1
|
341
|
-
|
329
|
+
|
342
330
|
@nodes.push(node)
|
343
331
|
end
|
344
|
-
|
332
|
+
|
345
333
|
# End a fake "{SuperSniffer::Parent}" that is a Key/Value to a Mapping.
|
346
|
-
#
|
334
|
+
#
|
347
335
|
# @see add_child
|
348
|
-
def end_mapping_value
|
349
|
-
end_parent
|
350
|
-
|
351
|
-
@parent.child_type = :key unless @parent.nil?
|
336
|
+
def end_mapping_value
|
337
|
+
end_parent # Do not pass in "mapping_value: true" and/or "top_level: true"
|
338
|
+
|
339
|
+
@parent.child_type = :key unless @parent.nil?
|
352
340
|
end
|
353
|
-
|
341
|
+
|
354
342
|
# End a {SuperSniffer::Parent}.
|
355
|
-
#
|
343
|
+
#
|
356
344
|
# Pops off a parent from {#parents} and sets {#parent} to the last one.
|
357
345
|
# {#level} and {#position} are reset according to the last parent.
|
358
|
-
#
|
346
|
+
#
|
359
347
|
# @param mapping_value [true,false] true if parent can be the value of a Mapping's key
|
360
348
|
# @param top_level [true,false] true if a top-level parent (i.e., encapsulating the main data)
|
361
349
|
def end_parent(mapping_value: false,top_level: false)
|
362
|
-
@parents.pop
|
350
|
+
@parents.pop
|
363
351
|
@parent = @parents.last
|
364
|
-
|
352
|
+
|
365
353
|
@level = top_level ? 1 : (@level - 1)
|
366
|
-
|
367
|
-
if !@parent.nil?
|
354
|
+
|
355
|
+
if !@parent.nil?
|
368
356
|
@parent.child_position += 1
|
369
357
|
@position = @parent.child_position
|
370
|
-
|
358
|
+
|
371
359
|
# add_child() will not be called again, so end a fake "parent" manually with a fake "value"
|
372
360
|
# - This is necessary for any parents that can be the value of a map's key (e.g., Sequence)
|
373
|
-
end_mapping_value
|
361
|
+
end_mapping_value if mapping_value && !@parent.child_type.nil?
|
374
362
|
end
|
375
363
|
end
|
376
|
-
|
364
|
+
|
377
365
|
# Start a fake "{SuperSniffer::Parent}" that is a Key/Value to a Mapping.
|
378
|
-
#
|
366
|
+
#
|
379
367
|
# Creates a {SuperSniffer::Parent}, sets {#parent} to it, and adds it to {#parents}.
|
380
368
|
# {#level} and {#position} are incremented/set accordingly.
|
381
|
-
#
|
369
|
+
#
|
382
370
|
# @param node [Psych::Nodes::Node] the Node to start
|
383
|
-
#
|
371
|
+
#
|
384
372
|
# @see start_parent
|
385
373
|
def start_mapping_key(node)
|
386
374
|
debug_tag = nil
|
387
|
-
|
375
|
+
|
388
376
|
# Value must be first because Scalar also has an anchor
|
389
377
|
if node.respond_to?(:value)
|
390
378
|
debug_tag = node.value
|
391
379
|
elsif node.respond_to?(:anchor)
|
392
380
|
debug_tag = node.anchor
|
393
381
|
end
|
394
|
-
|
395
|
-
debug_tag = :noface if debug_tag.nil?
|
396
|
-
|
382
|
+
|
383
|
+
debug_tag = :noface if debug_tag.nil?
|
384
|
+
|
397
385
|
start_parent(node,debug_tag: debug_tag,child_type: :value)
|
398
386
|
end
|
399
|
-
|
387
|
+
|
400
388
|
# Start a {SuperSniffer::Parent}.
|
401
|
-
#
|
389
|
+
#
|
402
390
|
# Creates a {SuperSniffer::Parent}, sets {#parent} to it, and adds it to {#parents}.
|
403
391
|
# {#level} and {#position} are incremented/set accordingly.
|
404
|
-
#
|
392
|
+
#
|
405
393
|
# @param node [Psych::Nodes::Node] the parent Node to start
|
406
394
|
# @param top_level [true,false] true if a top-level parent (i.e., encapsulating the main data)
|
407
395
|
# @param extra [Hash] the extra keyword args to pass to {SuperSniffer::Parent#initialize}
|
408
|
-
#
|
396
|
+
#
|
409
397
|
# @see SuperSniffer::Parent#initialize
|
410
398
|
def start_parent(node,top_level: false,**extra)
|
411
399
|
@parent = Parent.new(self,node,**extra)
|
412
|
-
|
400
|
+
|
413
401
|
@parents.push(@parent)
|
414
|
-
@nodes.push(node) unless node.nil?
|
415
|
-
|
402
|
+
@nodes.push(node) unless node.nil?
|
403
|
+
|
416
404
|
if top_level
|
417
405
|
@level = 1
|
418
406
|
@position = @parent.position
|