diff .svn/pristine/d8/d8ff1c547a8ab5f2037b019f178ac4f2175d8b5d.svn-base @ 927:9ee5fd0b9bd3

Merge from cannam_integration
author luisf <luis.figueira@eecs.qmul.ac.uk>
date Fri, 11 May 2012 16:13:59 +0100
parents cbb26bc654de
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/d8/d8ff1c547a8ab5f2037b019f178ac4f2175d8b5d.svn-base	Fri May 11 16:13:59 2012 +0100
@@ -0,0 +1,201 @@
+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