psych-pure 0.1.1 → 0.1.2
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/CHANGELOG.md +9 -1
- data/lib/psych/pure/version.rb +1 -1
- data/lib/psych/pure.rb +363 -170
- data/psych-pure.gemspec +1 -0
- metadata +22 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fb90297ca479adfe033c6d8db3544ec41c8e8083f23884e990de4ee2d8eb402
|
4
|
+
data.tar.gz: 8f895282ff5733903665ddcd0d1be2a28696dce0380242f8804ad42ce45123fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ad4470231f6587e40da0fe271ef65a1ba441f70ecc87bd7900f4fcc17a2da4be63396b73d15a131359977b62e53cfbd9d333969dbd920e984c6647741bfab34
|
7
|
+
data.tar.gz: 17965e31133a24c3f14c9d452884665f0d40e0c2e3edbf573fc59db5888471fb934caed61b9bed836287253061e549e540e4b79085360f9ec7a9a8082f4b7107
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [0.1.2] - 2025-03-04
|
10
|
+
|
11
|
+
- Fix up comment dumping to not drift around objects.
|
12
|
+
- Rely on source formatting when possible for scalar values.
|
13
|
+
- Fix up multi-line literals with the "keep" flag (|+).
|
14
|
+
- Fix up aliasing hashes that have comments loaded.
|
15
|
+
|
9
16
|
## [0.1.1] - 2025-02-13
|
10
17
|
|
11
18
|
- Fix up comment handling to preserve within hashes.
|
@@ -18,6 +25,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
18
25
|
|
19
26
|
- 🎉 Initial release. 🎉
|
20
27
|
|
21
|
-
[unreleased]: https://github.com/kddnewton/psych-pure/compare/v0.1.
|
28
|
+
[unreleased]: https://github.com/kddnewton/psych-pure/compare/v0.1.2...HEAD
|
29
|
+
[0.1.2]: https://github.com/kddnewton/psych-pure/compare/v0.1.1...v0.1.2
|
22
30
|
[0.1.1]: https://github.com/kddnewton/psych-pure/compare/v0.1.0...v0.1.1
|
23
31
|
[0.1.0]: https://github.com/kddnewton/psych-pure/compare/24de62...v0.1.0
|
data/lib/psych/pure/version.rb
CHANGED
data/lib/psych/pure.rb
CHANGED
@@ -147,43 +147,42 @@ module Psych
|
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
150
|
-
# Wraps a Ruby object with its
|
151
|
-
class
|
152
|
-
|
150
|
+
# Wraps a Ruby object with its node from the source input.
|
151
|
+
class LoadedObject < SimpleDelegator
|
152
|
+
# The node associated with the object.
|
153
|
+
attr_reader :psych_node
|
153
154
|
|
154
|
-
|
155
|
-
|
155
|
+
# Whether or not this object has been modified. If it has, then we cannot
|
156
|
+
# rely on the source formatting, and need to format it ourselves.
|
157
|
+
attr_reader :dirty
|
158
|
+
|
159
|
+
def initialize(object, psych_node, dirty = false)
|
156
160
|
super(object)
|
161
|
+
@psych_node = psych_node
|
162
|
+
@dirty = dirty
|
157
163
|
end
|
158
164
|
end
|
159
165
|
|
160
|
-
# Wraps a Ruby hash with its
|
161
|
-
class
|
162
|
-
|
163
|
-
|
164
|
-
def initialize(object, psych_comments, psych_key_comments = {})
|
165
|
-
@psych_comments = psych_comments
|
166
|
-
@psych_key_comments = psych_key_comments
|
167
|
-
commentless = {}
|
166
|
+
# Wraps a Ruby hash with its node from the source input.
|
167
|
+
class LoadedHash < SimpleDelegator
|
168
|
+
# The node associated with the hash.
|
169
|
+
attr_reader :psych_node
|
168
170
|
|
169
|
-
|
170
|
-
|
171
|
-
@psych_key_comments[key.__getobj__] = key.psych_comments
|
172
|
-
commentless[key.__getobj__] = value
|
173
|
-
else
|
174
|
-
commentless[key] = value
|
175
|
-
end
|
176
|
-
end
|
171
|
+
# The nodes associated with the keys of the hash.
|
172
|
+
attr_reader :psych_node_keys
|
177
173
|
|
178
|
-
|
174
|
+
def initialize(object, psych_node, psych_node_keys = {})
|
175
|
+
super(object)
|
176
|
+
@psych_node = psych_node
|
177
|
+
@psych_node_keys = psych_node_keys
|
179
178
|
end
|
180
179
|
|
181
180
|
def []=(key, value)
|
182
181
|
if (previous = self[key])
|
183
|
-
if previous.is_a?(
|
184
|
-
value =
|
185
|
-
elsif previous.is_a?(
|
186
|
-
value =
|
182
|
+
if previous.is_a?(LoadedObject)
|
183
|
+
value = LoadedObject.new(value, previous.psych_node, true)
|
184
|
+
elsif previous.is_a?(LoadedHash)
|
185
|
+
value = LoadedHash.new(value, previous.psych_node, previous.psych_node_keys)
|
187
186
|
end
|
188
187
|
end
|
189
188
|
|
@@ -304,9 +303,18 @@ module Psych
|
|
304
303
|
# Extend the document stream to be able to attach comments to the
|
305
304
|
# document.
|
306
305
|
module DocumentStream
|
306
|
+
def start_document(version, tag_directives, implicit)
|
307
|
+
node = Nodes::Document.new(version, tag_directives, implicit)
|
308
|
+
set_start_location(node)
|
309
|
+
push(node)
|
310
|
+
end
|
311
|
+
|
307
312
|
def end_document(implicit_end = !streaming?)
|
308
313
|
@last.implicit_end = implicit_end
|
309
|
-
|
314
|
+
node = pop
|
315
|
+
set_end_location(node)
|
316
|
+
attach_comments(node)
|
317
|
+
@block.call(node)
|
310
318
|
end
|
311
319
|
end
|
312
320
|
|
@@ -341,16 +349,38 @@ module Psych
|
|
341
349
|
def initialize(ss, class_loader, symbolize_names: false, freeze: false, comments: false)
|
342
350
|
super(ss, class_loader, symbolize_names: symbolize_names, freeze: freeze)
|
343
351
|
@comments = comments
|
352
|
+
@nodeless_objs = {}.compare_by_identity
|
353
|
+
@nodeless_keys = {}.compare_by_identity
|
344
354
|
end
|
345
355
|
|
346
356
|
def accept(node)
|
347
357
|
result = super
|
348
358
|
|
349
359
|
if @comments
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
360
|
+
case result
|
361
|
+
when LoadedObject, LoadedHash
|
362
|
+
# skip
|
363
|
+
when Hash
|
364
|
+
if !@nodeless_objs.key?(result)
|
365
|
+
nodeless_obj = {}
|
366
|
+
nodeless_key = {}
|
367
|
+
|
368
|
+
result.each do |key, value|
|
369
|
+
if key.is_a?(LoadedObject) || key.is_a?(LoadedHash)
|
370
|
+
nodeless_obj[key.__getobj__] = value
|
371
|
+
nodeless_key[key.__getobj__] = key
|
372
|
+
else
|
373
|
+
nodeless_obj[key] = value
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
@nodeless_objs[result] = nodeless_obj
|
378
|
+
@nodeless_keys[result] = nodeless_key
|
379
|
+
end
|
380
|
+
|
381
|
+
result = LoadedHash.new(@nodeless_objs.fetch(result), node, @nodeless_keys.fetch(result))
|
382
|
+
else
|
383
|
+
result = LoadedObject.new(result, node)
|
354
384
|
end
|
355
385
|
end
|
356
386
|
|
@@ -362,7 +392,7 @@ module Psych
|
|
362
392
|
module ToRubySingleton
|
363
393
|
def create(symbolize_names: false, freeze: false, strict_integer: false, comments: false)
|
364
394
|
class_loader = ClassLoader.new
|
365
|
-
scanner
|
395
|
+
scanner = ScalarScanner.new(class_loader, strict_integer: strict_integer)
|
366
396
|
new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze, comments: comments)
|
367
397
|
end
|
368
398
|
end
|
@@ -475,7 +505,7 @@ module Psych
|
|
475
505
|
end
|
476
506
|
|
477
507
|
def accept(handler)
|
478
|
-
handler.event_location(*@location)
|
508
|
+
handler.event_location(*@location.trim)
|
479
509
|
handler.scalar(
|
480
510
|
@value,
|
481
511
|
@anchor,
|
@@ -2441,7 +2471,6 @@ module Psych
|
|
2441
2471
|
} then
|
2442
2472
|
@in_scalar = false
|
2443
2473
|
lines = events_cache_pop
|
2444
|
-
lines.pop if lines.length > 0 && lines.last.empty?
|
2445
2474
|
value = lines.map { |line| "#{line}\n" }.join
|
2446
2475
|
|
2447
2476
|
case t
|
@@ -2450,7 +2479,7 @@ module Psych
|
|
2450
2479
|
when :strip
|
2451
2480
|
value.sub!(/\n+\z/, "")
|
2452
2481
|
when :keep
|
2453
|
-
|
2482
|
+
# nothing
|
2454
2483
|
else
|
2455
2484
|
raise InternalException, t.inspect
|
2456
2485
|
end
|
@@ -2469,6 +2498,8 @@ module Psych
|
|
2469
2498
|
# l-empty(n,block-in)*
|
2470
2499
|
# s-indent(n) nb-char+
|
2471
2500
|
def parse_l_nb_literal_text(n)
|
2501
|
+
events_cache_size = @events_cache[-1].size
|
2502
|
+
|
2472
2503
|
try do
|
2473
2504
|
if star { parse_l_empty(n, :block_in) } && parse_s_indent(n)
|
2474
2505
|
pos_start = @scanner.pos
|
@@ -2477,6 +2508,12 @@ module Psych
|
|
2477
2508
|
events_push(from(pos_start))
|
2478
2509
|
true
|
2479
2510
|
end
|
2511
|
+
else
|
2512
|
+
# When parsing all of the l_empty calls, we may have added a bunch
|
2513
|
+
# of empty lines to the events cache. We need to clear those out
|
2514
|
+
# here.
|
2515
|
+
@events_cache[-1].slice!(events_cache_size..-1)
|
2516
|
+
false
|
2480
2517
|
end
|
2481
2518
|
end
|
2482
2519
|
end
|
@@ -2739,7 +2776,7 @@ module Psych
|
|
2739
2776
|
|
2740
2777
|
if try { plus { try { parse_s_indent(n + m) && parse_ns_l_block_map_entry(n + m) } } }
|
2741
2778
|
events_cache_flush
|
2742
|
-
events_push_flush_properties(MappingEnd.new(Location.point(@source, @scanner.pos)))
|
2779
|
+
events_push_flush_properties(MappingEnd.new(Location.point(@source, @scanner.pos)))
|
2743
2780
|
true
|
2744
2781
|
else
|
2745
2782
|
events_cache_pop
|
@@ -2855,7 +2892,7 @@ module Psych
|
|
2855
2892
|
star { try { parse_s_indent(n) && parse_ns_l_block_map_entry(n) } }
|
2856
2893
|
} then
|
2857
2894
|
events_cache_flush
|
2858
|
-
events_push_flush_properties(MappingEnd.new(Location.point(@source, @scanner.pos)))
|
2895
|
+
events_push_flush_properties(MappingEnd.new(Location.point(@source, @scanner.pos)))
|
2859
2896
|
true
|
2860
2897
|
else
|
2861
2898
|
events_cache_pop
|
@@ -3042,12 +3079,12 @@ module Psych
|
|
3042
3079
|
def parse_l_yaml_stream
|
3043
3080
|
events_push_flush_properties(StreamStart.new(Location.point(@source, @scanner.pos)))
|
3044
3081
|
|
3045
|
-
@document_start_event = DocumentStart.new(Location.point(@source, @scanner.pos))
|
3046
|
-
@tag_directives = @document_start_event.tag_directives
|
3047
|
-
@document_end_event = nil
|
3048
|
-
|
3049
3082
|
if try {
|
3050
3083
|
if parse_l_document_prefix
|
3084
|
+
@document_start_event = DocumentStart.new(Location.point(@source, @scanner.pos))
|
3085
|
+
@tag_directives = @document_start_event.tag_directives
|
3086
|
+
@document_end_event = nil
|
3087
|
+
|
3051
3088
|
parse_l_any_document
|
3052
3089
|
star do
|
3053
3090
|
try do
|
@@ -3105,11 +3142,11 @@ module Psych
|
|
3105
3142
|
# aliases, since we may find that we need to add an anchor after the
|
3106
3143
|
# object has already been flushed.
|
3107
3144
|
class Node
|
3108
|
-
attr_reader :value, :
|
3145
|
+
attr_reader :value, :psych_node
|
3109
3146
|
|
3110
|
-
def initialize(value,
|
3147
|
+
def initialize(value, psych_node)
|
3111
3148
|
@value = value
|
3112
|
-
@
|
3149
|
+
@psych_node = psych_node
|
3113
3150
|
@anchor = nil
|
3114
3151
|
end
|
3115
3152
|
|
@@ -3127,7 +3164,7 @@ module Psych
|
|
3127
3164
|
|
3128
3165
|
# Represents an array of nodes.
|
3129
3166
|
class ArrayNode < Node
|
3130
|
-
attr_accessor :anchor
|
3167
|
+
attr_accessor :anchor, :tag
|
3131
3168
|
|
3132
3169
|
def accept(visitor)
|
3133
3170
|
visitor.visit_array(self)
|
@@ -3136,7 +3173,7 @@ module Psych
|
|
3136
3173
|
|
3137
3174
|
# Represents a hash of nodes.
|
3138
3175
|
class HashNode < Node
|
3139
|
-
attr_accessor :anchor
|
3176
|
+
attr_accessor :anchor, :tag
|
3140
3177
|
|
3141
3178
|
def accept(visitor)
|
3142
3179
|
visitor.visit_hash(self)
|
@@ -3150,6 +3187,14 @@ module Psych
|
|
3150
3187
|
# Represents a generic object that is not matched by any of the other node
|
3151
3188
|
# types.
|
3152
3189
|
class ObjectNode < Node
|
3190
|
+
# The explicit tag associated with the object.
|
3191
|
+
attr_accessor :tag
|
3192
|
+
|
3193
|
+
# Whether or not this object was modified after being loaded. In this
|
3194
|
+
# case we cannot rely on the source formatting, and need to instead
|
3195
|
+
# format the value ourselves.
|
3196
|
+
attr_accessor :dirty
|
3197
|
+
|
3153
3198
|
def accept(visitor)
|
3154
3199
|
visitor.visit_object(self)
|
3155
3200
|
end
|
@@ -3175,6 +3220,8 @@ module Psych
|
|
3175
3220
|
|
3176
3221
|
# Represents a string object.
|
3177
3222
|
class StringNode < Node
|
3223
|
+
attr_accessor :tag
|
3224
|
+
|
3178
3225
|
def accept(visitor)
|
3179
3226
|
visitor.visit_string(self)
|
3180
3227
|
end
|
@@ -3195,14 +3242,10 @@ module Psych
|
|
3195
3242
|
# Visit an ArrayNode.
|
3196
3243
|
def visit_array(node)
|
3197
3244
|
with_comments(node) do |value|
|
3198
|
-
if (
|
3199
|
-
|
3200
|
-
end
|
3201
|
-
|
3202
|
-
if value.empty?
|
3203
|
-
@q.text("[]")
|
3245
|
+
if value.empty? || ((psych_node = node.psych_node).is_a?(Nodes::Sequence) && psych_node.style == Nodes::Sequence::FLOW)
|
3246
|
+
visit_array_contents_flow(node.anchor, node.tag, value)
|
3204
3247
|
else
|
3205
|
-
|
3248
|
+
visit_array_contents_block(node.anchor, node.tag, value)
|
3206
3249
|
end
|
3207
3250
|
end
|
3208
3251
|
end
|
@@ -3210,16 +3253,10 @@ module Psych
|
|
3210
3253
|
# Visit a HashNode.
|
3211
3254
|
def visit_hash(node)
|
3212
3255
|
with_comments(node) do |value|
|
3213
|
-
if (
|
3214
|
-
|
3215
|
-
end
|
3216
|
-
|
3217
|
-
if value.empty?
|
3218
|
-
@q.text(" ") if anchor
|
3219
|
-
@q.text("{}")
|
3256
|
+
if value.empty? || ((psych_node = node.psych_node).is_a?(Nodes::Mapping) && psych_node.style == Nodes::Mapping::FLOW)
|
3257
|
+
visit_hash_contents_flow(node.anchor, node.tag, value)
|
3220
3258
|
else
|
3221
|
-
|
3222
|
-
visit_hash_contents(value)
|
3259
|
+
visit_hash_contents_block(node.anchor, node.tag, value)
|
3223
3260
|
end
|
3224
3261
|
end
|
3225
3262
|
end
|
@@ -3227,50 +3264,76 @@ module Psych
|
|
3227
3264
|
# Visit an ObjectNode.
|
3228
3265
|
def visit_object(node)
|
3229
3266
|
with_comments(node) do |value|
|
3230
|
-
|
3267
|
+
if (tag = node.tag)
|
3268
|
+
@q.text("#{tag} ")
|
3269
|
+
end
|
3270
|
+
|
3271
|
+
if !node.dirty && (psych_node = node.psych_node)
|
3272
|
+
@q.text(psych_node.value)
|
3273
|
+
else
|
3274
|
+
@q.text(dump_object(value))
|
3275
|
+
end
|
3231
3276
|
end
|
3232
3277
|
end
|
3233
3278
|
|
3234
3279
|
# Visit an OmapNode.
|
3235
3280
|
def visit_omap(node)
|
3236
3281
|
with_comments(node) do |value|
|
3237
|
-
|
3238
|
-
@q.text("&#{anchor} ")
|
3239
|
-
end
|
3240
|
-
|
3241
|
-
@q.text("!!omap")
|
3242
|
-
@q.breakable
|
3243
|
-
|
3244
|
-
visit_array_contents(value)
|
3282
|
+
visit_array_contents_block(node.anchor, "!!omap", value)
|
3245
3283
|
end
|
3246
3284
|
end
|
3247
3285
|
|
3248
3286
|
# Visit a SetNode.
|
3249
3287
|
def visit_set(node)
|
3250
3288
|
with_comments(node) do |value|
|
3251
|
-
|
3252
|
-
@q.text("&#{anchor} ")
|
3253
|
-
end
|
3254
|
-
|
3255
|
-
@q.text("!set")
|
3256
|
-
@q.breakable
|
3257
|
-
|
3258
|
-
visit_hash_contents(node.value)
|
3289
|
+
visit_hash_contents_block(node.anchor, "!set", value)
|
3259
3290
|
end
|
3260
3291
|
end
|
3261
3292
|
|
3262
3293
|
# Visit a StringNode.
|
3263
|
-
|
3294
|
+
def visit_string(node)
|
3295
|
+
with_comments(node) do |value|
|
3296
|
+
if (tag = node.tag)
|
3297
|
+
@q.text("#{tag} ")
|
3298
|
+
end
|
3299
|
+
|
3300
|
+
@q.text(dump_object(value))
|
3301
|
+
end
|
3302
|
+
end
|
3264
3303
|
|
3265
3304
|
private
|
3266
3305
|
|
3306
|
+
# TODO: Certain objects require special formatting. Usually this
|
3307
|
+
# involves scanning the object itself and determining what kind of YAML
|
3308
|
+
# object it is, then dumping it back out. We rely on Psych itself to do
|
3309
|
+
# this formatting for us.
|
3310
|
+
#
|
3311
|
+
# Note this is the one place where we indirectly rely on libyaml,
|
3312
|
+
# because Psych delegates to libyaml to dump the object. This is less
|
3313
|
+
# than ideal, because it means in some circumstances we have an indirect
|
3314
|
+
# dependency. Ideally this would all be removed in favor of our own
|
3315
|
+
# formatting.
|
3316
|
+
def dump_object(value)
|
3317
|
+
Psych.dump(value, indentation: @q.indent)[/\A--- (.+?)(?:\n\.\.\.)?\n\z/m, 1]
|
3318
|
+
end
|
3319
|
+
|
3267
3320
|
# Shortcut to visit a node by passing this visitor to the accept method.
|
3268
3321
|
def visit(node)
|
3269
3322
|
node.accept(self)
|
3270
3323
|
end
|
3271
3324
|
|
3272
|
-
# Visit the elements within an array.
|
3273
|
-
def
|
3325
|
+
# Visit the elements within an array in the block format.
|
3326
|
+
def visit_array_contents_block(anchor, tag, contents)
|
3327
|
+
if anchor
|
3328
|
+
@q.text("&#{anchor}")
|
3329
|
+
tag ? @q.text(" ") : @q.breakable
|
3330
|
+
end
|
3331
|
+
|
3332
|
+
if tag
|
3333
|
+
@q.text(tag)
|
3334
|
+
@q.breakable
|
3335
|
+
end
|
3336
|
+
|
3274
3337
|
@q.seplist(contents, -> { @q.breakable }) do |element|
|
3275
3338
|
@q.text("-")
|
3276
3339
|
next if element.is_a?(NilNode)
|
@@ -3278,79 +3341,147 @@ module Psych
|
|
3278
3341
|
@q.text(" ")
|
3279
3342
|
@q.nest(2) { visit(element) }
|
3280
3343
|
end
|
3344
|
+
|
3345
|
+
@q.current_group.break
|
3281
3346
|
end
|
3282
3347
|
|
3283
|
-
# Visit the
|
3284
|
-
def
|
3285
|
-
@q.
|
3286
|
-
|
3348
|
+
# Visit the elements within an array in the flow format.
|
3349
|
+
def visit_array_contents_flow(anchor, tag, contents)
|
3350
|
+
@q.group do
|
3351
|
+
@q.text("&#{anchor} ") if anchor
|
3352
|
+
@q.text("#{tag} ") if tag
|
3353
|
+
@q.text("[")
|
3287
3354
|
|
3288
|
-
|
3289
|
-
|
3290
|
-
|
3291
|
-
|
3292
|
-
if key.anchor.nil?
|
3293
|
-
@q.text("? ")
|
3294
|
-
@q.nest(2) { visit(key) }
|
3295
|
-
@q.breakable
|
3296
|
-
inlined = true
|
3297
|
-
else
|
3298
|
-
visit(key)
|
3355
|
+
unless contents.empty?
|
3356
|
+
@q.nest(2) do
|
3357
|
+
@q.breakable("")
|
3358
|
+
@q.seplist(contents, -> { @q.comma_breakable }) { |element| visit(element) }
|
3299
3359
|
end
|
3300
|
-
|
3360
|
+
@q.breakable("")
|
3361
|
+
end
|
3362
|
+
|
3363
|
+
@q.text("]")
|
3364
|
+
end
|
3365
|
+
end
|
3366
|
+
|
3367
|
+
# Visit a key value pair within a hash.
|
3368
|
+
def visit_hash_key_value(key, value)
|
3369
|
+
inlined = false
|
3370
|
+
|
3371
|
+
case key
|
3372
|
+
when NilNode
|
3373
|
+
@q.text("! ''")
|
3374
|
+
when ArrayNode, HashNode, OmapNode, SetNode
|
3375
|
+
if key.anchor.nil?
|
3376
|
+
@q.text("? ")
|
3377
|
+
@q.nest(2) { visit(key) }
|
3378
|
+
@q.breakable
|
3379
|
+
inlined = true
|
3380
|
+
else
|
3301
3381
|
visit(key)
|
3302
|
-
when StringNode
|
3303
|
-
if key.value.include?("\n")
|
3304
|
-
@q.text("? ")
|
3305
|
-
visit(key)
|
3306
|
-
@q.breakable
|
3307
|
-
inlined = true
|
3308
|
-
else
|
3309
|
-
visit(key)
|
3310
|
-
end
|
3311
3382
|
end
|
3383
|
+
when AliasNode, ObjectNode
|
3384
|
+
visit(key)
|
3385
|
+
when StringNode
|
3386
|
+
if key.value.include?("\n")
|
3387
|
+
@q.text("? ")
|
3388
|
+
visit(key)
|
3389
|
+
@q.breakable
|
3390
|
+
inlined = true
|
3391
|
+
else
|
3392
|
+
visit(key)
|
3393
|
+
end
|
3394
|
+
else
|
3395
|
+
raise InternalException
|
3396
|
+
end
|
3312
3397
|
|
3313
|
-
|
3398
|
+
@q.text(":")
|
3314
3399
|
|
3315
|
-
|
3316
|
-
|
3317
|
-
|
3318
|
-
|
3400
|
+
case value
|
3401
|
+
when NilNode
|
3402
|
+
# skip
|
3403
|
+
when OmapNode, SetNode
|
3404
|
+
@q.text(" ")
|
3405
|
+
@q.nest(2) { visit(value) }
|
3406
|
+
when ArrayNode
|
3407
|
+
if ((psych_node = value.psych_node).is_a?(Nodes::Sequence) && psych_node.style == Nodes::Sequence::FLOW) || value.value.empty?
|
3408
|
+
@q.text(" ")
|
3409
|
+
visit(value)
|
3410
|
+
elsif inlined || value.anchor || value.tag || value.value.empty?
|
3319
3411
|
@q.text(" ")
|
3320
3412
|
@q.nest(2) { visit(value) }
|
3321
|
-
|
3322
|
-
|
3323
|
-
|
3324
|
-
|
3325
|
-
|
3326
|
-
|
3327
|
-
|
3413
|
+
else
|
3414
|
+
@q.breakable
|
3415
|
+
visit(value)
|
3416
|
+
end
|
3417
|
+
when HashNode
|
3418
|
+
if ((psych_node = value.psych_node).is_a?(Nodes::Mapping) && psych_node.style == Nodes::Mapping::FLOW) || value.value.empty?
|
3419
|
+
@q.text(" ")
|
3420
|
+
visit(value)
|
3421
|
+
elsif inlined || value.anchor || value.tag
|
3422
|
+
@q.text(" ")
|
3423
|
+
@q.nest(2) { visit(value) }
|
3424
|
+
else
|
3425
|
+
@q.nest(2) do
|
3328
3426
|
@q.breakable
|
3329
3427
|
visit(value)
|
3330
3428
|
end
|
3331
|
-
|
3332
|
-
|
3333
|
-
|
3334
|
-
|
3335
|
-
|
3336
|
-
|
3337
|
-
|
3338
|
-
|
3339
|
-
|
3340
|
-
|
3429
|
+
end
|
3430
|
+
when AliasNode, ObjectNode, StringNode
|
3431
|
+
@q.text(" ")
|
3432
|
+
@q.nest(2) { visit(value) }
|
3433
|
+
else
|
3434
|
+
raise InternalException
|
3435
|
+
end
|
3436
|
+
end
|
3437
|
+
|
3438
|
+
# Visit the key/value pairs within a hash in the block format.
|
3439
|
+
def visit_hash_contents_block(anchor, tag, children)
|
3440
|
+
if anchor
|
3441
|
+
@q.text("&#{anchor}")
|
3442
|
+
tag ? @q.text(" ") : @q.breakable
|
3443
|
+
end
|
3444
|
+
|
3445
|
+
if tag
|
3446
|
+
@q.text(tag)
|
3447
|
+
@q.breakable
|
3448
|
+
end
|
3449
|
+
|
3450
|
+
((0...children.length) % 2).each do |index|
|
3451
|
+
@q.breakable if index != 0
|
3452
|
+
visit_hash_key_value(children[index], children[index + 1])
|
3453
|
+
end
|
3454
|
+
|
3455
|
+
@q.current_group.break
|
3456
|
+
end
|
3457
|
+
|
3458
|
+
# Visit the key/value pairs within a hash in the flow format.
|
3459
|
+
def visit_hash_contents_flow(anchor, tag, children)
|
3460
|
+
@q.group do
|
3461
|
+
@q.text("&#{anchor} ") if anchor
|
3462
|
+
@q.text("#{tag} ") if tag
|
3463
|
+
@q.text("{")
|
3464
|
+
|
3465
|
+
unless children.empty?
|
3466
|
+
@q.nest(2) do
|
3467
|
+
@q.breakable
|
3468
|
+
|
3469
|
+
((0...children.length) % 2).each do |index|
|
3470
|
+
@q.comma_breakable if index != 0
|
3471
|
+
visit_hash_key_value(children[index], children[index + 1])
|
3341
3472
|
end
|
3342
3473
|
end
|
3343
|
-
|
3344
|
-
@q.text(" ")
|
3345
|
-
@q.nest(2) { visit(value) }
|
3474
|
+
@q.breakable
|
3346
3475
|
end
|
3476
|
+
|
3477
|
+
@q.text("}")
|
3347
3478
|
end
|
3348
3479
|
end
|
3349
3480
|
|
3350
3481
|
# Print out the leading and trailing comments of a node, as well as
|
3351
3482
|
# yielding the value of the node to the block.
|
3352
3483
|
def with_comments(node)
|
3353
|
-
if (comments = node.comments) && (leading = comments.leading).any?
|
3484
|
+
if (comments = node.psych_node&.comments) && (leading = comments.leading).any?
|
3354
3485
|
line = nil
|
3355
3486
|
|
3356
3487
|
leading.each do |comment|
|
@@ -3435,14 +3566,42 @@ module Psych
|
|
3435
3566
|
# This is the main entrypoint into this object. It is responsible for
|
3436
3567
|
# pushing a new object onto the emitter, which is then represented as a
|
3437
3568
|
# YAML document.
|
3438
|
-
def
|
3569
|
+
def emit(object)
|
3439
3570
|
if @started
|
3440
|
-
@io << "...\n
|
3571
|
+
@io << "...\n"
|
3441
3572
|
else
|
3442
|
-
@io << "---"
|
3443
3573
|
@started = true
|
3444
3574
|
end
|
3445
3575
|
|
3576
|
+
# Very rare circumstance here that there are leading comments attached
|
3577
|
+
# to the root object of a document that occur before the --- marker. In
|
3578
|
+
# this case we want to output them first here, then dump the object.
|
3579
|
+
if (object.is_a?(LoadedObject) || object.is_a?(LoadedHash)) && (psych_node = object.psych_node).comments? && (leading = psych_node.comments.leading).any?
|
3580
|
+
leading = [*leading]
|
3581
|
+
line = psych_node.start_line - 1
|
3582
|
+
|
3583
|
+
while leading.any? && leading.last.start_line == line
|
3584
|
+
leading.pop
|
3585
|
+
line -= 1
|
3586
|
+
end
|
3587
|
+
|
3588
|
+
psych_node.comments.leading.slice!(0, leading.length)
|
3589
|
+
line = nil
|
3590
|
+
|
3591
|
+
leading.each do |comment|
|
3592
|
+
if line && (line < comment.start_line)
|
3593
|
+
@io << "\n" * (comment.start_line - line - 1)
|
3594
|
+
end
|
3595
|
+
|
3596
|
+
@io << comment.value
|
3597
|
+
@io << "\n"
|
3598
|
+
|
3599
|
+
line = comment.start_line
|
3600
|
+
end
|
3601
|
+
end
|
3602
|
+
|
3603
|
+
@io << "---"
|
3604
|
+
|
3446
3605
|
if (node = dump(object)).is_a?(NilNode)
|
3447
3606
|
@io << "\n"
|
3448
3607
|
else
|
@@ -3465,40 +3624,74 @@ module Psych
|
|
3465
3624
|
|
3466
3625
|
private
|
3467
3626
|
|
3468
|
-
#
|
3469
|
-
def
|
3470
|
-
|
3471
|
-
|
3472
|
-
|
3473
|
-
|
3474
|
-
|
3627
|
+
# Dump the tag value for a given node.
|
3628
|
+
def dump_tag(value)
|
3629
|
+
case value
|
3630
|
+
when nil, "tag:yaml.org,2002:binary"
|
3631
|
+
nil
|
3632
|
+
when /\Atag:yaml.org,2002:(.+)\z/
|
3633
|
+
"!!#{$1}"
|
3634
|
+
else
|
3635
|
+
value
|
3475
3636
|
end
|
3637
|
+
end
|
3476
3638
|
|
3477
|
-
|
3478
|
-
|
3479
|
-
|
3480
|
-
|
3639
|
+
# Walk through the given object and convert it into a tree of nodes.
|
3640
|
+
def dump(base_object)
|
3641
|
+
if base_object.nil?
|
3642
|
+
NilNode.new(nil, nil)
|
3481
3643
|
else
|
3482
|
-
|
3483
|
-
|
3484
|
-
|
3485
|
-
|
3486
|
-
|
3487
|
-
|
3488
|
-
|
3489
|
-
|
3490
|
-
|
3491
|
-
|
3492
|
-
|
3493
|
-
|
3494
|
-
object.to_h { |key, value| [dump(key), dump(value)] }
|
3495
|
-
end
|
3644
|
+
object = base_object
|
3645
|
+
psych_node = nil
|
3646
|
+
dirty = false
|
3647
|
+
|
3648
|
+
if base_object.is_a?(LoadedObject)
|
3649
|
+
object = base_object.__getobj__
|
3650
|
+
psych_node = base_object.psych_node
|
3651
|
+
dirty = base_object.dirty
|
3652
|
+
elsif base_object.is_a?(LoadedHash)
|
3653
|
+
object = base_object.__getobj__
|
3654
|
+
psych_node = base_object.psych_node
|
3655
|
+
end
|
3496
3656
|
|
3497
|
-
|
3498
|
-
|
3499
|
-
StringNode.new(object, comments)
|
3657
|
+
if @object_nodes.key?(object)
|
3658
|
+
AliasNode.new(@object_nodes[object].anchor = (@object_anchors[object] ||= (@object_anchor += 1)), nil)
|
3500
3659
|
else
|
3501
|
-
|
3660
|
+
case object
|
3661
|
+
when Psych::Omap
|
3662
|
+
@object_nodes[object] = OmapNode.new(object.map { |(key, value)| HashNode.new([dump(key), dump(value)], nil) }, psych_node)
|
3663
|
+
when Psych::Set
|
3664
|
+
@object_nodes[object] = SetNode.new(object.flat_map { |key, value| [dump(key), dump(value)] }, psych_node)
|
3665
|
+
when Array
|
3666
|
+
dumped = ArrayNode.new(object.map { |element| dump(element) }, psych_node)
|
3667
|
+
dumped.tag = dump_tag(psych_node&.tag)
|
3668
|
+
|
3669
|
+
@object_nodes[object] = dumped
|
3670
|
+
when Hash
|
3671
|
+
contents =
|
3672
|
+
if base_object.is_a?(LoadedHash)
|
3673
|
+
psych_node_keys = base_object.psych_node_keys
|
3674
|
+
object.flat_map { |key, value| [dump(psych_node_keys.fetch(key, key)), dump(value)] }
|
3675
|
+
else
|
3676
|
+
object.flat_map { |key, value| [dump(key), dump(value)] }
|
3677
|
+
end
|
3678
|
+
|
3679
|
+
dumped = HashNode.new(contents, psych_node)
|
3680
|
+
dumped.tag = dump_tag(psych_node&.tag)
|
3681
|
+
|
3682
|
+
@object_nodes[object] = dumped
|
3683
|
+
when String
|
3684
|
+
dumped = StringNode.new(object, psych_node)
|
3685
|
+
dumped.tag = dump_tag(psych_node&.tag)
|
3686
|
+
|
3687
|
+
dumped
|
3688
|
+
else
|
3689
|
+
dumped = ObjectNode.new(object, psych_node)
|
3690
|
+
dumped.tag = dump_tag(psych_node&.tag)
|
3691
|
+
dumped.dirty = dirty
|
3692
|
+
|
3693
|
+
dumped
|
3694
|
+
end
|
3502
3695
|
end
|
3503
3696
|
end
|
3504
3697
|
end
|
@@ -3538,10 +3731,10 @@ module Psych
|
|
3538
3731
|
private
|
3539
3732
|
|
3540
3733
|
# Dump the given object, ensuring that it is a permitted object.
|
3541
|
-
def dump(base_object
|
3734
|
+
def dump(base_object)
|
3542
3735
|
object = base_object
|
3543
3736
|
|
3544
|
-
if base_object.is_a?(
|
3737
|
+
if base_object.is_a?(LoadedObject) || base_object.is_a?(LoadedHash)
|
3545
3738
|
object = base_object.__getobj__
|
3546
3739
|
end
|
3547
3740
|
|
@@ -3677,7 +3870,7 @@ module Psych
|
|
3677
3870
|
|
3678
3871
|
real_io = io || StringIO.new
|
3679
3872
|
emitter = Emitter.new(real_io, options)
|
3680
|
-
emitter
|
3873
|
+
emitter.emit(o)
|
3681
3874
|
io || real_io.string
|
3682
3875
|
end
|
3683
3876
|
|
@@ -3691,7 +3884,7 @@ module Psych
|
|
3691
3884
|
|
3692
3885
|
real_io = io || StringIO.new
|
3693
3886
|
emitter = SafeEmitter.new(real_io, options)
|
3694
|
-
emitter
|
3887
|
+
emitter.emit(o)
|
3695
3888
|
io || real_io.string
|
3696
3889
|
end
|
3697
3890
|
|
@@ -3699,7 +3892,7 @@ module Psych
|
|
3699
3892
|
def self.dump_stream(*objects)
|
3700
3893
|
real_io = io || StringIO.new
|
3701
3894
|
emitter = Emitter.new(real_io, {})
|
3702
|
-
objects.each { |object| emitter
|
3895
|
+
objects.each { |object| emitter.emit(object) }
|
3703
3896
|
io || real_io.string
|
3704
3897
|
end
|
3705
3898
|
end
|
data/psych-pure.gemspec
CHANGED
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: psych-pure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Newton
|
8
|
+
autorequire:
|
8
9
|
bindir: bin
|
9
10
|
cert_chain: []
|
10
|
-
date: 2025-
|
11
|
+
date: 2025-03-04 00:00:00.000000000 Z
|
11
12
|
dependencies:
|
12
13
|
- !ruby/object:Gem::Dependency
|
13
14
|
name: psych
|
@@ -79,6 +80,21 @@ dependencies:
|
|
79
80
|
- - ">="
|
80
81
|
- !ruby/object:Gem::Version
|
81
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description:
|
82
98
|
email:
|
83
99
|
- kddnewton@gmail.com
|
84
100
|
executables: []
|
@@ -97,9 +113,10 @@ licenses:
|
|
97
113
|
- MIT
|
98
114
|
metadata:
|
99
115
|
bug_tracker_uri: https://github.com/kddnewton/psych-pure/issues
|
100
|
-
changelog_uri: https://github.com/kddnewton/psych-pure/blob/v0.1.
|
116
|
+
changelog_uri: https://github.com/kddnewton/psych-pure/blob/v0.1.2/CHANGELOG.md
|
101
117
|
source_code_uri: https://github.com/kddnewton/psych-pure
|
102
118
|
rubygems_mfa_required: 'true'
|
119
|
+
post_install_message:
|
103
120
|
rdoc_options: []
|
104
121
|
require_paths:
|
105
122
|
- lib
|
@@ -114,7 +131,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
131
|
- !ruby/object:Gem::Version
|
115
132
|
version: '0'
|
116
133
|
requirements: []
|
117
|
-
rubygems_version: 3.
|
134
|
+
rubygems_version: 3.5.16
|
135
|
+
signing_key:
|
118
136
|
specification_version: 4
|
119
137
|
summary: A YAML parser written in Ruby
|
120
138
|
test_files: []
|