psychgus 1.2.0 → 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.
data/lib/psychgus.rb CHANGED
@@ -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) 2017-2019 Jonathan Bradley Whited (@esotericpig)
7
- #
8
- # Psychgus is free software: you can redistribute it and/or modify
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) 2017-2021 Jonathan Bradley Whited
7
+ #
8
+ # SPDX-License-Identifier: LGPL-3.0-or-later
20
9
  #++
21
10
 
22
11
 
@@ -42,22 +31,22 @@ require 'psychgus/super_sniffer/parent'
42
31
  # Psychgus uses the core standard library {https://github.com/ruby/psych Psych} for working with YAML
43
32
  # and extends it so that developers can easily style the YAML according to their needs.
44
33
  # Thank you to the people that worked and continue to work hard on that project.
45
- #
34
+ #
46
35
  # The name comes from the well-styled character Gus from the TV show Psych.
47
- #
36
+ #
48
37
  # == Create a Styler
49
- #
38
+ #
50
39
  # First, we will create a {Styler}.
51
- #
40
+ #
52
41
  # All you need to do is add +include Psychgus::Styler+ to a class.
53
- #
42
+ #
54
43
  # Here is a complex {Styler} for the examples below:
55
44
  # require 'psychgus'
56
- #
45
+ #
57
46
  # class BurgerStyler
58
47
  # # Mix in methods needed for styling
59
48
  # include Psychgus::Styler
60
- #
49
+ #
61
50
  # def initialize(sniffer=nil)
62
51
  # if sniffer.nil?()
63
52
  # @class_level = 0
@@ -68,48 +57,48 @@ require 'psychgus/super_sniffer/parent'
68
57
  # @class_position = sniffer.position
69
58
  # end
70
59
  # end
71
- #
60
+ #
72
61
  # # Style all nodes (Psych::Nodes::Node)
73
62
  # def style(sniffer,node)
74
63
  # # Remove "!ruby/object:..." for classes
75
64
  # node.tag = nil if node.node_of?(:mapping,:scalar,:sequence)
76
- #
65
+ #
77
66
  # # This is another way to do the above
78
67
  # #node.tag = nil if node.respond_to?(:tag=)
79
68
  # end
80
- #
69
+ #
81
70
  # # Style aliases (Psych::Nodes::Alias)
82
71
  # def style_alias(sniffer,node)
83
72
  # end
84
- #
73
+ #
85
74
  # # Style maps (Psych::Nodes::Mapping)
86
75
  # # - Hashes (key/value pairs)
87
76
  # # - Example: "Burgers: Classic {}"
88
77
  # def style_mapping(sniffer,node)
89
78
  # parent = sniffer.parent
90
- #
79
+ #
91
80
  # if !parent.nil?()
92
81
  # # BBQ
93
82
  # node.style = Psychgus::MAPPING_FLOW if parent.node_of?(:scalar) &&
94
83
  # parent.value.casecmp('BBQ') == 0
95
84
  # end
96
85
  # end
97
- #
86
+ #
98
87
  # # Style scalars (Psych::Nodes::Scalar)
99
88
  # # - Any text (non-alias)
100
89
  # def style_scalar(sniffer,node)
101
90
  # parent = sniffer.parent
102
- #
91
+ #
103
92
  # # Single quote scalars that are not keys to a map
104
93
  # # - "child_key?" is the same as "child_type == :key"
105
94
  # node.style = Psychgus::SCALAR_SINGLE_QUOTED unless parent.child_key?()
106
- #
95
+ #
107
96
  # # Remove colon (change symbols into strings)
108
97
  # node.value = node.value.sub(':','')
109
- #
98
+ #
110
99
  # # Change lettuce to spinach
111
100
  # node.value = 'Spinach' if node.value.casecmp('Lettuce') == 0
112
- #
101
+ #
113
102
  # # Capitalize each word
114
103
  # node.value = node.value.split(' ').map do |v|
115
104
  # if v.casecmp('BBQ') == 0
@@ -119,23 +108,23 @@ require 'psychgus/super_sniffer/parent'
119
108
  # end
120
109
  # end.join(' ')
121
110
  # end
122
- #
111
+ #
123
112
  # # Style sequences (Psych::Nodes::Sequence)
124
113
  # # - Arrays
125
114
  # # - Example: "[Lettuce, Onions, Pickles, Tomatoes]"
126
115
  # def style_sequence(sniffer,node)
127
116
  # relative_level = (sniffer.level - @class_level) + 1
128
- #
117
+ #
129
118
  # node.style = Psychgus::SEQUENCE_FLOW if sniffer.level >= 4
130
- #
119
+ #
131
120
  # # Make "[Ketchup, Mustard]" a block for the Class Example
132
121
  # node.style = Psychgus::SEQUENCE_BLOCK if relative_level == 7
133
122
  # end
134
123
  # end
135
- #
124
+ #
136
125
  # @example Hash example
137
126
  # require 'psychgus'
138
- #
127
+ #
139
128
  # burgers = {
140
129
  # :Burgers => {
141
130
  # :Classic => {
@@ -161,9 +150,9 @@ require 'psychgus/super_sniffer/parent'
161
150
  # ]
162
151
  # }
163
152
  # burgers[:Favorite] = burgers[:Burgers][:BBQ] # Alias
164
- #
153
+ #
165
154
  # puts burgers.to_yaml(indent: 3,stylers: BurgerStyler.new,deref_aliases: true)
166
- #
155
+ #
167
156
  # # Output:
168
157
  # # ---
169
158
  # # Burgers:
@@ -184,21 +173,21 @@ require 'psychgus/super_sniffer/parent'
184
173
  # # Sauce: 'Honey BBQ'
185
174
  # # Cheese: 'Cheddar'
186
175
  # # Bun: 'Kaiser'
187
- #
176
+ #
188
177
  # @example Class example
189
178
  # require 'psychgus'
190
- #
179
+ #
191
180
  # class Burger
192
181
  # attr_accessor :bun
193
182
  # attr_accessor :cheese
194
183
  # attr_accessor :sauce
195
- #
184
+ #
196
185
  # def initialize(sauce,cheese,bun)
197
186
  # @bun = bun
198
187
  # @cheese = cheese
199
188
  # @sauce = sauce
200
189
  # end
201
- #
190
+ #
202
191
  # # You can still use Psych's encode_with(), no problem
203
192
  # #def encode_with(coder)
204
193
  # # coder['Bun'] = @bun
@@ -206,34 +195,34 @@ require 'psychgus/super_sniffer/parent'
206
195
  # # coder['Sauce'] = @sauce
207
196
  # #end
208
197
  # end
209
- #
198
+ #
210
199
  # class Burgers
211
200
  # include Psychgus::Blueberry
212
- #
201
+ #
213
202
  # attr_accessor :burgers
214
203
  # attr_accessor :toppings
215
204
  # attr_accessor :favorite
216
- #
205
+ #
217
206
  # def initialize()
218
207
  # @burgers = {
219
208
  # 'Classic' => Burger.new(['Ketchup','Mustard'],'American','Sesame Seed'),
220
209
  # 'BBQ' => Burger.new('Honey BBQ','Cheddar','Kaiser'),
221
210
  # 'Fancy' => Burger.new('Spicy Wasabi','Smoked Gouda','Hawaiian')
222
211
  # }
223
- #
212
+ #
224
213
  # @toppings = [
225
214
  # 'Mushrooms',
226
215
  # %w(Lettuce Onions Pickles Tomatoes),
227
216
  # [%w(Ketchup Mustard),%w(Salt Pepper)]
228
217
  # ]
229
- #
218
+ #
230
219
  # @favorite = @burgers['BBQ'] # Alias
231
220
  # end
232
- #
221
+ #
233
222
  # def psychgus_stylers(sniffer)
234
223
  # return BurgerStyler.new(sniffer)
235
224
  # end
236
- #
225
+ #
237
226
  # # You can still use Psych's encode_with(), no problem
238
227
  # #def encode_with(coder)
239
228
  # # coder['Burgers'] = @burgers
@@ -241,10 +230,10 @@ require 'psychgus/super_sniffer/parent'
241
230
  # # coder['Favorite'] = @favorite
242
231
  # #end
243
232
  # end
244
- #
233
+ #
245
234
  # burgers = Burgers.new
246
235
  # puts burgers.to_yaml(indent: 3,deref_aliases: true)
247
- #
236
+ #
248
237
  # # Output:
249
238
  # # ---
250
239
  # # Burgers:
@@ -267,146 +256,144 @@ require 'psychgus/super_sniffer/parent'
267
256
  # # Bun: 'Kaiser'
268
257
  # # Cheese: 'Cheddar'
269
258
  # # Sauce: 'Honey BBQ'
270
- #
259
+ #
271
260
  # @example Emitting / Parsing examples
272
261
  # styler = BurgerStyler.new()
273
262
  # options = {:indentation=>3,:stylers=>styler,:deref_aliases=>true}
274
263
  # yaml = burgers.to_yaml(options)
275
- #
264
+ #
276
265
  # # High-level emitting
277
266
  # Psychgus.dump(burgers,options)
278
267
  # Psychgus.dump_file('burgers.yaml',burgers,options)
279
268
  # burgers.to_yaml(options)
280
- #
269
+ #
281
270
  # # High-level parsing
282
271
  # # - Because to_ruby() will be called, just use Psych:
283
272
  # # - load(), load_file(), load_stream(), safe_load()
284
- #
273
+ #
285
274
  # # Mid-level emitting
286
275
  # stream = Psychgus.parse_stream(yaml,stylers: styler,deref_aliases: true)
287
- #
276
+ #
288
277
  # stream.to_yaml()
289
- #
278
+ #
290
279
  # # Mid-level parsing
291
280
  # Psychgus.parse(yaml,stylers: styler,deref_aliases: true)
292
281
  # Psychgus.parse_file('burgers.yaml',stylers: styler,deref_aliases: true)
293
282
  # Psychgus.parse_stream(yaml,stylers: styler,deref_aliases: true)
294
- #
283
+ #
295
284
  # # Low-level emitting
296
285
  # tree_builder = Psychgus::StyledTreeBuilder.new(styler,deref_aliases: true)
297
286
  # visitor = Psych::Visitors::YAMLTree.create(options,tree_builder)
298
- #
287
+ #
299
288
  # visitor << burgers
300
289
  # visitor.tree.to_yaml
301
- #
290
+ #
302
291
  # # Low-level parsing
303
292
  # parser = Psychgus.parser(stylers: styler,deref_aliases: true)
304
- #
293
+ #
305
294
  # parser.parse(yaml)
306
295
  # parser.handler
307
296
  # parser.handler.root
308
- #
309
- # @author Jonathan Bradley Whited (@esotericpig)
297
+ #
298
+ # @author Jonathan Bradley Whited
310
299
  # @since 1.0.0
311
300
  ###
312
301
  module Psychgus
313
302
  # Include these in the top namespace for convenience (i.e., less typing).
314
- #
315
- # @since 1.2.0
316
- include Stylables
317
- include Stylers
318
-
319
- NODE_CLASS_ALIASES = {:Doc => :Document,:Map => :Mapping,:Seq => :Sequence}
320
- OPTIONS_ALIASES = {:canon => :canonical,:indent => :indentation}
321
-
303
+ include Stylables # @since 1.2.0
304
+ include Stylers # @since 1.2.0
305
+
306
+ NODE_CLASS_ALIASES = {Doc: :Document,Map: :Mapping,Seq: :Sequence}.freeze
307
+ OPTIONS_ALIASES = {canon: :canonical,indent: :indentation}.freeze
308
+
322
309
  # Get a Class (constant) from Psych::Nodes.
323
- #
310
+ #
324
311
  # Some +name+s have aliases:
325
312
  # :doc => :document
326
313
  # :map => :mapping
327
314
  # :seq => :sequence
328
- #
315
+ #
329
316
  # @param name [Symbol,String] the name of the class from Psych::Nodes
330
- #
317
+ #
331
318
  # @return [Class] a class from Psych::Nodes
332
- #
319
+ #
333
320
  # @see Psych::Nodes
334
321
  # @see NODE_CLASS_ALIASES
335
322
  def self.node_class(name)
336
- name = name.to_sym().capitalize()
337
-
323
+ name = name.to_sym.capitalize
324
+
338
325
  actual_name = NODE_CLASS_ALIASES[name]
339
- name = actual_name unless actual_name.nil?()
340
-
326
+ name = actual_name unless actual_name.nil?
327
+
341
328
  return Psych::Nodes.const_get(name)
342
329
  end
343
-
330
+
344
331
  # Get a constant from a Psych::Nodes class (using {.node_class}).
345
- #
332
+ #
346
333
  # @param class_name [Symbol,String] the name of the class to get using {.node_class}
347
334
  # @param const_name [Symbol,String] the constant to get from the class
348
335
  # @param lenient [true,false] if true, will return 0 if not const_defined?(), else raise an error
349
- #
336
+ #
350
337
  # @return [Integer,Object] the constant value from the class (usually an int)
351
- #
338
+ #
352
339
  # @see .node_class
353
340
  def self.node_const(class_name,const_name,lenient=true)
354
341
  node_class = node_class(class_name)
355
- const_name = const_name.to_sym().upcase()
356
-
342
+ const_name = const_name.to_sym.upcase
343
+
357
344
  return 0 if lenient && !node_class.const_defined?(const_name,true)
358
345
  return node_class.const_get(const_name,true)
359
346
  end
360
-
347
+
361
348
  MAPPING_ANY = node_const(:mapping,:any)
362
349
  MAPPING_BLOCK = node_const(:mapping,:block)
363
350
  MAPPING_FLOW = node_const(:mapping,:flow)
364
351
  MAP_ANY = MAPPING_ANY
365
352
  MAP_BLOCK = MAPPING_BLOCK
366
353
  MAP_FLOW = MAPPING_FLOW
367
-
354
+
368
355
  SCALAR_ANY = node_const(:scalar,:any)
369
356
  SCALAR_PLAIN = node_const(:scalar,:plain)
370
357
  SCALAR_SINGLE_QUOTED = node_const(:scalar,:single_quoted)
371
358
  SCALAR_DOUBLE_QUOTED = node_const(:scalar,:double_quoted)
372
359
  SCALAR_LITERAL = node_const(:scalar,:literal)
373
360
  SCALAR_FOLDED = node_const(:scalar,:folded)
374
-
361
+
375
362
  SEQUENCE_ANY = node_const(:sequence,:any)
376
363
  SEQUENCE_BLOCK = node_const(:sequence,:block)
377
364
  SEQUENCE_FLOW = node_const(:sequence,:flow)
378
365
  SEQ_ANY = SEQUENCE_ANY
379
366
  SEQ_BLOCK = SEQUENCE_BLOCK
380
367
  SEQ_FLOW = SEQUENCE_FLOW
381
-
368
+
382
369
  STREAM_ANY = node_const(:stream,:any)
383
370
  STREAM_UTF8 = node_const(:stream,:utf8)
384
371
  STREAM_UTF16LE = node_const(:stream,:utf16le)
385
372
  STREAM_UTF16BE = node_const(:stream,:utf16be)
386
-
373
+
387
374
  # Convert +object+ to YAML and dump to +io+.
388
- #
375
+ #
389
376
  # +object+, +io+, and +options+ are used like in Psych.dump so can be a drop-in replacement for Psych.
390
- #
377
+ #
391
378
  # @param object [Object] the Object to convert to YAML and dump
392
379
  # @param io [nil,IO,Hash] the IO to dump the YAML to or the +options+ Hash; if nil, will use StringIO
393
380
  # @param options [Hash] the options (or keyword args) to use; see {.dump_stream}
394
- #
381
+ #
395
382
  # @return [String,Object] the result of converting +object+ to YAML using the params
396
- #
383
+ #
397
384
  # @see .dump_stream
398
385
  # @see Psych.dump_stream
399
386
  def self.dump(object,io=nil,**options)
400
387
  return dump_stream(object,io: io,**options)
401
388
  end
402
-
389
+
403
390
  # Convert +objects+ to YAML and dump to a file.
404
- #
391
+ #
405
392
  # @example
406
393
  # Psychgus.dump_file('my_dir/my_file.yaml',my_object1,my_object2,mode: 'w:UTF-16',
407
394
  # stylers: MyStyler.new())
408
395
  # Psychgus.dump_file('my_file.yaml',my_object,stylers: [MyStyler1.new(),MyStyler2.new()])
409
- #
396
+ #
410
397
  # @param filename [String] the name of the file (and path) to dump to
411
398
  # @param objects [Object,Array<Object>] the Object(s) to convert to YAML and dump
412
399
  # @param mode [String,Integer] the IO open mode to use; examples:
@@ -415,24 +402,25 @@ module Psychgus
415
402
  # [+'a:UTF-16'+] create a new file or append to an existing file
416
403
  # and use UTF-16 encoding
417
404
  # @param perm [Integer] the permission bits to use (platform dependent)
418
- # @param opt [Symbol] the option(s) to use, more readable alternative to +mode+;
419
- # examples: +:textmode+, +:autoclose+
405
+ # @param opt [Hash] Hash of keyword args to pass to +File.open()+
420
406
  # @param options [Hash] the options (or keyword args) to use; see {.dump_stream}
421
- #
407
+ #
422
408
  # @see .dump_stream
423
409
  # @see File.open
424
410
  # @see IO.new
425
411
  # @see https://ruby-doc.org/core/IO.html#method-c-new
426
412
  def self.dump_file(filename,*objects,mode: 'w',perm: nil,opt: nil,**options)
427
- File.open(filename,mode,perm,opt) do |file|
413
+ opt = Hash(opt)
414
+
415
+ File.open(filename,mode,perm,**opt) do |file|
428
416
  file.write(dump_stream(*objects,**options))
429
417
  end
430
418
  end
431
-
419
+
432
420
  # Convert +objects+ to YAML and dump to +io+.
433
- #
421
+ #
434
422
  # +io+ and +options+ are used like in Psych.dump so can be a drop-in replacement for Psych.
435
- #
423
+ #
436
424
  # @param objects [Object,Array<Object>] the Object(s) to convert to YAML and dump
437
425
  # @param io [nil,IO,Hash] the IO to dump the YAML to or the +options+ Hash; if nil, will use StringIO
438
426
  # @param stylers [nil,Styler,Array<Styler>] the Styler(s) to use when converting to YAML
@@ -450,47 +438,48 @@ module Psychgus
450
438
  # Write "canonical" YAML form (very verbose, yet strictly formal).
451
439
  # [+:header+] Default: +false+.
452
440
  # Write +%YAML [version]+ at the beginning of document.
453
- #
441
+ #
454
442
  # @return [String,Object] the result of converting +object+ to YAML using the params
455
- #
443
+ #
456
444
  # @see Psych.dump_stream
457
445
  # @see OPTIONS_ALIASES
458
446
  def self.dump_stream(*objects,io: nil,stylers: nil,deref_aliases: false,**options)
459
447
  # If you call this method with only a Hash that uses symbols as keys,
460
448
  # then options will be set to the Hash, instead of objects.
461
- #
449
+ #
462
450
  # For example, the below will be stored in options, not objects:
463
451
  # - dump_stream({:coffee => {:roast => [],:style => []}})
464
- #
452
+ #
465
453
  # This if-statement is guaranteed because dump_stream([]) and dump_stream(nil)
466
454
  # will produce [[]] and [nil], which are not empty.
467
- #
455
+ #
468
456
  # dump_stream() w/o any args is the only problem, but resolved w/ [nil].
469
- if objects.empty?()
470
- objects = options.empty?() ? [nil] : [options]
457
+ if objects.empty?
458
+ objects = options.empty? ? [nil] : [options]
471
459
  options = {}
472
460
  end
473
-
474
- if Hash === io
461
+
462
+ if io.is_a?(Hash)
475
463
  options = io
476
464
  io = nil
477
465
  end
478
-
479
- if !options.empty?()
466
+
467
+ if !options.empty?
480
468
  OPTIONS_ALIASES.each do |option_alias,actual_option|
481
469
  if options.key?(option_alias) && !options.key?(actual_option)
482
470
  options[actual_option] = options[option_alias]
483
471
  end
484
472
  end
485
473
  end
486
-
474
+
487
475
  visitor = Psych::Visitors::YAMLTree.create(options,StyledTreeBuilder.new(*stylers,
488
476
  deref_aliases: deref_aliases))
489
-
490
- if objects.empty?()
477
+
478
+ if objects.empty?
491
479
  # Else, will throw a cryptic NoMethodError:
492
- # - "psych/tree_builder.rb:in `set_end_location': undefined method `end_line=' for nil:NilClass (NoMethodError)"
493
- #
480
+ # - "psych/tree_builder.rb:in `set_end_location':
481
+ # undefined method `end_line=' for nil:NilClass (NoMethodError)"
482
+ #
494
483
  # This should never occur because of the if-statement at the top of this method.
495
484
  visitor << nil
496
485
  else
@@ -498,17 +487,17 @@ module Psychgus
498
487
  visitor << object
499
488
  end
500
489
  end
501
-
490
+
502
491
  return visitor.tree.yaml(io,options)
503
492
  end
504
-
493
+
505
494
  # Get a visual hierarchy of the levels as a String.
506
- #
495
+ #
507
496
  # This is useful for determining the correct level/position when writing a {Styler}.
508
- #
497
+ #
509
498
  # @example
510
499
  # require 'psychgus'
511
- #
500
+ #
512
501
  # burgers = {
513
502
  # :burgers => {
514
503
  # :classic => {:sauce => %w(Ketchup Mustard),
@@ -527,9 +516,9 @@ module Psychgus
527
516
  # [%w(Ketchup Mustard), %w(Salt Pepper)]
528
517
  # ]
529
518
  # }
530
- #
519
+ #
531
520
  # puts Psychgus.hierarchy(burgers)
532
- #
521
+ #
533
522
  # # Output:
534
523
  # # ---
535
524
  # # (level:position):current_node - <parent:(parent_level:parent_position)>
@@ -580,34 +569,34 @@ module Psychgus
580
569
  # # (5:2):Psych::Nodes::Sequence - <seq:(4:3)>
581
570
  # # (6:1):Salt - <seq:(5:2)>
582
571
  # # (6:2):Pepper - <seq:(5:2)>
583
- #
572
+ #
584
573
  # @param objects [Object,Array<Object>] the Object(s) to get a visual hierarchy of
585
574
  # @param kargs [Hash] the keyword args to pass to {Stylers::HierarchyStyler} and to {dump_stream}
586
- #
575
+ #
587
576
  # @return [String] the visual hierarchy of levels
588
- #
577
+ #
589
578
  # @see Stylers::HierarchyStyler
590
579
  # @see dump_stream
591
- #
580
+ #
592
581
  # @since 1.2.0
593
582
  def self.hierarchy(*objects,**kargs)
594
583
  styler = Stylers::HierarchyStyler.new(**kargs)
595
-
584
+
596
585
  dump_stream(*objects,stylers: styler,**kargs)
597
-
598
- return styler.to_s()
586
+
587
+ return styler.to_s
599
588
  end
600
-
589
+
601
590
  # Parse +yaml+ into a Psych::Nodes::Document.
602
- #
591
+ #
603
592
  # If you're just going to call to_ruby(), then using this method is unnecessary,
604
593
  # and the styler(s) will do nothing for you.
605
- #
594
+ #
606
595
  # @param yaml [String] the YAML to parse
607
596
  # @param kargs [Hash] the keyword args to use; see {.parse_stream}
608
- #
597
+ #
609
598
  # @return [Psych::Nodes::Document] the parsed Document node
610
- #
599
+ #
611
600
  # @see .parse_stream
612
601
  # @see Psych.parse
613
602
  # @see Psych::Nodes::Document
@@ -615,40 +604,43 @@ module Psychgus
615
604
  parse_stream(yaml,**kargs) do |node|
616
605
  return node
617
606
  end
618
-
607
+
619
608
  return false
620
609
  end
621
-
610
+
622
611
  # Parse a YAML file into a Psych::Nodes::Document.
623
- #
612
+ #
624
613
  # If you're just going to call to_ruby(), then using this method is unnecessary,
625
614
  # and the styler(s) will do nothing for you.
626
- #
615
+ #
627
616
  # @param filename [String] the name of the YAML file (and path) to parse
628
617
  # @param fallback [Object] the return value when nothing is parsed
629
618
  # @param mode [String,Integer] the IO open mode to use; example: +'r:BOM|UTF-8'+
619
+ # @param opt [Hash] Hash of keyword args to pass to +File.open()+
630
620
  # @param kargs [Hash] the keyword args to use; see {.parse_stream}
631
- #
621
+ #
632
622
  # @return [Psych::Nodes::Document] the parsed Document node
633
- #
623
+ #
634
624
  # @see .parse_stream
635
625
  # @see Psych.parse_file
636
626
  # @see Psych::Nodes::Document
637
627
  # @see File.open
638
628
  # @see IO.new
639
- def self.parse_file(filename,fallback: false,mode: 'r:BOM|UTF-8',**kargs)
640
- result = File.open(filename,mode) do |file|
629
+ def self.parse_file(filename,fallback: false,mode: 'r:BOM|UTF-8',opt: nil,**kargs)
630
+ opt = Hash(opt)
631
+
632
+ result = File.open(filename,mode,**opt) do |file|
641
633
  parse(file,filename: filename,**kargs)
642
634
  end
643
-
635
+
644
636
  return result || fallback
645
637
  end
646
-
638
+
647
639
  # Parse +yaml+ into a Psych::Nodes::Stream for one document or for multiple documents in one YAML.
648
- #
640
+ #
649
641
  # If you're just going to call to_ruby(), then using this method is unnecessary,
650
642
  # and the styler(s) will do nothing for you.
651
- #
643
+ #
652
644
  # @example
653
645
  # burgers = <<EOY
654
646
  # ---
@@ -662,9 +654,9 @@ module Psychgus
662
654
  # ---
663
655
  # `Invalid`
664
656
  # EOY
665
- #
657
+ #
666
658
  # i = 0
667
- #
659
+ #
668
660
  # begin
669
661
  # Psychgus.parse_stream(burgers,filename: 'burgers.yaml') do |document|
670
662
  # puts "Document ##{i += 1}"
@@ -673,52 +665,52 @@ module Psychgus
673
665
  # rescue Psych::SyntaxError => err
674
666
  # puts "File: #{err.file}"
675
667
  # end
676
- #
668
+ #
677
669
  # # Output:
678
670
  # # Document #1
679
671
  # # {"Burgers"=>{"Classic"=>{"BBQ"=>{"Sauce"=>"Honey BBQ", "Cheese"=>"Cheddar", "Bun"=>"Kaiser"}}}}
680
672
  # # Document #2
681
673
  # # {"Toppings"=>[["Mushrooms", "Mustard"], ["Salt", "Pepper", "Pickles"]]}
682
674
  # # File: burgers.yaml
683
- #
675
+ #
684
676
  # @param yaml [String] the YAML to parse
685
677
  # @param filename [String] the filename to pass as +file+ to the Error potentially raised
686
678
  # @param stylers [nil,Styler,Array<Styler>] the Styler(s) to use when parsing the YAML
687
679
  # @param deref_aliases [true,false] whether to dereference aliases; output the actual value
688
680
  # instead of the alias
689
681
  # @param block [Proc] an optional block for parsing multiple documents
690
- #
682
+ #
691
683
  # @return [Psych::Nodes::Stream] the parsed Stream node
692
- #
684
+ #
693
685
  # @see StyledDocumentStream
694
686
  # @see Psych.parse_stream
695
687
  # @see Psych::Nodes::Stream
696
688
  # @see Psych::SyntaxError
697
689
  def self.parse_stream(yaml,filename: nil,stylers: nil,deref_aliases: false,**options,&block)
698
- if block_given?()
690
+ if block_given?
699
691
  parser = Psych::Parser.new(StyledDocumentStream.new(*stylers,deref_aliases: deref_aliases,**options,
700
692
  &block))
701
-
693
+
702
694
  return parser.parse(yaml,filename)
703
695
  else
704
696
  parser = self.parser(stylers: stylers,deref_aliases: deref_aliases,**options)
705
697
  parser.parse(yaml,filename)
706
-
698
+
707
699
  return parser.handler.root
708
700
  end
709
701
  end
710
-
702
+
711
703
  # Create a new styled Psych::Parser for parsing YAML.
712
- #
704
+ #
713
705
  # @example
714
706
  # class CoffeeStyler
715
707
  # include Psychgus::Styler
716
- #
708
+ #
717
709
  # def style_sequence(sniffer,node)
718
710
  # node.style = Psychgus::SEQUENCE_FLOW
719
711
  # end
720
712
  # end
721
- #
713
+ #
722
714
  # coffee = <<EOY
723
715
  # Coffee:
724
716
  # Roast:
@@ -730,43 +722,43 @@ module Psychgus
730
722
  # - Latte
731
723
  # - Mocha
732
724
  # EOY
733
- #
725
+ #
734
726
  # parser = Psychgus.parser(stylers: CoffeeStyler.new)
735
727
  # parser.parse(coffee)
736
728
  # puts parser.handler.root.to_yaml
737
- #
729
+ #
738
730
  # # Output:
739
731
  # # Coffee:
740
732
  # # Roast: [Light, Medium, Dark]
741
733
  # # Style: [Cappuccino, Latte, Mocha]
742
- #
734
+ #
743
735
  # @param stylers [nil,Styler,Array<Styler>] the Styler(s) to use when parsing the YAML
744
736
  # @param deref_aliases [true,false] whether to dereference aliases; output the actual value
745
737
  # instead of the alias
746
- #
738
+ #
747
739
  # @return [Psych::Parser] the new styled Parser
748
- #
740
+ #
749
741
  # @see StyledTreeBuilder
750
742
  # @see Psych.parser
751
743
  def self.parser(stylers: nil,deref_aliases: false,**options)
752
744
  return Psych::Parser.new(StyledTreeBuilder.new(*stylers,deref_aliases: deref_aliases,**options))
753
745
  end
754
-
746
+
755
747
  ###
756
748
  # Unnecessary Methods
757
- #
749
+ #
758
750
  # All of the below methods are not needed, but are defined
759
751
  # so that Psychgus can be a drop-in replacement for Psych.
760
- #
752
+ #
761
753
  # Instead, you should probably use Psych.
762
754
  # This is also the recommended practice in case your version
763
755
  # of Psych defines the method differently.
764
- #
756
+ #
765
757
  # Private methods of Psych are not defined.
766
- #
758
+ #
767
759
  # @note For devs/hacking: because extend is used, do not prefix methods with "self."
768
- #
769
- # @author Jonathan Bradley Whited (@esotericpig)
760
+ #
761
+ # @author Jonathan Bradley Whited
770
762
  # @since 1.0.0
771
763
  ###
772
764
  module PsychDropIn
@@ -774,47 +766,47 @@ module Psychgus
774
766
  def add_builtin_type(*args,&block)
775
767
  Psych.add_builtin_type(*args,&block)
776
768
  end
777
-
769
+
778
770
  # @see Psych.add_domain_type
779
771
  def add_domain_type(*args,&block)
780
772
  Psych.add_domain_type(*args,&block)
781
773
  end
782
-
774
+
783
775
  # @see Psych.add_tag
784
776
  def add_tag(*args)
785
777
  Psych.add_tag(*args)
786
778
  end
787
-
779
+
788
780
  # @see Psych.load
789
781
  def load(*args,**kargs)
790
782
  Psych.load(*args,**kargs)
791
783
  end
792
-
784
+
793
785
  # @see Psych.load_file
794
786
  def load_file(*args,**kargs)
795
787
  Psych.load_file(*args,**kargs)
796
788
  end
797
-
789
+
798
790
  # @see Psych.load_stream
799
791
  def load_stream(*args,**kargs)
800
792
  Psych.load_stream(*args,**kargs)
801
793
  end
802
-
794
+
803
795
  # @see Psych.remove_type
804
796
  def remove_type(*args)
805
797
  Psych.remove_type(*args)
806
798
  end
807
-
799
+
808
800
  # @see Psych.safe_load
809
801
  def safe_load(*args,**kargs)
810
802
  Psych.safe_load(*args,**kargs)
811
803
  end
812
-
804
+
813
805
  # @see Psych.to_json
814
806
  def to_json(*args)
815
807
  Psych.to_json(*args)
816
808
  end
817
809
  end
818
-
810
+
819
811
  extend PsychDropIn
820
812
  end