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

Update to Redmine trunk rev 4802
author Chris Cannam
date Tue, 08 Feb 2011 13:51:46 +0000
parents
children
comparison
equal deleted inserted replaced
128:07fa8a8b56a8 210:0579821a129a
1 # = CodeRay Library
2 #
3 # CodeRay is a Ruby library for syntax highlighting.
4 #
5 # I try to make CodeRay easy to use and intuitive, but at the same time fully featured, complete,
6 # fast and efficient.
7 #
8 # See README.
9 #
10 # It consists mainly of
11 # * the main engine: CodeRay (Scanners::Scanner, Tokens/TokenStream, Encoders::Encoder), PluginHost
12 # * the scanners in CodeRay::Scanners
13 # * the encoders in CodeRay::Encoders
14 #
15 # Here's a fancy graphic to light up this gray docu:
16 #
17 # http://cycnus.de/raindark/coderay/scheme.png
18 #
19 # == Documentation
20 #
21 # See CodeRay, Encoders, Scanners, Tokens.
22 #
23 # == Usage
24 #
25 # Remember you need RubyGems to use CodeRay, unless you have it in your load path. Run Ruby with
26 # -rubygems option if required.
27 #
28 # === Highlight Ruby code in a string as html
29 #
30 # require 'coderay'
31 # print CodeRay.scan('puts "Hello, world!"', :ruby).html
32 #
33 # # prints something like this:
34 # puts <span class="s">&quot;Hello, world!&quot;</span>
35 #
36 #
37 # === Highlight C code from a file in a html div
38 #
39 # require 'coderay'
40 # print CodeRay.scan(File.read('ruby.h'), :c).div
41 # print CodeRay.scan_file('ruby.h').html.div
42 #
43 # You can include this div in your page. The used CSS styles can be printed with
44 #
45 # % coderay_stylesheet
46 #
47 # === Highlight without typing too much
48 #
49 # If you are one of the hasty (or lazy, or extremely curious) people, just run this file:
50 #
51 # % ruby -rubygems /path/to/coderay/coderay.rb > example.html
52 #
53 # and look at the file it created in your browser.
54 #
55 # = CodeRay Module
56 #
57 # The CodeRay module provides convenience methods for the engine.
58 #
59 # * The +lang+ and +format+ arguments select Scanner and Encoder to use. These are
60 # simply lower-case symbols, like <tt>:python</tt> or <tt>:html</tt>.
61 # * All methods take an optional hash as last parameter, +options+, that is send to
62 # the Encoder / Scanner.
63 # * Input and language are always sorted in this order: +code+, +lang+.
64 # (This is in alphabetical order, if you need a mnemonic ;)
65 #
66 # You should be able to highlight everything you want just using these methods;
67 # so there is no need to dive into CodeRay's deep class hierarchy.
68 #
69 # The examples in the demo directory demonstrate common cases using this interface.
70 #
71 # = Basic Access Ways
72 #
73 # Read this to get a general view what CodeRay provides.
74 #
75 # == Scanning
76 #
77 # Scanning means analysing an input string, splitting it up into Tokens.
78 # Each Token knows about what type it is: string, comment, class name, etc.
79 #
80 # Each +lang+ (language) has its own Scanner; for example, <tt>:ruby</tt> code is
81 # handled by CodeRay::Scanners::Ruby.
82 #
83 # CodeRay.scan:: Scan a string in a given language into Tokens.
84 # This is the most common method to use.
85 # CodeRay.scan_file:: Scan a file and guess the language using FileType.
86 #
87 # The Tokens object you get from these methods can encode itself; see Tokens.
88 #
89 # == Encoding
90 #
91 # Encoding means compiling Tokens into an output. This can be colored HTML or
92 # LaTeX, a textual statistic or just the number of non-whitespace tokens.
93 #
94 # Each Encoder provides output in a specific +format+, so you select Encoders via
95 # formats like <tt>:html</tt> or <tt>:statistic</tt>.
96 #
97 # CodeRay.encode:: Scan and encode a string in a given language.
98 # CodeRay.encode_tokens:: Encode the given tokens.
99 # CodeRay.encode_file:: Scan a file, guess the language using FileType and encode it.
100 #
101 # == Streaming
102 #
103 # Streaming saves RAM by running Scanner and Encoder in some sort of
104 # pipe mode; see TokenStream.
105 #
106 # CodeRay.scan_stream:: Scan in stream mode.
107 #
108 # == All-in-One Encoding
109 #
110 # CodeRay.encode:: Highlight a string with a given input and output format.
111 #
112 # == Instanciating
113 #
114 # You can use an Encoder instance to highlight multiple inputs. This way, the setup
115 # for this Encoder must only be done once.
116 #
117 # CodeRay.encoder:: Create an Encoder instance with format and options.
118 # CodeRay.scanner:: Create an Scanner instance for lang, with '' as default code.
119 #
120 # To make use of CodeRay.scanner, use CodeRay::Scanner::code=.
121 #
122 # The scanning methods provide more flexibility; we recommend to use these.
123 #
124 # == Reusing Scanners and Encoders
125 #
126 # If you want to re-use scanners and encoders (because that is faster), see
127 # CodeRay::Duo for the most convenient (and recommended) interface.
128 module CodeRay
129
130 $CODERAY_DEBUG ||= false
131
132 # Version: Major.Minor.Teeny[.Revision]
133 # Major: 0 for pre-stable, 1 for stable
134 # Minor: feature milestone
135 # Teeny: development state, 0 for pre-release
136 # Revision: Subversion Revision number (generated on rake gem:make)
137 VERSION = '0.9.7'
138
139 require 'coderay/tokens'
140 require 'coderay/token_classes'
141 require 'coderay/scanner'
142 require 'coderay/encoder'
143 require 'coderay/duo'
144 require 'coderay/style'
145
146
147 class << self
148
149 # Scans the given +code+ (a String) with the Scanner for +lang+.
150 #
151 # This is a simple way to use CodeRay. Example:
152 # require 'coderay'
153 # page = CodeRay.scan("puts 'Hello, world!'", :ruby).html
154 #
155 # See also demo/demo_simple.
156 def scan code, lang, options = {}, &block
157 scanner = Scanners[lang].new code, options, &block
158 scanner.tokenize
159 end
160
161 # Scans +filename+ (a path to a code file) with the Scanner for +lang+.
162 #
163 # If +lang+ is :auto or omitted, the CodeRay::FileType module is used to
164 # determine it. If it cannot find out what type it is, it uses
165 # CodeRay::Scanners::Plaintext.
166 #
167 # Calls CodeRay.scan.
168 #
169 # Example:
170 # require 'coderay'
171 # page = CodeRay.scan_file('some_c_code.c').html
172 def scan_file filename, lang = :auto, options = {}, &block
173 file = IO.read filename
174 if lang == :auto
175 require 'coderay/helpers/file_type'
176 lang = FileType.fetch filename, :plaintext, true
177 end
178 scan file, lang, options = {}, &block
179 end
180
181 # Scan the +code+ (a string) with the scanner for +lang+.
182 #
183 # Calls scan.
184 #
185 # See CodeRay.scan.
186 def scan_stream code, lang, options = {}, &block
187 options[:stream] = true
188 scan code, lang, options, &block
189 end
190
191 # Encode a string in Streaming mode.
192 #
193 # This starts scanning +code+ with the the Scanner for +lang+
194 # while encodes the output with the Encoder for +format+.
195 # +options+ will be passed to the Encoder.
196 #
197 # See CodeRay::Encoder.encode_stream
198 def encode_stream code, lang, format, options = {}
199 encoder(format, options).encode_stream code, lang, options
200 end
201
202 # Encode a string.
203 #
204 # This scans +code+ with the the Scanner for +lang+ and then
205 # encodes it with the Encoder for +format+.
206 # +options+ will be passed to the Encoder.
207 #
208 # See CodeRay::Encoder.encode
209 def encode code, lang, format, options = {}
210 encoder(format, options).encode code, lang, options
211 end
212
213 # Highlight a string into a HTML <div>.
214 #
215 # CSS styles use classes, so you have to include a stylesheet
216 # in your output.
217 #
218 # See encode.
219 def highlight code, lang, options = { :css => :class }, format = :div
220 encode code, lang, format, options
221 end
222
223 # Encode pre-scanned Tokens.
224 # Use this together with CodeRay.scan:
225 #
226 # require 'coderay'
227 #
228 # # Highlight a short Ruby code example in a HTML span
229 # tokens = CodeRay.scan '1 + 2', :ruby
230 # puts CodeRay.encode_tokens(tokens, :span)
231 #
232 def encode_tokens tokens, format, options = {}
233 encoder(format, options).encode_tokens tokens, options
234 end
235
236 # Encodes +filename+ (a path to a code file) with the Scanner for +lang+.
237 #
238 # See CodeRay.scan_file.
239 # Notice that the second argument is the output +format+, not the input language.
240 #
241 # Example:
242 # require 'coderay'
243 # page = CodeRay.encode_file 'some_c_code.c', :html
244 def encode_file filename, format, options = {}
245 tokens = scan_file filename, :auto, get_scanner_options(options)
246 encode_tokens tokens, format, options
247 end
248
249 # Highlight a file into a HTML <div>.
250 #
251 # CSS styles use classes, so you have to include a stylesheet
252 # in your output.
253 #
254 # See encode.
255 def highlight_file filename, options = { :css => :class }, format = :div
256 encode_file filename, format, options
257 end
258
259 # Finds the Encoder class for +format+ and creates an instance, passing
260 # +options+ to it.
261 #
262 # Example:
263 # require 'coderay'
264 #
265 # stats = CodeRay.encoder(:statistic)
266 # stats.encode("puts 17 + 4\n", :ruby)
267 #
268 # puts '%d out of %d tokens have the kind :integer.' % [
269 # stats.type_stats[:integer].count,
270 # stats.real_token_count
271 # ]
272 # #-> 2 out of 4 tokens have the kind :integer.
273 def encoder format, options = {}
274 Encoders[format].new options
275 end
276
277 # Finds the Scanner class for +lang+ and creates an instance, passing
278 # +options+ to it.
279 #
280 # See Scanner.new.
281 def scanner lang, options = {}
282 Scanners[lang].new '', options
283 end
284
285 # Extract the options for the scanner from the +options+ hash.
286 #
287 # Returns an empty Hash if <tt>:scanner_options</tt> is not set.
288 #
289 # This is used if a method like CodeRay.encode has to provide options
290 # for Encoder _and_ scanner.
291 def get_scanner_options options
292 options.fetch :scanner_options, {}
293 end
294
295 end
296
297 # This Exception is raised when you try to stream with something that is not
298 # capable of streaming.
299 class NotStreamableError < Exception
300 def initialize obj
301 @obj = obj
302 end
303
304 def to_s
305 '%s is not Streamable!' % @obj.class
306 end
307 end
308
309 # A dummy module that is included by subclasses of CodeRay::Scanner an CodeRay::Encoder
310 # to show that they are able to handle streams.
311 module Streamable
312 end
313
314 end
315
316 # Run a test script.
317 if $0 == __FILE__
318 $stderr.print 'Press key to print demo.'; gets
319 # Just use this file as an example of Ruby code.
320 code = File.read(__FILE__)[/module CodeRay.*/m]
321 print CodeRay.scan(code, :ruby).html
322 end