comparison vendor/gems/coderay-0.9.7/lib/coderay/.svn/text-base/encoder.rb.svn-base @ 210:0579821a129a

Update to Redmine trunk rev 4802
author Chris Cannam
date Tue, 08 Feb 2011 13:51:46 +0000
parents vendor/plugins/coderay-0.9.2/lib/coderay/encoder.rb@513646585e45
children
comparison
equal deleted inserted replaced
128:07fa8a8b56a8 210:0579821a129a
1 module CodeRay
2
3 # This module holds the Encoder class and its subclasses.
4 # For example, the HTML encoder is named CodeRay::Encoders::HTML
5 # can be found in coderay/encoders/html.
6 #
7 # Encoders also provides methods and constants for the register
8 # mechanism and the [] method that returns the Encoder class
9 # belonging to the given format.
10 module Encoders
11 extend PluginHost
12 plugin_path File.dirname(__FILE__), 'encoders'
13
14 # = Encoder
15 #
16 # The Encoder base class. Together with Scanner and
17 # Tokens, it forms the highlighting triad.
18 #
19 # Encoder instances take a Tokens object and do something with it.
20 #
21 # The most common Encoder is surely the HTML encoder
22 # (CodeRay::Encoders::HTML). It highlights the code in a colorful
23 # html page.
24 # If you want the highlighted code in a div or a span instead,
25 # use its subclasses Div and Span.
26 class Encoder
27 extend Plugin
28 plugin_host Encoders
29
30 attr_reader :token_stream
31
32 class << self
33
34 # Returns if the Encoder can be used in streaming mode.
35 def streamable?
36 is_a? Streamable
37 end
38
39 # If FILE_EXTENSION isn't defined, this method returns the
40 # downcase class name instead.
41 def const_missing sym
42 if sym == :FILE_EXTENSION
43 plugin_id
44 else
45 super
46 end
47 end
48
49 end
50
51 # Subclasses are to store their default options in this constant.
52 DEFAULT_OPTIONS = { :stream => false }
53
54 # The options you gave the Encoder at creating.
55 attr_accessor :options
56
57 # Creates a new Encoder.
58 # +options+ is saved and used for all encode operations, as long
59 # as you don't overwrite it there by passing additional options.
60 #
61 # Encoder objects provide three encode methods:
62 # - encode simply takes a +code+ string and a +lang+
63 # - encode_tokens expects a +tokens+ object instead
64 # - encode_stream is like encode, but uses streaming mode.
65 #
66 # Each method has an optional +options+ parameter. These are
67 # added to the options you passed at creation.
68 def initialize options = {}
69 @options = self.class::DEFAULT_OPTIONS.merge options
70 raise "I am only the basic Encoder class. I can't encode "\
71 "anything. :( Use my subclasses." if self.class == Encoder
72 end
73
74 # Encode a Tokens object.
75 def encode_tokens tokens, options = {}
76 options = @options.merge options
77 setup options
78 compile tokens, options
79 finish options
80 end
81
82 # Encode the given +code+ after tokenizing it using the Scanner
83 # for +lang+.
84 def encode code, lang, options = {}
85 options = @options.merge options
86 scanner_options = CodeRay.get_scanner_options(options)
87 tokens = CodeRay.scan code, lang, scanner_options
88 encode_tokens tokens, options
89 end
90
91 # You can use highlight instead of encode, if that seems
92 # more clear to you.
93 alias highlight encode
94
95 # Encode the given +code+ using the Scanner for +lang+ in
96 # streaming mode.
97 def encode_stream code, lang, options = {}
98 raise NotStreamableError, self unless kind_of? Streamable
99 options = @options.merge options
100 setup options
101 scanner_options = CodeRay.get_scanner_options options
102 @token_stream =
103 CodeRay.scan_stream code, lang, scanner_options, &self
104 finish options
105 end
106
107 # Behave like a proc. The token method is converted to a proc.
108 def to_proc
109 method(:token).to_proc
110 end
111
112 # Return the default file extension for outputs of this encoder.
113 def file_extension
114 self.class::FILE_EXTENSION
115 end
116
117 protected
118
119 # Called with merged options before encoding starts.
120 # Sets @out to an empty string.
121 #
122 # See the HTML Encoder for an example of option caching.
123 def setup options
124 @out = ''
125 end
126
127 # Called with +content+ and +kind+ of the currently scanned token.
128 # For simple scanners, it's enougth to implement this method.
129 #
130 # By default, it calls text_token or block_token, depending on
131 # whether +content+ is a String.
132 def token content, kind
133 encoded_token =
134 if content.is_a? ::String
135 text_token content, kind
136 elsif content.is_a? ::Symbol
137 block_token content, kind
138 else
139 raise 'Unknown token content type: %p' % [content]
140 end
141 append_encoded_token_to_output encoded_token
142 end
143
144 def append_encoded_token_to_output encoded_token
145 @out << encoded_token if encoded_token && defined?(@out) && @out
146 end
147
148 # Called for each text token ([text, kind]), where text is a String.
149 def text_token text, kind
150 end
151
152 # Called for each block (non-text) token ([action, kind]),
153 # where +action+ is a Symbol.
154 #
155 # Calls open_token, close_token, begin_line, and end_line according to
156 # the value of +action+.
157 def block_token action, kind
158 case action
159 when :open
160 open_token kind
161 when :close
162 close_token kind
163 when :begin_line
164 begin_line kind
165 when :end_line
166 end_line kind
167 else
168 raise 'unknown block action: %p' % action
169 end
170 end
171
172 # Called for each block token at the start of the block ([:open, kind]).
173 def open_token kind
174 end
175
176 # Called for each block token end of the block ([:close, kind]).
177 def close_token kind
178 end
179
180 # Called for each line token block at the start of the line ([:begin_line, kind]).
181 def begin_line kind
182 end
183
184 # Called for each line token block at the end of the line ([:end_line, kind]).
185 def end_line kind
186 end
187
188 # Called with merged options after encoding starts.
189 # The return value is the result of encoding, typically @out.
190 def finish options
191 @out
192 end
193
194 # Do the encoding.
195 #
196 # The already created +tokens+ object must be used; it can be a
197 # TokenStream or a Tokens object.
198 if RUBY_VERSION >= '1.9'
199 def compile tokens, options
200 for text, kind in tokens
201 token text, kind
202 end
203 end
204 else
205 def compile tokens, options
206 tokens.each(&self)
207 end
208 end
209
210 end
211
212 end
213 end