summaryrefslogtreecommitdiffstats
path: root/lib/yaml/baseemitter.rb
diff options
context:
space:
mode:
authorwhy <why@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-07-11 23:56:42 +0000
committerwhy <why@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-07-11 23:56:42 +0000
commitc74be7e1a2664ad92a5000d519ef31d75838fda0 (patch)
tree5a59b1baa851ded983192804cad67a33246bdb3d /lib/yaml/baseemitter.rb
parentd1ee5e08ab0cd065d10e9ae2191b61a87aa9e36b (diff)
downloadruby-c74be7e1a2664ad92a5000d519ef31d75838fda0.tar.gz
ruby-c74be7e1a2664ad92a5000d519ef31d75838fda0.tar.xz
ruby-c74be7e1a2664ad92a5000d519ef31d75838fda0.zip
BaseEmitter left out as well.
git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@4068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/yaml/baseemitter.rb')
-rw-r--r--lib/yaml/baseemitter.rb241
1 files changed, 241 insertions, 0 deletions
diff --git a/lib/yaml/baseemitter.rb b/lib/yaml/baseemitter.rb
new file mode 100644
index 000000000..007ee7be5
--- /dev/null
+++ b/lib/yaml/baseemitter.rb
@@ -0,0 +1,241 @@
+#
+# BaseEmitter
+#
+
+require 'yaml/constants'
+require 'yaml/encoding'
+require 'yaml/error'
+
+module YAML
+
+ module BaseEmitter
+
+ def options( opt = nil )
+ if opt
+ @options[opt] || YAML::DEFAULTS[opt]
+ else
+ @options
+ end
+ end
+
+ def options=( opt )
+ @options = opt
+ end
+
+ #
+ # Emit binary data
+ #
+ def binary_base64( value )
+ self << "!binary "
+ self.node_text( [value].pack("m"), '|' )
+ end
+
+ #
+ # Emit plain, normal flowing text
+ #
+ def node_text( value, block = '>' )
+ @seq_map = false
+ valx = value.dup
+ if options(:UseBlock)
+ block = '|'
+ elsif not options(:UseFold) and valx =~ /\n[ \t]/ and not valx =~ /#{YAML::ESCAPE_CHAR}/
+ block = '|'
+ end
+ str = block.dup
+ if valx =~ /\n\Z\n/
+ str << "+"
+ elsif valx =~ /\Z\n/
+ else
+ str << "-"
+ end
+ if valx =~ /#{YAML::ESCAPE_CHAR}/
+ valx = YAML::escape( valx )
+ end
+ if valx =~ /\A[ \t#]/
+ str << options(:Indent).to_s
+ end
+ if block == '>'
+ valx = fold( valx )
+ end
+ self << str + indent_text( valx ) + "\n"
+ end
+
+ #
+ # Emit a simple, unqouted string
+ #
+ def simple( value )
+ @seq_map = false
+ self << value.to_s
+ end
+
+ #
+ # Emit double-quoted string
+ #
+ def double( value )
+ "\"#{YAML.escape( value )}\""
+ end
+
+ #
+ # Emit single-quoted string
+ #
+ def single( value )
+ "'#{value}'"
+ end
+
+ #
+ # Write a text block with the current indent
+ #
+ def indent_text( text )
+ return "" if text.to_s.empty?
+ spacing = " " * ( level * options(:Indent) )
+ return "\n" + text.gsub( /^([^\n])/, "#{spacing}\\1" )
+ end
+
+ #
+ # Write a current indent
+ #
+ def indent
+ #p [ self.id, @level, :INDENT ]
+ return " " * ( level * options(:Indent) )
+ end
+
+ #
+ # Add indent to the buffer
+ #
+ def indent!
+ self << indent
+ end
+
+ #
+ # Folding paragraphs within a column
+ #
+ def fold( value )
+ value.gsub!( /\A\n+/, '' )
+ folded = $&.to_s
+ width = (0..options(:BestWidth))
+ while not value.empty?
+ last = value.index( /(\n+)/ )
+ chop_s = false
+ if width.include?( last )
+ last += $1.length - 1
+ elsif width.include?( value.length )
+ last = value.length
+ else
+ last = value.rindex( /[ \t]/, options(:BestWidth) )
+ chop_s = true
+ end
+ folded += value.slice!( 0, width.include?( last ) ? last + 1 : options(:BestWidth) )
+ folded.chop! if chop_s
+ folded += "\n" unless value.empty?
+ end
+ folded
+ end
+
+ #
+ # Quick mapping
+ #
+ def map( type, &e )
+ val = Mapping.new
+ e.call( val )
+ self << "#{type} " if type.length.nonzero?
+
+ #
+ # Empty hashes
+ #
+ if val.length.zero?
+ self << "{}"
+ @seq_map = false
+ else
+ # FIXME
+ # if @buffer.length == 1 and options(:UseHeader) == false and type.length.zero?
+ # @headless = 1
+ # end
+
+ defkey = @options.delete( :DefaultKey )
+ if defkey
+ seq_map_shortcut
+ self << "= : "
+ defkey.to_yaml( :Emitter => self )
+ end
+
+ #
+ # Emit the key and value
+ #
+ val.each { |v|
+ seq_map_shortcut
+ if v[0].is_complex_yaml?
+ self << "? "
+ end
+ v[0].to_yaml( :Emitter => self )
+ if v[0].is_complex_yaml?
+ self << "\n"
+ indent!
+ end
+ self << ": "
+ v[1].to_yaml( :Emitter => self )
+ }
+ end
+ end
+
+ def seq_map_shortcut
+ # FIXME: seq_map needs to work with the new anchoring system
+ # if @seq_map
+ # @anchor_extras[@buffer.length - 1] = "\n" + indent
+ # @seq_map = false
+ # else
+ self << "\n"
+ indent!
+ # end
+ end
+
+ #
+ # Quick sequence
+ #
+ def seq( type, &e )
+ @seq_map = false
+ val = Sequence.new
+ e.call( val )
+ self << "#{type} " if type.length.nonzero?
+
+ #
+ # Empty arrays
+ #
+ if val.length.zero?
+ self << "[]"
+ else
+ # FIXME
+ # if @buffer.length == 1 and options(:UseHeader) == false and type.length.zero?
+ # @headless = 1
+ # end
+
+ #
+ # Emit the key and value
+ #
+ val.each { |v|
+ self << "\n"
+ indent!
+ self << "- "
+ @seq_map = true if v.class == Hash
+ v.to_yaml( :Emitter => self )
+ }
+ end
+ end
+
+ end
+
+ #
+ # Emitter helper classes
+ #
+ class Mapping < Array
+ def add( k, v )
+ push [k, v]
+ end
+ end
+
+ class Sequence < Array
+ def add( v )
+ push v
+ end
+ end
+
+end