annotate vendor/gems/coderay-1.0.0/lib/coderay/encoder.rb @ 1171:b4558bc5837f bug_505

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