comparison vendor/gems/coderay-1.0.0/lib/coderay/encoder.rb @ 909:cbb26bc654de redmine-1.3

Update to Redmine 1.3-stable branch (Redmine SVN rev 8964)
author Chris Cannam
date Fri, 24 Feb 2012 19:09:32 +0000
parents
children
comparison
equal deleted inserted replaced
908:c6c2cbd0afee 909:cbb26bc654de
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
12 extend PluginHost
13 plugin_path File.dirname(__FILE__), 'encoders'
14
15 # = Encoder
16 #
17 # The Encoder base class. Together with Scanner and
18 # Tokens, it forms the highlighting triad.
19 #
20 # Encoder instances take a Tokens object and do something with it.
21 #
22 # The most common Encoder is surely the HTML encoder
23 # (CodeRay::Encoders::HTML). It highlights the code in a colorful
24 # html page.
25 # If you want the highlighted code in a div or a span instead,
26 # use its subclasses Div and Span.
27 class Encoder
28 extend Plugin
29 plugin_host Encoders
30
31 class << self
32
33 # If FILE_EXTENSION isn't defined, this method returns the
34 # downcase class name instead.
35 def const_missing sym
36 if sym == :FILE_EXTENSION
37 (defined?(@plugin_id) && @plugin_id || name[/\w+$/].downcase).to_s
38 else
39 super
40 end
41 end
42
43 # The default file extension for output file of this encoder class.
44 def file_extension
45 self::FILE_EXTENSION
46 end
47
48 end
49
50 # Subclasses are to store their default options in this constant.
51 DEFAULT_OPTIONS = { }
52
53 # The options you gave the Encoder at creating.
54 attr_accessor :options, :scanner
55
56 # Creates a new Encoder.
57 # +options+ is saved and used for all encode operations, as long
58 # as you don't overwrite it there by passing additional options.
59 #
60 # Encoder objects provide three encode methods:
61 # - encode simply takes a +code+ string and a +lang+
62 # - encode_tokens expects a +tokens+ object instead
63 #
64 # Each method has an optional +options+ parameter. These are
65 # added to the options you passed at creation.
66 def initialize options = {}
67 @options = self.class::DEFAULT_OPTIONS.merge options
68 @@CODERAY_TOKEN_INTERFACE_DEPRECATION_WARNING_GIVEN = false
69 end
70
71 # Encode a Tokens object.
72 def encode_tokens tokens, options = {}
73 options = @options.merge options
74 @scanner = tokens.scanner if tokens.respond_to? :scanner
75 setup options
76 compile tokens, options
77 finish options
78 end
79
80 # Encode the given +code+ using the Scanner for +lang+.
81 def encode code, lang, options = {}
82 options = @options.merge options
83 @scanner = Scanners[lang].new code, CodeRay.get_scanner_options(options).update(:tokens => self)
84 setup options
85 @scanner.tokenize
86 finish options
87 end
88
89 # You can use highlight instead of encode, if that seems
90 # more clear to you.
91 alias highlight encode
92
93 # The default file extension for this encoder.
94 def file_extension
95 self.class.file_extension
96 end
97
98 def << token
99 unless @@CODERAY_TOKEN_INTERFACE_DEPRECATION_WARNING_GIVEN
100 warn 'Using old Tokens#<< interface.'
101 @@CODERAY_TOKEN_INTERFACE_DEPRECATION_WARNING_GIVEN = true
102 end
103 self.token(*token)
104 end
105
106 # Called with +content+ and +kind+ of the currently scanned token.
107 # For simple scanners, it's enougth to implement this method.
108 #
109 # By default, it calls text_token, begin_group, end_group, begin_line,
110 # or end_line, depending on the +content+.
111 def token content, kind
112 case content
113 when String
114 text_token content, kind
115 when :begin_group
116 begin_group kind
117 when :end_group
118 end_group kind
119 when :begin_line
120 begin_line kind
121 when :end_line
122 end_line kind
123 else
124 raise ArgumentError, 'Unknown token content type: %p, kind = %p' % [content, kind]
125 end
126 end
127
128 # Called for each text token ([text, kind]), where text is a String.
129 def text_token text, kind
130 @out << text
131 end
132
133 # Starts a token group with the given +kind+.
134 def begin_group kind
135 end
136
137 # Ends a token group with the given +kind+.
138 def end_group kind
139 end
140
141 # Starts a new line token group with the given +kind+.
142 def begin_line kind
143 end
144
145 # Ends a new line token group with the given +kind+.
146 def end_line kind
147 end
148
149 protected
150
151 # Called with merged options before encoding starts.
152 # Sets @out to an empty string.
153 #
154 # See the HTML Encoder for an example of option caching.
155 def setup options
156 @out = get_output(options)
157 end
158
159 def get_output options
160 options[:out] || ''
161 end
162
163 # Append data.to_s to the output. Returns the argument.
164 def output data
165 @out << data.to_s
166 data
167 end
168
169 # Called with merged options after encoding starts.
170 # The return value is the result of encoding, typically @out.
171 def finish options
172 @out
173 end
174
175 # Do the encoding.
176 #
177 # The already created +tokens+ object must be used; it must be a
178 # Tokens object.
179 def compile tokens, options = {}
180 content = nil
181 for item in tokens
182 if item.is_a? Array
183 raise ArgumentError, 'Two-element array tokens are no longer supported.'
184 end
185 if content
186 token content, item
187 content = nil
188 else
189 content = item
190 end
191 end
192 raise 'odd number list for Tokens' if content
193 end
194
195 alias tokens compile
196 public :tokens
197
198 end
199
200 end
201 end