123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- # = CodeRay Library
- #
- # $Id: coderay.rb 227 2007-04-24 12:26:18Z murphy $
- #
- # CodeRay is a Ruby library for syntax highlighting.
- #
- # I try to make CodeRay easy to use and intuitive, but at the same time fully featured, complete,
- # fast and efficient.
- #
- # See README.
- #
- # It consists mainly of
- # * the main engine: CodeRay (Scanners::Scanner, Tokens/TokenStream, Encoders::Encoder), PluginHost
- # * the scanners in CodeRay::Scanners
- # * the encoders in CodeRay::Encoders
- #
- # Here's a fancy graphic to light up this gray docu:
- #
- # http://rd.cYcnus.de/coderay/scheme.png
- #
- # == Documentation
- #
- # See CodeRay, Encoders, Scanners, Tokens.
- #
- # == Usage
- #
- # Remember you need RubyGems to use CodeRay, unless you have it in your load path. Run Ruby with
- # -rubygems option if required.
- #
- # === Highlight Ruby code in a string as html
- #
- # require 'coderay'
- # print CodeRay.scan('puts "Hello, world!"', :ruby).html
- #
- # # prints something like this:
- # puts <span class="s">"Hello, world!"</span>
- #
- #
- # === Highlight C code from a file in a html div
- #
- # require 'coderay'
- # print CodeRay.scan(File.read('ruby.h'), :c).div
- # print CodeRay.scan_file('ruby.h').html.div
- #
- # You can include this div in your page. The used CSS styles can be printed with
- #
- # % coderay_stylesheet
- #
- # === Highlight without typing too much
- #
- # If you are one of the hasty (or lazy, or extremely curious) people, just run this file:
- #
- # % ruby -rubygems /path/to/coderay/coderay.rb > example.html
- #
- # and look at the file it created in your browser.
- #
- # = CodeRay Module
- #
- # The CodeRay module provides convenience methods for the engine.
- #
- # * The +lang+ and +format+ arguments select Scanner and Encoder to use. These are
- # simply lower-case symbols, like <tt>:python</tt> or <tt>:html</tt>.
- # * All methods take an optional hash as last parameter, +options+, that is send to
- # the Encoder / Scanner.
- # * Input and language are always sorted in this order: +code+, +lang+.
- # (This is in alphabetical order, if you need a mnemonic ;)
- #
- # You should be able to highlight everything you want just using these methods;
- # so there is no need to dive into CodeRay's deep class hierarchy.
- #
- # The examples in the demo directory demonstrate common cases using this interface.
- #
- # = Basic Access Ways
- #
- # Read this to get a general view what CodeRay provides.
- #
- # == Scanning
- #
- # Scanning means analysing an input string, splitting it up into Tokens.
- # Each Token knows about what type it is: string, comment, class name, etc.
- #
- # Each +lang+ (language) has its own Scanner; for example, <tt>:ruby</tt> code is
- # handled by CodeRay::Scanners::Ruby.
- #
- # CodeRay.scan:: Scan a string in a given language into Tokens.
- # This is the most common method to use.
- # CodeRay.scan_file:: Scan a file and guess the language using FileType.
- #
- # The Tokens object you get from these methods can encode itself; see Tokens.
- #
- # == Encoding
- #
- # Encoding means compiling Tokens into an output. This can be colored HTML or
- # LaTeX, a textual statistic or just the number of non-whitespace tokens.
- #
- # Each Encoder provides output in a specific +format+, so you select Encoders via
- # formats like <tt>:html</tt> or <tt>:statistic</tt>.
- #
- # CodeRay.encode:: Scan and encode a string in a given language.
- # CodeRay.encode_tokens:: Encode the given tokens.
- # CodeRay.encode_file:: Scan a file, guess the language using FileType and encode it.
- #
- # == Streaming
- #
- # Streaming saves RAM by running Scanner and Encoder in some sort of
- # pipe mode; see TokenStream.
- #
- # CodeRay.scan_stream:: Scan in stream mode.
- #
- # == All-in-One Encoding
- #
- # CodeRay.encode:: Highlight a string with a given input and output format.
- #
- # == Instanciating
- #
- # You can use an Encoder instance to highlight multiple inputs. This way, the setup
- # for this Encoder must only be done once.
- #
- # CodeRay.encoder:: Create an Encoder instance with format and options.
- # CodeRay.scanner:: Create an Scanner instance for lang, with '' as default code.
- #
- # To make use of CodeRay.scanner, use CodeRay::Scanner::code=.
- #
- # The scanning methods provide more flexibility; we recommend to use these.
- #
- # == Reusing Scanners and Encoders
- #
- # If you want to re-use scanners and encoders (because that is faster), see
- # CodeRay::Duo for the most convenient (and recommended) interface.
- module CodeRay
-
- # Version: Major.Minor.Teeny[.Revision]
- # Major: 0 for pre-release
- # Minor: odd for beta, even for stable
- # Teeny: development state
- # Revision: Subversion Revision number (generated on rake)
- VERSION = '0.7.6'
-
- require 'coderay/tokens'
- require 'coderay/scanner'
- require 'coderay/encoder'
- require 'coderay/duo'
- require 'coderay/style'
-
-
- class << self
-
- # Scans the given +code+ (a String) with the Scanner for +lang+.
- #
- # This is a simple way to use CodeRay. Example:
- # require 'coderay'
- # page = CodeRay.scan("puts 'Hello, world!'", :ruby).html
- #
- # See also demo/demo_simple.
- def scan code, lang, options = {}, &block
- scanner = Scanners[lang].new code, options, &block
- scanner.tokenize
- end
-
- # Scans +filename+ (a path to a code file) with the Scanner for +lang+.
- #
- # If +lang+ is :auto or omitted, the CodeRay::FileType module is used to
- # determine it. If it cannot find out what type it is, it uses
- # CodeRay::Scanners::Plaintext.
- #
- # Calls CodeRay.scan.
- #
- # Example:
- # require 'coderay'
- # page = CodeRay.scan_file('some_c_code.c').html
- def scan_file filename, lang = :auto, options = {}, &block
- file = IO.read filename
- if lang == :auto
- require 'coderay/helpers/file_type'
- lang = FileType.fetch filename, :plaintext, true
- end
- scan file, lang, options = {}, &block
- end
-
- # Scan the +code+ (a string) with the scanner for +lang+.
- #
- # Calls scan.
- #
- # See CodeRay.scan.
- def scan_stream code, lang, options = {}, &block
- options[:stream] = true
- scan code, lang, options, &block
- end
-
- # Encode a string in Streaming mode.
- #
- # This starts scanning +code+ with the the Scanner for +lang+
- # while encodes the output with the Encoder for +format+.
- # +options+ will be passed to the Encoder.
- #
- # See CodeRay::Encoder.encode_stream
- def encode_stream code, lang, format, options = {}
- encoder(format, options).encode_stream code, lang, options
- end
-
- # Encode a string.
- #
- # This scans +code+ with the the Scanner for +lang+ and then
- # encodes it with the Encoder for +format+.
- # +options+ will be passed to the Encoder.
- #
- # See CodeRay::Encoder.encode
- def encode code, lang, format, options = {}
- encoder(format, options).encode code, lang, options
- end
-
- # Highlight a string into a HTML <div>.
- #
- # CSS styles use classes, so you have to include a stylesheet
- # in your output.
- #
- # See encode.
- def highlight code, lang, options = { :css => :class }, format = :div
- encode code, lang, format, options
- end
-
- # Encode pre-scanned Tokens.
- # Use this together with CodeRay.scan:
- #
- # require 'coderay'
- #
- # # Highlight a short Ruby code example in a HTML span
- # tokens = CodeRay.scan '1 + 2', :ruby
- # puts CodeRay.encode_tokens(tokens, :span)
- #
- def encode_tokens tokens, format, options = {}
- encoder(format, options).encode_tokens tokens, options
- end
-
- # Encodes +filename+ (a path to a code file) with the Scanner for +lang+.
- #
- # See CodeRay.scan_file.
- # Notice that the second argument is the output +format+, not the input language.
- #
- # Example:
- # require 'coderay'
- # page = CodeRay.encode_file 'some_c_code.c', :html
- def encode_file filename, format, options = {}
- tokens = scan_file filename, :auto, get_scanner_options(options)
- encode_tokens tokens, format, options
- end
-
- # Highlight a file into a HTML <div>.
- #
- # CSS styles use classes, so you have to include a stylesheet
- # in your output.
- #
- # See encode.
- def highlight_file filename, options = { :css => :class }, format = :div
- encode_file filename, format, options
- end
-
- # Finds the Encoder class for +format+ and creates an instance, passing
- # +options+ to it.
- #
- # Example:
- # require 'coderay'
- #
- # stats = CodeRay.encoder(:statistic)
- # stats.encode("puts 17 + 4\n", :ruby)
- #
- # puts '%d out of %d tokens have the kind :integer.' % [
- # stats.type_stats[:integer].count,
- # stats.real_token_count
- # ]
- # #-> 2 out of 4 tokens have the kind :integer.
- def encoder format, options = {}
- Encoders[format].new options
- end
-
- # Finds the Scanner class for +lang+ and creates an instance, passing
- # +options+ to it.
- #
- # See Scanner.new.
- def scanner lang, options = {}
- Scanners[lang].new '', options
- end
-
- # Extract the options for the scanner from the +options+ hash.
- #
- # Returns an empty Hash if <tt>:scanner_options</tt> is not set.
- #
- # This is used if a method like CodeRay.encode has to provide options
- # for Encoder _and_ scanner.
- def get_scanner_options options
- options.fetch :scanner_options, {}
- end
-
- end
-
- # This Exception is raised when you try to stream with something that is not
- # capable of streaming.
- class NotStreamableError < Exception
- def initialize obj
- @obj = obj
- end
-
- def to_s
- '%s is not Streamable!' % @obj.class
- end
- end
-
- # A dummy module that is included by subclasses of CodeRay::Scanner an CodeRay::Encoder
- # to show that they are able to handle streams.
- module Streamable
- end
-
- end
-
- # Run a test script.
- if $0 == __FILE__
- $stderr.print 'Press key to print demo.'; gets
- code = File.read(__FILE__)[/module CodeRay.*/m]
- print CodeRay.scan(code, :ruby).html
- end
|