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}
- OPTIONS_ALIASES =
{:canon => :canonical,:indent => :indentation}
- 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.2'
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.
397 398 399 |
# File 'lib/psychgus.rb', line 397 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.
423 424 425 426 427 428 429 |
# File 'lib/psychgus.rb', line 423 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.
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 493 494 495 496 497 498 499 500 501 502 |
# File 'lib/psychgus.rb', line 457 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 Hash === io = 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.
592 593 594 595 596 597 598 |
# File 'lib/psychgus.rb', line 592 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
333 334 335 336 337 338 339 340 |
# File 'lib/psychgus.rb', line 333 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).
351 352 353 354 355 356 357 |
# File 'lib/psychgus.rb', line 351 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.
613 614 615 616 617 618 619 |
# File 'lib/psychgus.rb', line 613 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.
639 640 641 642 643 644 645 646 647 |
# File 'lib/psychgus.rb', line 639 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.
699 700 701 702 703 704 705 706 707 708 709 710 711 |
# File 'lib/psychgus.rb', line 699 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.
753 754 755 |
# File 'lib/psychgus.rb', line 753 def self.parser(stylers: nil,deref_aliases: false,**) return Psych::Parser.new(StyledTreeBuilder.new(*stylers,deref_aliases: deref_aliases,**)) end |