mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/yaml.rb: reworking YAML::Stream to use the new
emitter. * lib/yaml/stream.rb: ditto. * lib/yaml/rubytypes.rb: added Object#yaml_new. * lib/yaml/tag.rb: the tag_subclasses? method now shows up in the class. allow taguri to be set using an accessor. continue support of Object#to_yaml_type. * ext/syck/rubyext.c: new emitter code. yaml_new and yaml_initialize get called, should they be present. consolidated all the diaspora of internal node types into the family below YAML::Syck::Node -- Map, Seq, Scalar -- all of whom are SyckNode structs pointing to Ruby data. moved Object#yaml_new into the node_import and made it the default behavior. the target_class is always called wih yaml_new, prepended a parameter, which is the klass. loaded nodes through GenericResolver show their style. new Resolver#tagurize converts type ids to taguris. * ext/syck/implicit.re: were 'y' and 'n' seriously omitted?? * ext/syck/emitter.c: renovated emitter, walks the tree in advance. consolidated redundant block_styles struct into the scalar_style struct. (this means loaded nodes can now be sent back to emitter and preserve at least its very basic formatting.) * ext/syck/gram.c: headless documents of any kind allowed. * ext/syck/node.c: new syck_replace_str methods and syck_empty_* methods for rewriting node contents, while keeping the ID and other setup info. added syck_seq_assign. * ext/syck/syck.h: reflect block_styles and new node functions. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9139 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ef1ccbbc40
commit
9852657e86
3 changed files with 38 additions and 354 deletions
38
ChangeLog
38
ChangeLog
|
@ -1,3 +1,41 @@
|
|||
Tue Sep 13 12:33:05 2005 <why@ruby-lang.org>
|
||||
|
||||
* lib/yaml.rb: reworking YAML::Stream to use the new
|
||||
emitter.
|
||||
|
||||
* lib/yaml/stream.rb: ditto.
|
||||
|
||||
* lib/yaml/rubytypes.rb: added Object#yaml_new.
|
||||
|
||||
* lib/yaml/tag.rb: the tag_subclasses? method now
|
||||
shows up in the class. allow taguri to be set using an accessor.
|
||||
continue support of Object#to_yaml_type.
|
||||
|
||||
* ext/syck/rubyext.c: new emitter code. yaml_new and yaml_initialize
|
||||
get called, should they be present. consolidated all the diaspora of internal
|
||||
node types into the family below YAML::Syck::Node -- Map,
|
||||
Seq, Scalar -- all of whom are SyckNode structs pointing to
|
||||
Ruby data. moved Object#yaml_new into the node_import and made it the
|
||||
default behavior. the target_class is always called wih yaml_new, prepended
|
||||
a parameter, which is the klass. loaded nodes through GenericResolver show their style.
|
||||
new Resolver#tagurize converts type ids to taguris.
|
||||
|
||||
* ext/syck/implicit.re: were 'y' and 'n' seriously omitted??
|
||||
|
||||
* ext/syck/emitter.c: renovated emitter, walks the tree in advance.
|
||||
consolidated redundant block_styles struct into
|
||||
the scalar_style struct. (this means loaded nodes can now
|
||||
be sent back to emitter and preserve at least its very basic
|
||||
formatting.)
|
||||
|
||||
* ext/syck/gram.c: headless documents of any kind allowed.
|
||||
|
||||
* ext/syck/node.c: new syck_replace_str methods and syck_empty_*
|
||||
methods for rewriting node contents, while keeping the ID
|
||||
and other setup info. added syck_seq_assign.
|
||||
|
||||
* ext/syck/syck.h: reflect block_styles and new node functions.
|
||||
|
||||
Tue Sep 13 08:09:18 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* lib/ostruct.rb (new_ostruct_member): Object#send no longer call
|
||||
|
|
|
@ -1,247 +0,0 @@
|
|||
#
|
||||
# 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 = nil )
|
||||
@seq_map = false
|
||||
valx = value.dup
|
||||
unless block
|
||||
block =
|
||||
if options(:UseBlock)
|
||||
'|'
|
||||
elsif not options(:UseFold) and valx =~ /\n[ \t]/ and not valx =~ /#{YAML::ESCAPE_CHAR}/
|
||||
'|'
|
||||
else
|
||||
'>'
|
||||
end
|
||||
|
||||
indt = $&.to_i if block =~ /\d+/
|
||||
if valx =~ /(\A\n*[ \t#]|^---\s+)/
|
||||
indt = options(:Indent) unless indt.to_i > 0
|
||||
block += indt.to_s
|
||||
end
|
||||
|
||||
block +=
|
||||
if valx =~ /\n\Z\n/
|
||||
"+"
|
||||
elsif valx =~ /\Z\n/
|
||||
""
|
||||
else
|
||||
"-"
|
||||
end
|
||||
end
|
||||
block += "\n"
|
||||
if block[0] == ?"
|
||||
esc_skip = ( "\t\n" unless valx =~ /^[ \t]/ ) || ""
|
||||
valx = fold( YAML::escape( valx, esc_skip ) + "\"" ).chomp
|
||||
self << '"' + indent_text( valx, indt, false )
|
||||
else
|
||||
if block[0] == ?>
|
||||
valx = fold( valx )
|
||||
end
|
||||
#p [block, indt]
|
||||
self << block + indent_text( valx, indt )
|
||||
end
|
||||
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, mod, first_line = true )
|
||||
return "" if text.to_s.empty?
|
||||
spacing = indent( mod )
|
||||
text = text.gsub( /\A([^\n])/, "#{ spacing }\\1" ) if first_line
|
||||
return text.gsub( /\n^([^\n])/, "\n#{spacing}\\1" )
|
||||
end
|
||||
|
||||
#
|
||||
# Write a current indent
|
||||
#
|
||||
def indent( mod = nil )
|
||||
#p [ self.id, level, mod, :INDENT ]
|
||||
if level <= 0
|
||||
mod ||= 0
|
||||
else
|
||||
mod ||= options(:Indent)
|
||||
mod += ( level - 1 ) * options(:Indent)
|
||||
end
|
||||
return " " * mod
|
||||
end
|
||||
|
||||
#
|
||||
# Add indent to the buffer
|
||||
#
|
||||
def indent!
|
||||
self << indent
|
||||
end
|
||||
|
||||
#
|
||||
# Folding paragraphs within a column
|
||||
#
|
||||
def fold( value )
|
||||
value.gsub( /(^[ \t]+.*$)|(\S.{0,#{options(:BestWidth) - 1}})(?:[ \t]+|(\n+(?=[ \t]|\Z))|$)/ ) do |s|
|
||||
$1 || $2 + ( $3 || "\n" )
|
||||
end
|
||||
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
|
|
@ -1,107 +0,0 @@
|
|||
#
|
||||
# Output classes and methods
|
||||
#
|
||||
|
||||
require 'yaml/baseemitter'
|
||||
require 'yaml/encoding'
|
||||
|
||||
module YAML
|
||||
|
||||
#
|
||||
# Emit a set of values
|
||||
#
|
||||
|
||||
class Emitter
|
||||
|
||||
include BaseEmitter
|
||||
|
||||
attr_accessor :options
|
||||
|
||||
def initialize( opts )
|
||||
opts = {} if opts.class != Hash
|
||||
@options = YAML::DEFAULTS.dup.update( opts )
|
||||
@headless = 0
|
||||
@seq_map = false
|
||||
@anchors = {}
|
||||
@anchor_extras = {}
|
||||
@active_anchors = []
|
||||
@level = -1
|
||||
self.clear
|
||||
end
|
||||
|
||||
def clear
|
||||
@buffer = []
|
||||
end
|
||||
|
||||
def level
|
||||
@level
|
||||
end
|
||||
|
||||
#
|
||||
# Version string
|
||||
#
|
||||
def version_s
|
||||
" %YAML:#{@options[:Version]}" if @options[:UseVersion]
|
||||
end
|
||||
|
||||
#
|
||||
# Header
|
||||
#
|
||||
def header
|
||||
if @headless.nonzero?
|
||||
""
|
||||
else
|
||||
"---#{version_s} "
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Concatenate to the buffer
|
||||
#
|
||||
def <<( str )
|
||||
#p [ self.id, @level, str ]
|
||||
@buffer.last << str
|
||||
end
|
||||
|
||||
#
|
||||
# Monitor objects and allow references
|
||||
#
|
||||
def start_object( oid )
|
||||
@level += 1
|
||||
@buffer.push( "" )
|
||||
#p [ self.id, @level, :OPEN ]
|
||||
idx = nil
|
||||
if oid
|
||||
if @anchors.has_key?( oid )
|
||||
idx = @active_anchors.index( oid )
|
||||
unless idx
|
||||
idx = @active_anchors.length
|
||||
af_str = "&#{@options[:AnchorFormat]} " % [ idx + 1 ]
|
||||
af_str += @anchor_extras[ @anchors[ oid ] ].to_s
|
||||
@buffer[ @anchors[ oid ] ][0,0] = af_str
|
||||
@headless = 0 if @anchors[ oid ].zero?
|
||||
end
|
||||
idx += 1
|
||||
@active_anchors.push( oid )
|
||||
else
|
||||
@anchors[ oid ] = @buffer.length - 1
|
||||
end
|
||||
end
|
||||
return idx
|
||||
end
|
||||
|
||||
#
|
||||
# Output method
|
||||
#
|
||||
def end_object
|
||||
@level -= 1
|
||||
@buffer.push( "" )
|
||||
#p [ self.id, @level, :END ]
|
||||
if @level < 0
|
||||
header + @buffer.to_s[@headless..-1].to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
Loading…
Reference in a new issue