Chris@909: module CodeRay Chris@909: module Encoders Chris@909: Chris@909: # = XML Encoder Chris@909: # Chris@909: # Uses REXML. Very slow. Chris@909: class XML < Encoder Chris@909: Chris@909: register_for :xml Chris@909: Chris@909: FILE_EXTENSION = 'xml' Chris@909: Chris@909: autoload :REXML, 'rexml/document' Chris@909: Chris@909: DEFAULT_OPTIONS = { Chris@909: :tab_width => 8, Chris@909: :pretty => -1, Chris@909: :transitive => false, Chris@909: } Chris@909: Chris@909: protected Chris@909: def setup options Chris@909: super Chris@909: Chris@909: @doc = REXML::Document.new Chris@909: @doc << REXML::XMLDecl.new Chris@909: @tab_width = options[:tab_width] Chris@909: @root = @node = @doc.add_element('coderay-tokens') Chris@909: end Chris@909: Chris@909: def finish options Chris@909: @doc.write @out, options[:pretty], options[:transitive], true Chris@909: Chris@909: super Chris@909: end Chris@909: Chris@909: public Chris@909: def text_token text, kind Chris@909: if kind == :space Chris@909: token = @node Chris@909: else Chris@909: token = @node.add_element kind.to_s Chris@909: end Chris@909: text.scan(/(\x20+)|(\t+)|(\n)|[^\x20\t\n]+/) do |space, tab, nl| Chris@909: case Chris@909: when space Chris@909: token << REXML::Text.new(space, true) Chris@909: when tab Chris@909: token << REXML::Text.new(tab, true) Chris@909: when nl Chris@909: token << REXML::Text.new(nl, true) Chris@909: else Chris@909: token << REXML::Text.new($&) Chris@909: end Chris@909: end Chris@909: end Chris@909: Chris@909: def begin_group kind Chris@909: @node = @node.add_element kind.to_s Chris@909: end Chris@909: Chris@909: def end_group kind Chris@909: if @node == @root Chris@909: raise 'no token to close!' Chris@909: end Chris@909: @node = @node.parent Chris@909: end Chris@909: Chris@909: end Chris@909: Chris@909: end Chris@909: end