summaryrefslogtreecommitdiff
path: root/lib/coderay/encoders/xml.rb
blob: 5596f46dd9b68ef3ef290f6865cbb516c9651823 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
module CodeRay
	module Encoders

		# = Debug Encoder
		class XML < Encoder

			include Streamable
			register_for :xml

			FILE_EXTENSION = 'xml'

			require 'rexml/document'

			DEFAULT_OPTIONS = {
				:tab_width => 8,
				:pretty => -1,
				:transitive => false,
			}

		protected
			
			def setup options
				@out = ''
				@doc = REXML::Document.new
				@doc << REXML::XMLDecl.new
				@tab_width = options[:tab_width]
				@root = @node = @doc.add_element('coderay-tokens')
			end
			
			def finish options
				@doc.write @out, options[:pretty], options[:transitive], true
				@out
			end
			
			def text_token text, kind
				if kind == :space
					token = @node
				else
					token = @node.add_element kind.to_s
				end
				text.scan(/(\x20+)|(\t+)|(\n)|[^\x20\t\n]+/) do |space, tab, nl|
					case
					when space
						token << REXML::Text.new(space, true)
					when tab
						token << REXML::Text.new(tab, true)
					when nl
						token << REXML::Text.new(nl, true)
					else
						token << REXML::Text.new($&)
					end
				end
			end

			def open_token kind
				@node = @node.add_element kind.to_s
			end

			def close_token kind
				if @node == @root
					raise 'no token to close!'
				end
				@node = @node.parent
			end

		end

	end
end