annotate vendor/plugins/coderay-0.9.2/lib/coderay/.svn/text-base/encoder.rb.svn-base @ 874:12771bc38f20 feature_123

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