Module: Psychgus
- Extended by:
- PsychDropIn
- Defined in:
- lib/psychgus.rb,
lib/psychgus/ext.rb,
lib/psychgus/styler.rb,
lib/psychgus/stylers.rb,
lib/psychgus/version.rb,
lib/psychgus/blueberry.rb,
lib/psychgus/stylables.rb,
lib/psychgus/ext/core_ext.rb,
lib/psychgus/ext/node_ext.rb,
lib/psychgus/super_sniffer.rb,
lib/psychgus/ext/yaml_tree_ext.rb,
lib/psychgus/styled_tree_builder.rb,
lib/psychgus/super_sniffer/parent.rb,
lib/psychgus/styled_document_stream.rb
Overview
Psychgus uses the core standard library Psych for working with YAML and extends it so that developers can easily style the YAML according to their needs. Thank you to the people that worked and continue to work hard on that project.
The name comes from the well-styled character Gus from the TV show Psych.
Create a Styler
First, we will create a Styler.
All you need to do is add include Psychgus::Styler to a class.
Here is a complex Styler for the examples below:
require 'psychgus'
class BurgerStyler
# Mix in methods needed for styling
include Psychgus::Styler
def initialize(sniffer=nil)
if sniffer.nil?()
@class_level = 0
@class_position = 0
else
# For the Class Example
@class_level = sniffer.level
@class_position = sniffer.position
end
end
# Style all nodes (Psych::Nodes::Node)
def style(sniffer,node)
# Remove "!ruby/object:..." for classes
node.tag = nil if node.node_of?(:mapping,:scalar,:sequence)
# This is another way to do the above
#node.tag = nil if node.respond_to?(:tag=)
end
# Style aliases (Psych::Nodes::Alias)
def style_alias(sniffer,node)
end
# Style maps (Psych::Nodes::Mapping)
# - Hashes (key/value pairs)
# - Example: "Burgers: Classic {}"
def style_mapping(sniffer,node)
parent = sniffer.parent
if !parent.nil?()
# BBQ
node.style = Psychgus::MAPPING_FLOW if parent.node_of?(:scalar) &&
parent.value.casecmp('BBQ') == 0
end
end
# Style scalars (Psych::Nodes::Scalar)
# - Any text (non-alias)
def style_scalar(sniffer,node)
parent = sniffer.parent
# Single quote scalars that are not keys to a map
# - "child_key?" is the same as "child_type == :key"
node.style = Psychgus::SCALAR_SINGLE_QUOTED unless parent.child_key?()
# Remove colon (change symbols into strings)
node.value = node.value.sub(':','')
# Change lettuce to spinach
node.value = 'Spinach' if node.value.casecmp('Lettuce') == 0
# Capitalize each word
node.value = node.value.split(' ').map do |v|
if v.casecmp('BBQ') == 0
v.upcase()
else
v.capitalize()
end
end.join(' ')
end
# Style sequences (Psych::Nodes::Sequence)
# - Arrays
# - Example: "[Lettuce, Onions, Pickles, Tomatoes]"
def style_sequence(sniffer,node)
relative_level = (sniffer.level - @class_level) + 1
node.style = Psychgus::SEQUENCE_FLOW if sniffer.level >= 4
# Make "[Ketchup, Mustard]" a block for the Class Example
node.style = Psychgus::SEQUENCE_BLOCK if relative_level == 7
end
end
Defined Under Namespace
Modules: Blueberry, Ext, PsychDropIn, Stylables, Styler, Stylers Classes: StyledDocumentStream, StyledTreeBuilder, SuperSniffer
Constant Summary collapse
- NODE_CLASS_ALIASES =
{Doc: :Document,Map: :Mapping,Seq: :Sequence}.freeze
- OPTIONS_ALIASES =
{canon: :canonical,indent: :indentation}.freeze
- MAPPING_ANY =
node_const(:mapping,:any)
- MAPPING_BLOCK =
node_const(:mapping,:block)
- MAPPING_FLOW =
node_const(:mapping,:flow)
- MAP_ANY =
MAPPING_ANY
- MAP_BLOCK =
MAPPING_BLOCK
- MAP_FLOW =
MAPPING_FLOW
- SCALAR_ANY =
node_const(:scalar,:any)
- SCALAR_PLAIN =
node_const(:scalar,:plain)
- SCALAR_SINGLE_QUOTED =
node_const(:scalar,:single_quoted)
- SCALAR_DOUBLE_QUOTED =
node_const(:scalar,:double_quoted)
- SCALAR_LITERAL =
node_const(:scalar,:literal)
- SCALAR_FOLDED =
node_const(:scalar,:folded)
- SEQUENCE_ANY =
node_const(:sequence,:any)
- SEQUENCE_BLOCK =
node_const(:sequence,:block)
- SEQUENCE_FLOW =
node_const(:sequence,:flow)
- SEQ_ANY =
SEQUENCE_ANY
- SEQ_BLOCK =
SEQUENCE_BLOCK
- SEQ_FLOW =
SEQUENCE_FLOW
- STREAM_ANY =
node_const(:stream,:any)
- STREAM_UTF8 =
node_const(:stream,:utf8)
- STREAM_UTF16LE =
node_const(:stream,:utf16le)
- STREAM_UTF16BE =
node_const(:stream,:utf16be)
- VERSION =
Version of this gem in “#.#.#” format
'1.3.4'
Class Method Summary collapse
-
.dump(object, io = nil, **options) ⇒ String, Object
Convert
object
to YAML and dump toio
. -
.dump_file(filename, *objects, mode: 'w', perm: nil, opt: nil, **options) ⇒ Object
Convert
objects
to YAML and dump to a file. -
.dump_stream(*objects, io: nil, stylers: nil, deref_aliases: false, **options) ⇒ String, Object
Convert
objects
to YAML and dump toio
. -
.hierarchy(*objects, **kargs) ⇒ String
Get a visual hierarchy of the levels as a String.
-
.node_class(name) ⇒ Class
Get a Class (constant) from Psych::Nodes.
-
.node_const(class_name, const_name, lenient = true) ⇒ Integer, Object
Get a constant from a Psych::Nodes class (using Psychgus.node_class).
-
.parse(yaml, **kargs) ⇒ Psych::Nodes::Document
Parse
yaml
into a Psych::Nodes::Document. -
.parse_file(filename, fallback: false, mode: 'r:BOM|UTF-8', opt: nil, **kargs) ⇒ Psych::Nodes::Document
Parse a YAML file into a Psych::Nodes::Document.
-
.parse_stream(yaml, filename: nil, stylers: nil, deref_aliases: false, **options, &block) ⇒ Psych::Nodes::Stream
Parse
yaml
into a Psych::Nodes::Stream for one document or for multiple documents in one YAML. -
.parser(stylers: nil, deref_aliases: false, **options) ⇒ Psych::Parser
Create a new styled Psych::Parser for parsing YAML.
Methods included from PsychDropIn
add_builtin_type, add_domain_type, add_tag, load, load_file, load_stream, remove_type, safe_load, to_json
Class Method Details
.dump(object, io = nil, **options) ⇒ String, Object
Convert object
to YAML and dump to io
.
object
, io
, and options
are used like in Psych.dump so can be a drop-in replacement for Psych.
386 387 388 |
# File 'lib/psychgus.rb', line 386 def self.dump(object,io=nil,**) return dump_stream(object,io: io,**) end |
.dump_file(filename, *objects, mode: 'w', perm: nil, opt: nil, **options) ⇒ Object
Convert objects
to YAML and dump to a file.
412 413 414 415 416 417 418 |
# File 'lib/psychgus.rb', line 412 def self.dump_file(filename,*objects,mode: 'w',perm: nil,opt: nil,**) opt = Hash(opt) File.open(filename,mode,perm,**opt) do |file| file.write(dump_stream(*objects,**)) end end |
.dump_stream(*objects, io: nil, stylers: nil, deref_aliases: false, **options) ⇒ String, Object
Convert objects
to YAML and dump to io
.
io
and options
are used like in Psych.dump so can be a drop-in replacement for Psych.
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 |
# File 'lib/psychgus.rb', line 446 def self.dump_stream(*objects,io: nil,stylers: nil,deref_aliases: false,**) # If you call this method with only a Hash that uses symbols as keys, # then options will be set to the Hash, instead of objects. # # For example, the below will be stored in options, not objects: # - dump_stream({:coffee => {:roast => [],:style => []}}) # # This if-statement is guaranteed because dump_stream([]) and dump_stream(nil) # will produce [[]] and [nil], which are not empty. # # dump_stream() w/o any args is the only problem, but resolved w/ [nil]. if objects.empty? objects = .empty? ? [nil] : [] = {} end if io.is_a?(Hash) = io io = nil end if !.empty? OPTIONS_ALIASES.each do |option_alias,actual_option| if .key?(option_alias) && !.key?(actual_option) [actual_option] = [option_alias] end end end visitor = Psych::Visitors::YAMLTree.create(,StyledTreeBuilder.new(*stylers, deref_aliases: deref_aliases)) if objects.empty? # Else, will throw a cryptic NoMethodError: # - "psych/tree_builder.rb:in `set_end_location': # undefined method `end_line=' for nil:NilClass (NoMethodError)" # # This should never occur because of the if-statement at the top of this method. visitor << nil else objects.each do |object| visitor << object end end return visitor.tree.yaml(io,) end |
.hierarchy(*objects, **kargs) ⇒ String
Get a visual hierarchy of the levels as a String.
This is useful for determining the correct level/position when writing a Styler.
582 583 584 585 586 587 588 |
# File 'lib/psychgus.rb', line 582 def self.hierarchy(*objects,**kargs) styler = Stylers::HierarchyStyler.new(**kargs) dump_stream(*objects,stylers: styler,**kargs) return styler.to_s end |
.node_class(name) ⇒ Class
Get a Class (constant) from Psych::Nodes.
Some names have aliases:
:doc => :document
:map => :mapping
:seq => :sequence
322 323 324 325 326 327 328 329 |
# File 'lib/psychgus.rb', line 322 def self.node_class(name) name = name.to_sym.capitalize actual_name = NODE_CLASS_ALIASES[name] name = actual_name unless actual_name.nil? return Psych::Nodes.const_get(name) end |
.node_const(class_name, const_name, lenient = true) ⇒ Integer, Object
Get a constant from a Psych::Nodes class (using node_class).
340 341 342 343 344 345 346 |
# File 'lib/psychgus.rb', line 340 def self.node_const(class_name,const_name,lenient=true) node_class = node_class(class_name) const_name = const_name.to_sym.upcase return 0 if lenient && !node_class.const_defined?(const_name,true) return node_class.const_get(const_name,true) end |
.parse(yaml, **kargs) ⇒ Psych::Nodes::Document
Parse yaml
into a Psych::Nodes::Document.
If you’re just going to call to_ruby(), then using this method is unnecessary, and the styler(s) will do nothing for you.
603 604 605 606 607 608 609 |
# File 'lib/psychgus.rb', line 603 def self.parse(yaml,**kargs) parse_stream(yaml,**kargs) do |node| return node end return false end |
.parse_file(filename, fallback: false, mode: 'r:BOM|UTF-8', opt: nil, **kargs) ⇒ Psych::Nodes::Document
Parse a YAML file into a Psych::Nodes::Document.
If you’re just going to call to_ruby(), then using this method is unnecessary, and the styler(s) will do nothing for you.
629 630 631 632 633 634 635 636 637 |
# File 'lib/psychgus.rb', line 629 def self.parse_file(filename,fallback: false,mode: 'r:BOM|UTF-8',opt: nil,**kargs) opt = Hash(opt) result = File.open(filename,mode,**opt) do |file| parse(file,filename: filename,**kargs) end return result || fallback end |
.parse_stream(yaml, filename: nil, stylers: nil, deref_aliases: false, **options, &block) ⇒ Psych::Nodes::Stream
Parse yaml
into a Psych::Nodes::Stream for one document or for multiple documents in one YAML.
If you’re just going to call to_ruby(), then using this method is unnecessary, and the styler(s) will do nothing for you.
689 690 691 692 693 694 695 696 697 698 699 700 701 |
# File 'lib/psychgus.rb', line 689 def self.parse_stream(yaml,filename: nil,stylers: nil,deref_aliases: false,**,&block) if block_given? parser = Psych::Parser.new(StyledDocumentStream.new(*stylers,deref_aliases: deref_aliases,**, &block)) return parser.parse(yaml,filename) else parser = self.parser(stylers: stylers,deref_aliases: deref_aliases,**) parser.parse(yaml,filename) return parser.handler.root end end |
.parser(stylers: nil, deref_aliases: false, **options) ⇒ Psych::Parser
Create a new styled Psych::Parser for parsing YAML.
743 744 745 |
# File 'lib/psychgus.rb', line 743 def self.parser(stylers: nil,deref_aliases: false,**) return Psych::Parser.new(StyledTreeBuilder.new(*stylers,deref_aliases: deref_aliases,**)) end |