Redmine/vendor/gems/coderay-1.0.0/lib/coderay/encoder.rb

202 lines
5.9 KiB
Ruby
Raw Normal View History

module CodeRay
# This module holds the Encoder class and its subclasses.
# For example, the HTML encoder is named CodeRay::Encoders::HTML
# can be found in coderay/encoders/html.
#
# Encoders also provides methods and constants for the register
# mechanism and the [] method that returns the Encoder class
# belonging to the given format.
module Encoders
extend PluginHost
plugin_path File.dirname(__FILE__), 'encoders'
# = Encoder
#
# The Encoder base class. Together with Scanner and
# Tokens, it forms the highlighting triad.
#
# Encoder instances take a Tokens object and do something with it.
#
# The most common Encoder is surely the HTML encoder
# (CodeRay::Encoders::HTML). It highlights the code in a colorful
# html page.
# If you want the highlighted code in a div or a span instead,
# use its subclasses Div and Span.
class Encoder
extend Plugin
plugin_host Encoders
class << self
# If FILE_EXTENSION isn't defined, this method returns the
# downcase class name instead.
def const_missing sym
if sym == :FILE_EXTENSION
(defined?(@plugin_id) && @plugin_id || name[/\w+$/].downcase).to_s
else
super
end
end
# The default file extension for output file of this encoder class.
def file_extension
self::FILE_EXTENSION
end
end
# Subclasses are to store their default options in this constant.
DEFAULT_OPTIONS = { }
# The options you gave the Encoder at creating.
attr_accessor :options, :scanner
# Creates a new Encoder.
# +options+ is saved and used for all encode operations, as long
# as you don't overwrite it there by passing additional options.
#
# Encoder objects provide three encode methods:
# - encode simply takes a +code+ string and a +lang+
# - encode_tokens expects a +tokens+ object instead
#
# Each method has an optional +options+ parameter. These are
# added to the options you passed at creation.
def initialize options = {}
@options = self.class::DEFAULT_OPTIONS.merge options
@@CODERAY_TOKEN_INTERFACE_DEPRECATION_WARNING_GIVEN = false
end
# Encode a Tokens object.
def encode_tokens tokens, options = {}
options = @options.merge options
@scanner = tokens.scanner if tokens.respond_to? :scanner
setup options
compile tokens, options
finish options
end
# Encode the given +code+ using the Scanner for +lang+.
def encode code, lang, options = {}
options = @options.merge options
@scanner = Scanners[lang].new code, CodeRay.get_scanner_options(options).update(:tokens => self)
setup options
@scanner.tokenize
finish options
end
# You can use highlight instead of encode, if that seems
# more clear to you.
alias highlight encode
# The default file extension for this encoder.
def file_extension
self.class.file_extension
end
def << token
unless @@CODERAY_TOKEN_INTERFACE_DEPRECATION_WARNING_GIVEN
warn 'Using old Tokens#<< interface.'
@@CODERAY_TOKEN_INTERFACE_DEPRECATION_WARNING_GIVEN = true
end
self.token(*token)
end
# Called with +content+ and +kind+ of the currently scanned token.
# For simple scanners, it's enougth to implement this method.
#
# By default, it calls text_token, begin_group, end_group, begin_line,
# or end_line, depending on the +content+.
def token content, kind
case content
when String
text_token content, kind
when :begin_group
begin_group kind
when :end_group
end_group kind
when :begin_line
begin_line kind
when :end_line
end_line kind
else
raise ArgumentError, 'Unknown token content type: %p, kind = %p' % [content, kind]
end
end
# Called for each text token ([text, kind]), where text is a String.
def text_token text, kind
@out << text
end
# Starts a token group with the given +kind+.
def begin_group kind
end
# Ends a token group with the given +kind+.
def end_group kind
end
# Starts a new line token group with the given +kind+.
def begin_line kind
end
# Ends a new line token group with the given +kind+.
def end_line kind
end
protected
# Called with merged options before encoding starts.
# Sets @out to an empty string.
#
# See the HTML Encoder for an example of option caching.
def setup options
@out = get_output(options)
end
def get_output options
options[:out] || ''
end
# Append data.to_s to the output. Returns the argument.
def output data
@out << data.to_s
data
end
# Called with merged options after encoding starts.
# The return value is the result of encoding, typically @out.
def finish options
@out
end
# Do the encoding.
#
# The already created +tokens+ object must be used; it must be a
# Tokens object.
def compile tokens, options = {}
content = nil
for item in tokens
if item.is_a? Array
raise ArgumentError, 'Two-element array tokens are no longer supported.'
end
if content
token content, item
content = nil
else
content = item
end
end
raise 'odd number list for Tokens' if content
end
alias tokens compile
public :tokens
end
end
end