class CodeRay::Tokens
to load them from a file, and still use any Encoder that CodeRay provides.
It also allows you to generate tokens directly (without using a scanner),
that you put in your DB.
You can convert it to a webpage, a YAML file, or dump it into a gzip’ed string
Tokens gives you the power to handle pre-scanned code very easily:
See how small it is? ;)
# the Tokens object is here ——-^
CodeRay.scan(‘price = 2.59’, :ruby).html
Thus, the syntax below becomes clear:
then builds the output from this object.
The input is split and saved into a Tokens object. The Encoder
Tokens is the interface between Scanners and Encoders:
]
[:end_group, :string]
[‘“’, :delimiter],
[‘a string’, :content],
[‘”’, :delimiter],
[:begin_group, :string],
[
The Ruby scanner, for example, splits “a string” into:
token actions, namely begin_group and end_group.
Some scanners also yield sub-tokens, represented by special
[‘$^’, :error]
[‘3.1415926’, :float]
[‘# It looks like this’, :comment]
A token looks like this:
* the token kind (a Symbol representing the type of the token)
a token action (begin_group, end_group, begin_line, end_line)
* the token text (the original source of the token in a String) or
consisting of
A token is not a special object, just a two-element Array
a Scanner.
The Tokens class represents a list of tokens returnd from
= Tokens TODO: Rewrite!
def begin_group kind; push :begin_group, kind end
def begin_group kind; push :begin_group, kind end
def begin_line kind; push :begin_line, kind end
def begin_line kind; push :begin_line, kind end
def count
def count size / 2 end
def dump gzip_level = 7
speed and compression rate.
in most cases as it is a good compromise between
but the default value 7 should be what you want
You can configure the level of compression,
so it has an #undump method. See Tokens.load.
The returned String object includes Undumping
In addition, it is gzipped using GZip.gzip.
The dump is created with Marshal.dump;
in files or databases.
Dumps the object into a String that can be saved
def dump gzip_level = 7 dump = Marshal.dump self dump = GZip.gzip dump, gzip_level dump.extend Undumping end
def encode encoder, options = {}
* an Encoder object
* an Encoder class
* a symbol like :html oder :statistic
encoder can be
Encode the tokens using encoder.
def encode encoder, options = {} encoder = Encoders[encoder].new options if encoder.respond_to? :to_sym encoder.encode_tokens self, options end
def end_group kind; push :end_group, kind end
def end_group kind; push :end_group, kind end
def end_line kind; push :end_line, kind end
def end_line kind; push :end_line, kind end
def method_missing meth, options = {}
For example, if you call +tokens.html+, the HTML encoder
Redirects unknown methods to encoder calls.
def method_missing meth, options = {} encode meth, options rescue PluginHost::PluginNotFound super end
def split_into_parts *sizes
This method is used by @Scanner#tokenize@ when called with an Array
betweem them.
part closes all opened tokens. This is useful to insert tokens
the text size specified by the parameter. In addition, each
The result will be an Array of Tokens objects. The parts have
Split the tokens into parts of the given +sizes+.
def split_into_parts *sizes parts = [] opened = [] content = nil part = Tokens.new part_size = 0 size = sizes.first i = 0 for item in self case content when nil content = item when String if size && part_size + content.size > size # token must be cut if part_size < size # some part of the token goes into this part content = content.dup # content may no be safe to change part << content.slice!(0, size - part_size) << item end # close all open groups and lines... closing = opened.reverse.flatten.map do |content_or_kind| case content_or_kind when :begin_group :end_group when :begin_line :end_line else content_or_kind end end part.concat closing begin parts << part part = Tokens.new size = sizes[i += 1] end until size.nil? || size > 0 # ...and open them again. part.concat opened.flatten part_size = 0 redo unless content.empty? else part << content << item part_size += content.size end content = nil when Symbol case content when :begin_group, :begin_line opened << [content, item] when :end_group, :end_line opened.pop else raise ArgumentError, 'Unknown token action: %p, kind = %p' % [content, item] end part << content << item content = nil else raise ArgumentError, 'Token input junk: %p, kind = %p' % [content, item] end end parts << part parts << Tokens.new while parts.size < sizes.size parts end
def to_s
def to_s encode CodeRay::Encoders::Encoder.new end