psychgus 1.2.0 → 1.3.4

Sign up to get free protection for your applications and to get access to all the features.
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