example..
Test outputs go to bench/test..
Run bench/bench.rb to get a usage description.
Run rake bench to perform an example benchmark.
== bin - Scripts
Executional files for CodeRay.
coderay:: The CodeRay executable.
== demo - Demos and functional tests
Demonstrational scripts to show of CodeRay's features.
Run them as functional tests with rake test:demos.
== etc - Lots of stuff
Some additional files for CodeRay, mainly graphics and Vim scripts.
== lib - CodeRay library code
This is the base directory for the CodeRay library.
== rake_helpers - Rake helper libraries
Some files to enhance Rake, including the Autumnal Rdoc template and some scripts.
== test - Tests
In the subfolder scanners/ are the scanners tests.
Each language has its own subfolder and sub-suite.
Run with rake test.
coderay-1.1.3/Gemfile 0000664 0000000 0000000 00000001734 13664404461 0014452 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
# Specify your gem's dependencies in coderay.gemspec
gemspec
# Add dependencies to develop your gem here.
# Include everything needed to run rake, tests, features, etc.
group :development do
gem 'bundler'
gem 'json', '~> 1.8' if RUBY_VERSION < '2.0'
gem 'rake', RUBY_VERSION < '1.9' ? '~> 10.5' : '>= 10.5'
gem 'rdoc', Gem::Version.new(RUBY_VERSION) < Gem::Version.new('1.9.3') ? '~> 4.2.2' : Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.2') ? '< 6' : '>= 6'
gem 'RedCloth', RUBY_PLATFORM == 'java' ? '= 4.2.9' : '>= 4.0.3'
gem 'rspec', '~> 3.9.0'
gem 'shoulda-context', RUBY_VERSION < '1.9' ? '= 1.2.1' : '>= 1.2.1'
gem 'simplecov', '~> 0.17.1'
gem 'term-ansicolor', RUBY_VERSION < '2.0' ? '~> 1.3.2' : '>= 1.3.2'
gem 'test-unit', RUBY_VERSION < '1.9' ? '~> 2.0' : '>= 3.0'
gem 'tins', RUBY_VERSION < '2.0' ? '~> 1.6.0' : '>= 1.6.0'
end
coderay-1.1.3/MIT-LICENSE 0000664 0000000 0000000 00000002155 13664404461 0014611 0 ustar 00root root 0000000 0000000 Copyright (C) 2005-2012 Kornelius Kalnbach The server encountered an exception and was unable to complete your request.
" self.puts "The exception has provided the following information:
" self.puts "#{exception.class}: #{exception.message} on"
self.puts
self.puts "#{exception.backtrace.join("\n")}"
self.puts ""
self.puts ""
else
self.puts "The server encountered an exception and was unable to complete your request"
self.puts "The exception has provided the following information:"
self.puts "#{exception.class}: #{exception.message}"
self.puts
self.puts exception.backtrace.join("\n")
end
end
end
if @settings["cache"]
buffer = @buffer.join
unless @output_started
unless @header.has_key?("content-length")
self.header("content-length: #{buffer.length}")
end
sendHeaders
end
$stdout.print(buffer)
elsif !@output_started
sendHeaders
end
@output_allowed = false;
# }}}
end
# Decodes URL encoded data, %20 for example stands for a space.
def Rweb.unescape(str)
# {{{
if defined? str and str.is_a? String
str.gsub!(/\+/, " ")
str.gsub(/%.{2}/) do | s |
s[1,2].hex.chr
end
end
# }}}
end
protected
def sendHeaders
# {{{
Cookie.disallow # no more cookies can be set or modified
if !(@settings.has_key?("silent") and @settings["silent"] == true) and !@header.has_key?("x-powered-by")
if @mod_ruby
header("x-powered-by: #{RWEB} (Ruby/#{RUBY_VERSION}, #{MOD_RUBY})");
else
header("x-powered-by: #{RWEB} (Ruby/#{RUBY_VERSION})");
end
end
if @output_method == "ph"
if ((@status == nil or @status == 200) and !@header.has_key?("content-type") and !@header.has_key?("location"))
header("content-type: text/html")
end
if @status != nil
$stdout.print "Status: #{@status} #{@reasonPhrase}\r\n"
end
@header.each do |key, value|
key = key *1 # "unfreeze" key :)
key[0] = key[0,1].upcase![0]
key = key.gsub(/-[a-z]/) do |char|
"-" + char[1,1].upcase
end
$stdout.print "#{key}: #{value}\r\n"
end
cookies = Cookie.getHttpHeader # Get all cookies as an HTTP Header
if cookies
$stdout.print cookies
end
$stdout.print "\r\n"
elsif @output_method == "nph"
elsif @output_method == "mod_ruby"
r = Apache.request
if ((@status == nil or @status == 200) and !@header.has_key?("content-type") and !@header.has_key?("location"))
header("text/html")
end
if @status != nil
r.status_line = "#{@status} #{@reasonPhrase}"
end
r.send_http_header
@header.each do |key, value|
key = key *1 # "unfreeze" key :)
key[0] = key[0,1].upcase![0]
key = key.gsub(/-[a-z]/) do |char|
"-" + char[1,1].upcase
end
puts "#{key}: #{value.class}"
#r.headers_out[key] = value
end
end
@output_started = true
# }}}
end
def getReasonPhrase (status)
# {{{
if status == 100
"Continue"
elsif status == 101
"Switching Protocols"
elsif status == 200
"OK"
elsif status == 201
"Created"
elsif status == 202
"Accepted"
elsif status == 203
"Non-Authoritative Information"
elsif status == 204
"No Content"
elsif status == 205
"Reset Content"
elsif status == 206
"Partial Content"
elsif status == 300
"Multiple Choices"
elsif status == 301
"Moved Permanently"
elsif status == 302
"Found"
elsif status == 303
"See Other"
elsif status == 304
"Not Modified"
elsif status == 305
"Use Proxy"
elsif status == 307
"Temporary Redirect"
elsif status == 400
"Bad Request"
elsif status == 401
"Unauthorized"
elsif status == 402
"Payment Required"
elsif status == 403
"Forbidden"
elsif status == 404
"Not Found"
elsif status == 405
"Method Not Allowed"
elsif status == 406
"Not Acceptable"
elsif status == 407
"Proxy Authentication Required"
elsif status == 408
"Request Time-out"
elsif status == 409
"Conflict"
elsif status == 410
"Gone"
elsif status == 411
"Length Required"
elsif status == 412
"Precondition Failed"
elsif status == 413
"Request Entity Too Large"
elsif status == 414
"Request-URI Too Large"
elsif status == 415
"Unsupported Media Type"
elsif status == 416
"Requested range not satisfiable"
elsif status == 417
"Expectation Failed"
elsif status == 500
"Internal Server Error"
elsif status == 501
"Not Implemented"
elsif status == 502
"Bad Gateway"
elsif status == 503
"Service Unavailable"
elsif status == 504
"Gateway Time-out"
elsif status == 505
"HTTP Version not supported"
else
raise "Unknown Statuscode. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1 for more information."
end
# }}}
end
end
class Cookie
attr_reader :name, :value, :maxage, :path, :domain, :secure, :comment
# Sets a cookie. Please see below for details of the attributes.
def initialize (name, value = nil, maxage = nil, path = nil, domain = nil, secure = false)
# {{{
# HTTP headers (Cookies are a HTTP header) can only set, while no content
# is send. So an exception will be raised, when @@allowed is set to false
# and a new cookie has set.
unless defined?(@@allowed)
@@allowed = true
end
unless @@allowed
raise "You can't set cookies after the HTTP headers are send."
end
unless defined?(@@list)
@@list = []
end
@@list += [self]
unless defined?(@@type)
@@type = "netscape"
end
unless name.class == String
raise TypeError, "The name of a cookie must be a string", caller
end
if value.class.superclass == Integer || value.class == Float
value = value.to_s
elsif value.class != String && value != nil
raise TypeError, "The value of a cookie must be a string, integer, float or nil", caller
end
if maxage.class == Time
maxage = maxage - Time.now
elsif !maxage.class.superclass == Integer || !maxage == nil
raise TypeError, "The maxage date of a cookie must be an Integer or Time object or nil.", caller
end
unless path.class == String || path == nil
raise TypeError, "The path of a cookie must be nil or a string", caller
end
unless domain.class == String || domain == nil
raise TypeError, "The value of a cookie must be nil or a string", caller
end
unless secure == true || secure == false
raise TypeError, "The secure field of a cookie must be true or false", caller
end
@name, @value, @maxage, @path, @domain, @secure = name, value, maxage, path, domain, secure
@comment = nil
# }}}
end
# Modifies the value of this cookie. The information you want to store. If the
# value is nil, the cookie will be deleted by the client.
#
# This attribute can be a String, Integer or Float object or nil.
def value=(value)
# {{{
if value.class.superclass == Integer || value.class == Float
value = value.to_s
elsif value.class != String && value != nil
raise TypeError, "The value of a cookie must be a string, integer, float or nil", caller
end
@value = value
# }}}
end
# Modifies the maxage of this cookie. This attribute defines the lifetime of
# the cookie, in seconds. A value of 0 means the cookie should be discarded
# imediatly. If it set to nil, the cookie will be deleted when the browser
# will be closed.
#
# Attention: This is different from other implementations like PHP, where you
# gives the seconds since 1/1/1970 0:00:00 GMT.
#
# This attribute must be an Integer or Time object or nil.
def maxage=(maxage)
# {{{
if maxage.class == Time
maxage = maxage - Time.now
elsif maxage.class.superclass == Integer || !maxage == nil
raise TypeError, "The maxage of a cookie must be an Interger or Time object or nil.", caller
end
@maxage = maxage
# }}}
end
# Modifies the path value of this cookie. The client will send this cookie
# only, if the requested document is this directory or a subdirectory of it.
#
# The value of the attribute must be a String object or nil.
def path=(path)
# {{{
unless path.class == String || path == nil
raise TypeError, "The path of a cookie must be nil or a string", caller
end
@path = path
# }}}
end
# Modifies the domain value of this cookie. The client will send this cookie
# only if it's connected with this domain (or a subdomain, if the first
# character is a dot like in ".ruby-lang.org")
#
# The value of this attribute must be a String or nil.
def domain=(domain)
# {{{
unless domain.class == String || domain == nil
raise TypeError, "The domain of a cookie must be a String or nil.", caller
end
@domain = domain
# }}}
end
# Modifies the secure flag of this cookie. If it's true, the client will only
# send this cookie if it is secured connected with us.
#
# The value od this attribute has to be true or false.
def secure=(secure)
# {{{
unless secure == true || secure == false
raise TypeError, "The secure field of a cookie must be true or false", caller
end
@secure = secure
# }}}
end
# Modifies the comment value of this cookie. The comment won't be send, if
# type is "netscape".
def comment=(comment)
# {{{
unless comment.class == String || comment == nil
raise TypeError, "The comment of a cookie must be a string or nil", caller
end
@comment = comment
# }}}
end
# Changes the type of all cookies.
# Allowed values are RFC2109 and netscape (default).
def Cookie.type=(type)
# {{{
unless @@allowed
raise "The cookies are allready send, so you can't change the type anymore."
end
unless type.downcase == "rfc2109" && type.downcase == "netscape"
raise "The type of the cookies must be \"RFC2109\" or \"netscape\"."
end
@@type = type;
# }}}
end
# After sending this message, no cookies can be set or modified. Use it, when
# HTTP-Headers are send. Rweb does this for you.
def Cookie.disallow
# {{{
@@allowed = false
true
# }}}
end
# Returns a HTTP header (type String) with all cookies. Rweb does this for
# you.
def Cookie.getHttpHeader
# {{{
if defined?(@@list)
if @@type == "netscape"
str = ""
@@list.each do |cookie|
if cookie.value == nil
cookie.maxage = 0
cookie.value = ""
end
# TODO: Name and value should be escaped!
str += "Set-Cookie: #{cookie.name}=#{cookie.value}"
unless cookie.maxage == nil
expire = Time.now + cookie.maxage
expire.gmtime
str += "; Expire=#{expire.strftime("%a, %d-%b-%Y %H:%M:%S %Z")}"
end
unless cookie.domain == nil
str += "; Domain=#{cookie.domain}"
end
unless cookie.path == nil
str += "; Path=#{cookie.path}"
end
if cookie.secure
str += "; Secure"
end
str += "\r\n"
end
return str
else # type == "RFC2109"
str = "Set-Cookie: "
comma = false;
@@list.each do |cookie|
if cookie.value == nil
cookie.maxage = 0
cookie.value = ""
end
if comma
str += ","
end
comma = true
str += "#{cookie.name}=\"#{cookie.value}\""
unless cookie.maxage == nil
str += "; Max-Age=\"#{cookie.maxage}\""
end
unless cookie.domain == nil
str += "; Domain=\"#{cookie.domain}\""
end
unless cookie.path == nil
str += "; Path=\"#{cookie.path}\""
end
if cookie.secure
str += "; Secure"
end
unless cookie.comment == nil
str += "; Comment=\"#{cookie.comment}\""
end
str += "; Version=\"1\""
end
str
end
else
false
end
# }}}
end
end
require 'strscan'
module BBCode
DEBUG = true
use 'encoder', 'tags', 'tagstack', 'smileys'
=begin
The Parser class takes care of the encoding.
It scans the given BBCode (as plain text), finds tags
and smilies and also makes links of urls in text.
Normal text is send directly to the encoder.
If a tag was found, an instance of a Tag subclass is created
to handle the case.
The @tagstack manages tag nesting and ensures valid HTML.
=end
class Parser
class Attribute
# flatten and use only one empty_arg
def self.create attr
attr = flatten attr
return @@empty_attr if attr.empty?
new attr
end
private_class_method :new
# remove leading and trailing whitespace; concat lines
def self.flatten attr
attr.strip.gsub(/\n/, ' ')
# -> ^ and $ can only match at begin and end now
end
ATTRIBUTE_SCAN = /
(?!$) # don't match at end
\s*
( # $1 = key
[^=\s\]"\\]*
(?:
(?: \\. | "[^"\\]*(?:\\.[^"\\]*)*"? )
[^=\s\]"\\]*
)*
)
(?:
=
( # $2 = value
[^\s\]"\\]*
(?:
(?: \\. | "[^"\\]*(?:\\.[^"\\]*)*"? )
[^\s\]"\\]*
)*
)?
)?
\s*
/x
def self.parse source
source = source.dup
# empty_tag: the tag looks like [... /]
# slice!: this deletes the \s*/] at the end
# \s+ because [url=http://rubybb.org/forum/] is NOT an empty tag.
# In RubyBBCode, you can use [url=http://rubybb.org/forum/ /], and this has to be
# interpreted correctly.
empty_tag = source.sub!(/^:/, '=') or source.slice!(/\/$/)
debug 'PARSE: ' + source.inspect + ' => ' + empty_tag.inspect
#-> we have now an attr that's EITHER empty OR begins and ends with non-whitespace.
attr = Hash.new
attr[:flags] = []
source.scan(ATTRIBUTE_SCAN) { |key, value|
if not value
attr[:flags] << unescape(key)
else
next if value.empty? and key.empty?
attr[unescape(key)] = unescape(value)
end
}
debug attr.inspect
return empty_tag, attr
end
def self.unescape_char esc
esc[1]
end
def self.unquote qt
qt[1..-1].chomp('"').gsub(/\\./) { |esc| unescape_char esc }
end
def self.unescape str
str.gsub(/ (\\.) | (" [^"\\]* (?:\\.[^"\\]*)* "?) /x) {
if $1
unescape_char $1
else
unquote $2
end
}
end
include Enumerable
def each &block
@args.each(&block)
end
attr_reader :source, :args, :value
def initialize source
@source = source
debug 'Attribute#new(%p)' % source
@empty_tag, @attr = Attribute.parse source
@value = @attr[''].to_s
end
def empty?
self == @@empty_attr
end
def empty_tag?
@empty_tag
end
def [] *keys
res = @attr[*keys]
end
def flags
attr[:flags]
end
def to_s
@attr
end
def inspect
'ATTR[' + @attr.inspect + (@empty_tag ? ' | empty tag' : '') + ']'
end
end
class Attribute
@@empty_attr = new ''
end
end
class Parser
def Parser.flatten str
# replace mac & dos newlines with unix style
str.gsub(/\r\n?/, "\n")
end
def initialize input = ''
# input manager
@scanner = StringScanner.new ''
# output manager
@encoder = Encoder.new
@output = ''
# tag manager
@tagstack = TagStack.new(@encoder)
@do_magic = true
# set the input
feed input
end
# if you want, you can feed a parser instance after creating,
# or even feed it repeatedly.
def feed food
@scanner.string = Parser.flatten food
end
# parse through the string using parse_token
def parse
parse_token until @scanner.eos?
@tagstack.close_all
@output = parse_magic @encoder.output
end
def output
@output
end
# ok, internals start here
private
# the default output functions. everything should use them or the tags.
def add_text text = @scanner.matched
@encoder.add_text text
end
# use this carefully
def add_html html
@encoder.add_html html
end
# highlights the text as error
def add_garbage garbage
add_html '' if DEBUG
add_text garbage
add_html '' if DEBUG
end
# unknown and incorrectly nested tags are ignored and
# sent as plaintext (garbage in - garbage out).
# in debug mode, garbage is marked with lime background.
def garbage_out start
@scanner.pos = start
garbage = @scanner.scan(/./m)
debug 'GARBAGE: ' + garbage
add_garbage garbage
end
# simple text; everything but [, \[ allowed
SIMPLE_TEXT_SCAN_ = /
[^\[\\]* # normal*
(?: # (
\\.? # special
[^\[\\]* # normal*
)* # )*
/mx
SIMPLE_TEXT_SCAN = /[^\[]+/
=begin
WHAT IS A TAG?
==============
Tags in BBCode can be much more than just a simple [b].
I use many terms here to differ the parts of each tag.
Basic scheme:
[ code ]
TAG START TAG INFO TAG END
Most tags need a second tag to close the range it opened.
This is done with CLOSING TAGS:
[/code]
or by using empty tags that have no content and close themselfes:
[url=winamp.com /]
You surely know this from HTML.
These slashes define the TAG KIND = normal|closing|empty and
cannot be used together.
Everything between [ and ] and expluding the slashes is called the
TAG INFO. This info may contain:
- TAG ID
- TAG NAME including the tag id
- attributes
The TAG ID is the first char of the info:
TAG | ID
----------+----
[quote] | q
[±] | &
["[b]"] | "
[/url] | u
[---] | -
As you can see, the tag id shows the TAG TYPE, it can be a
normal tag, a formatting tag or an entity.
Therefor, the parser first scans the id to decide how to go
on with parsing.
=end
# tag
# TODO more complex expression allowing
# [quote="[ladico]"] and [quote=\[ladico\]] to be correct tags
TAG_BEGIN_SCAN = /
\[ # tag start
( \/ )? # $1 = closing tag?
( [^\]] ) # $2 = tag id
/x
TAG_END_SCAN = /
[^\]]* # rest that was not handled
\]? # tag end
/x
CLOSE_TAG_SCAN = /
( [^\]]* ) # $1 = the rest of the tag info
( \/ )? # $2 = empty tag?
\]? # tag end
/x
UNCLOSED_TAG_SCAN = / \[ /x
CLASSIC_TAG_SCAN = / [a-z]* /ix
SEPARATOR_TAG_SCAN = / \** /x
FORMAT_TAG_SCAN = / -- -* /x
QUOTED_SCAN = /
( # $1 = quoted text
[^"\\]* # normal*
(?: # (
\\. # special
[^"\\]* # normal*
)* # )*
)
"? # end quote "
/mx
ENTITY_SCAN = /
( [^;\]]+ ) # $1 = entity code
;? # optional ending semicolon
/ix
SMILEY_SCAN = Smileys::SMILEY_PATTERN
# this is the main parser loop that separates
# text - everything until "["
# from
# tags - starting with "[", ending with "]"
def parse_token
if @scanner.scan(SIMPLE_TEXT_SCAN)
add_text
else
handle_tag
end
end
def handle_tag
tag_start = @scanner.pos
unless @scanner.scan TAG_BEGIN_SCAN
garbage_out tag_start
return
end
closing, id = @scanner[1], @scanner[2]
#debug 'handle_tag(%p)' % @scanner.matched
handled =
case id
when /[a-z]/i
if @scanner.scan(CLASSIC_TAG_SCAN)
if handle_classic_tag(id + @scanner.matched, closing)
already_closed = true
end
end
when '*'
if @scanner.scan(SEPARATOR_TAG_SCAN)
handle_asterisk tag_start, id + @scanner.matched
true
end
when '-'
if @scanner.scan(FORMAT_TAG_SCAN)
#format = id + @scanner.matched
@encoder.add_html "\n- can be any combination of <, >, - or whitespace.
#
# === Symbols
#
# Uppercase letters stand for meta symbols, lowercase for terminals.
#
# You can make epsilon-derivations by leaving empty.
#
# === Example
# S - Ac
# A - Sc
# A - b
# A -
class Grammar
attr_reader :tracer
# Creates a new Grammar.
# If $trace is true, the algorithms explain (textual) what they do to $stdout.
def initialize data, tracer = Tracer.new
@tracer = tracer
@rules = Rules.new
@terminals, @meta_symbols = SortedSet.new, Array.new
@start_symbol = nil
add_rules data
end
attr_reader :meta_symbols, :terminals, :rules, :start_symbol
alias_method :sigma, :terminals
alias_method :alphabet, :terminals
alias_method :variables, :meta_symbols
alias_method :nonterminals, :meta_symbols
# A string representation of the grammar for debugging.
def inspect productions_too = false
'Grammar(meta symbols: %s; alphabet: %s; productions: [%s]; start symbol: %s)' %
[
meta_symbols.join(', '),
terminals.join(', '),
if productions_too
@rules.inspect
else
@rules.size
end,
start_symbol
]
end
# Add rules to the grammar. +rules+ should be a String or respond to +scan+ in a similar way.
#
# Syntax: see Grammar.
def add_rules grammar
@rules = Rules.parse grammar do |rule|
@start_symbol ||= rule.left
@meta_symbols << rule.left
@terminals.merge rule.right.split('').select { |s| terminal? s }
end
@meta_symbols.uniq!
update
end
# Returns a hash acting as FIRST operator, so that
# first["ABC"] is FIRST(ABC).
# See http://en.wikipedia.org/wiki/LL_parser "Constructing an LL(1) parsing table" for details.
def first
first_operator
end
# Returns a hash acting as FOLLOW operator, so that
# first["A"] is FOLLOW(A).
# See http://en.wikipedia.org/wiki/LL_parser "Constructing an LL(1) parsing table" for details.
def follow
follow_operator
end
LLError = Class.new(Exception)
LLErrorType1 = Class.new(LLError)
LLErrorType2 = Class.new(LLError)
# Tests if the grammar is LL(1).
def ll1?
begin
for meta in @meta_symbols
first_sets = @rules[meta].map { |alpha| first[alpha] }
first_sets.inject(Set[]) do |already_used, another_first_set|
unless already_used.disjoint? another_first_set
raise LLErrorType1
end
already_used.merge another_first_set
end
if first[meta].include? EPSILON and not first[meta].disjoint? follow[meta]
raise LLErrorType2
end
end
rescue LLError
false
else
true
end
end
private
def first_operator
@first ||= FirstOperator.new self
end
def follow_operator
@follow ||= FollowOperator.new self
end
def update
@first = @follow = nil
end
end
if $0 == __FILE__
eval DATA.read, nil, $0, __LINE__+4
end
require 'test/unit'
class TestCaseGrammar < Test::Unit::TestCase
include Grammar::Symbols
def fifo s
Set[*s.split('')]
end
def test_fifo
assert_equal Set[], fifo('')
assert_equal Set[EPSILON, END_OF_INPUT, 'x', 'Y'], fifo('?xY$')
end
TEST_GRAMMAR_1 = <<-EOG
S - ABCD
A - a
A -
B - b
B -
C - c
C -
D - S
D -
EOG
def test_symbols
assert EPSILON
assert END_OF_INPUT
end
def test_first_1
g = Grammar.new TEST_GRAMMAR_1
f = nil
assert_nothing_raised { f = g.first }
assert_equal(Set['a', EPSILON], f['A'])
assert_equal(Set['b', EPSILON], f['B'])
assert_equal(Set['c', EPSILON], f['C'])
assert_equal(Set['a', 'b', 'c', EPSILON], f['D'])
assert_equal(f['D'], f['S'])
end
def test_follow_1
g = Grammar.new TEST_GRAMMAR_1
f = nil
assert_nothing_raised { f = g.follow }
assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['A'])
assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['B'])
assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['C'])
assert_equal(Set[END_OF_INPUT], f['D'])
assert_equal(Set[END_OF_INPUT], f['S'])
end
TEST_GRAMMAR_2 = <<-EOG
S - Ed
E - EpT
E - EmT
E - T
T - TuF
T - TdF
T - F
F - i
F - n
F - aEz
EOG
def test_first_2
g = Grammar.new TEST_GRAMMAR_2
f = nil
assert_nothing_raised { f = g.first }
assert_equal(Set['a', 'n', 'i'], f['E'])
assert_equal(Set['a', 'n', 'i'], f['F'])
assert_equal(Set['a', 'n', 'i'], f['T'])
assert_equal(Set['a', 'n', 'i'], f['S'])
end
def test_follow_2
g = Grammar.new TEST_GRAMMAR_2
f = nil
assert_nothing_raised { f = g.follow }
assert_equal(Set['m', 'd', 'z', 'p'], f['E'])
assert_equal(Set['m', 'd', 'z', 'p', 'u'], f['F'])
assert_equal(Set['m', 'd', 'z', 'p', 'u'], f['T'])
assert_equal(Set[END_OF_INPUT], f['S'])
end
LLError = Grammar::LLError
TEST_GRAMMAR_3 = <<-EOG
E - TD
D - pTD
D -
T - FS
S - uFS
S -
S - p
F - aEz
F - i
EOG
NoError = Class.new(Exception)
def test_first_3
g = Grammar.new TEST_GRAMMAR_3
# Grammar 3 is LL(1), so all first-sets must be disjoint.
f = nil
assert_nothing_raised { f = g.first }
assert_equal(Set['a', 'i'], f['E'])
assert_equal(Set[EPSILON, 'p'], f['D'])
assert_equal(Set['a', 'i'], f['F'])
assert_equal(Set['a', 'i'], f['T'])
assert_equal(Set[EPSILON, 'u', 'p'], f['S'])
for m in g.meta_symbols
r = g.rules[m]
firsts = r.map { |x| f[x] }.to_set
assert_nothing_raised do
firsts.inject(Set.new) do |already_used, another_first_set|
raise LLError, 'not disjoint!' unless already_used.disjoint? another_first_set
already_used.merge another_first_set
end
end
end
end
def test_follow_3
g = Grammar.new TEST_GRAMMAR_3
# Grammar 3 is not LL(1), because epsilon is in FIRST(S),
# but FIRST(S) and FOLLOW(S) are not disjoint.
f = nil
assert_nothing_raised { f = g.follow }
assert_equal(Set['z', END_OF_INPUT], f['E'])
assert_equal(Set['z', END_OF_INPUT], f['D'])
assert_equal(Set['z', 'p', 'u', END_OF_INPUT], f['F'])
assert_equal(Set['p', 'z', END_OF_INPUT], f['T'])
assert_equal(Set['p', 'z', END_OF_INPUT], f['S'])
for m in g.meta_symbols
first_m = g.first[m]
next unless first_m.include? EPSILON
assert_raise(m == 'S' ? LLError : NoError) do
if first_m.disjoint? f[m]
raise NoError # this is fun :D
else
raise LLError
end
end
end
end
TEST_GRAMMAR_3b = <<-EOG
E - TD
D - pTD
D - PTD
D -
T - FS
S - uFS
S -
F - aEz
F - i
P - p
EOG
def test_first_3b
g = Grammar.new TEST_GRAMMAR_3b
# Grammar 3b is NOT LL(1), since not all first-sets are disjoint.
f = nil
assert_nothing_raised { f = g.first }
assert_equal(Set['a', 'i'], f['E'])
assert_equal(Set[EPSILON, 'p'], f['D'])
assert_equal(Set['p'], f['P'])
assert_equal(Set['a', 'i'], f['F'])
assert_equal(Set['a', 'i'], f['T'])
assert_equal(Set[EPSILON, 'u'], f['S'])
for m in g.meta_symbols
r = g.rules[m]
firsts = r.map { |x| f[x] }
assert_raise(m == 'D' ? LLError : NoError) do
firsts.inject(Set.new) do |already_used, another_first_set|
raise LLError, 'not disjoint!' unless already_used.disjoint? another_first_set
already_used.merge another_first_set
end
raise NoError
end
end
end
def test_follow_3b
g = Grammar.new TEST_GRAMMAR_3b
# Although Grammar 3b is NOT LL(1), the FOLLOW-condition is satisfied.
f = nil
assert_nothing_raised { f = g.follow }
assert_equal(fifo('z$'), f['E'], 'E')
assert_equal(fifo('z$'), f['D'], 'D')
assert_equal(fifo('ai'), f['P'], 'P')
assert_equal(fifo('z$pu'), f['F'], 'F')
assert_equal(fifo('z$p'), f['T'], 'T')
assert_equal(fifo('z$p'), f['S'], 'S')
for m in g.meta_symbols
first_m = g.first[m]
next unless first_m.include? EPSILON
assert_raise(NoError) do
if first_m.disjoint? f[m]
raise NoError # this is fun :D
else
raise LLError
end
end
end
end
def test_ll1?
assert_equal false, Grammar.new(TEST_GRAMMAR_3).ll1?, 'Grammar 3'
assert_equal false, Grammar.new(TEST_GRAMMAR_3b).ll1?, 'Grammar 3b'
end
def test_new
assert_nothing_raised { Grammar.new '' }
assert_nothing_raised { Grammar.new TEST_GRAMMAR_1 }
assert_nothing_raised { Grammar.new TEST_GRAMMAR_2 }
assert_nothing_raised { Grammar.new TEST_GRAMMAR_3 }
assert_nothing_raised { Grammar.new TEST_GRAMMAR_1 + TEST_GRAMMAR_2 + TEST_GRAMMAR_3 }
assert_raise(ArgumentError) { Grammar.new 'S - ?' }
end
end
# vim:foldmethod=syntax
#!/usr/bin/env ruby
require 'fox12'
include Fox
class Window < FXMainWindow
def initialize(app)
super(app, app.appName + ": First Set Calculation", nil, nil, DECOR_ALL, 0, 0, 800, 600, 0, 0)
# {{{ menubar
menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
filemenu = FXMenuPane.new(self)
FXMenuCommand.new(filemenu, "&Start\tCtl-S\tStart the application.", nil, getApp()).connect(SEL_COMMAND, method(:start))
FXMenuCommand.new(filemenu, "&Quit\tAlt-F4\tQuit the application.", nil, getApp(), FXApp::ID_QUIT)
FXMenuTitle.new(menubar, "&File", nil, filemenu)
# }}} menubar
# {{{ statusbar
@statusbar = FXStatusBar.new(self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER)
# }}} statusbar
# {{{ window content
horizontalsplitt = FXSplitter.new(self, SPLITTER_VERTICAL|LAYOUT_SIDE_TOP|LAYOUT_FILL)
@productions = FXList.new(horizontalsplitt, nil, 0, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT|LIST_SINGLESELECT)
@productions.height = 100
@result = FXTable.new(horizontalsplitt, nil, 0, LAYOUT_FILL)
@result.height = 200
@result.setTableSize(2, 2, false)
@result.rowHeaderWidth = 0
header = @result.columnHeader
header.setItemText 0, 'X'
header.setItemText 1, 'FIRST(X)'
for item in header
item.justification = FXHeaderItem::CENTER_X
end
@debug = FXText.new(horizontalsplitt, nil, 0, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT)
@debug.height = 200
# }}} window content
end
def load_grammar grammar
@tracer = FirstTracer.new(self)
@grammar = Grammar.new grammar, @tracer
@rules_indexes = Hash.new
@grammar.rules.each_with_index do |rule, i|
@productions.appendItem rule.inspect
@rules_indexes[rule] = i
end
end
def create
super
show(PLACEMENT_SCREEN)
end
def rule rule
@productions.selectItem @rules_indexes[rule]
sleep 0.1
end
def iterate i
setTitle i.to_s
sleep 0.1
end
def missing what
@debug.appendText what + "\n"
sleep 0.1
end
def start sender, sel, pointer
Thread.new do
begin
@grammar.first
rescue => boom
@debug.appendText [boom.to_s, *boom.backtrace].join("\n")
end
end
end
end
$: << 'grammar'
require 'grammar'
require 'first_tracer'
app = FXApp.new("Shinobu", "cYcnus")
# fenster erzeugen
window = Window.new app
unless ARGV.empty?
grammar = File.read(ARGV.first)
else
grammar = <<-EOG1
Z --> S
S --> Sb
S --> bAa
A --> aSc
A --> a
A --> aSb
EOG1
end
window.load_grammar grammar
app.create
app.run
require 'erb'
require 'ftools'
require 'yaml'
require 'redcloth'
module WhyTheLuckyStiff
class Book
attr_accessor :author, :title, :terms, :image, :teaser,
:chapters, :expansion_paks, :encoding, :credits
def [] x
@lang.fetch(x) do
warn warning = "[not translated: '#{x}'!]"
warning
end
end
end
def Book::load( file_name )
YAML::load( File.open( file_name ) )
end
class Section
attr_accessor :index, :header, :content
def initialize( i, h, c )
@index, @header, @content = i, h, RedCloth::new( c.to_s )
end
end
class Sidebar
attr_accessor :title, :content
end
YAML::add_domain_type( 'whytheluckystiff.net,2003', 'sidebar' ) do |taguri, val|
YAML::object_maker( Sidebar, 'title' => val.keys.first, 'content' => RedCloth::new( val.values.first ) )
end
class Chapter
attr_accessor :index, :title, :sections
def initialize( i, t, sects )
@index = i
@title = t
i = 0
@sections = sects.collect do |s|
if s.respond_to?( :keys )
i += 1
Section.new( i, s.keys.first, s.values.first )
else
s
end
end
end
end
YAML::add_domain_type( 'whytheluckystiff.net,2003', 'book' ) do |taguri, val|
['chapters', 'expansion_paks'].each do |chaptype|
i = 0
val[chaptype].collect! do |c|
i += 1
Chapter::new( i, c.keys.first, c.values.first )
end
end
val['teaser'].collect! do |t|
Section::new( 1, t.keys.first, t.values.first )
end
val['terms'] = RedCloth::new( val['terms'] )
YAML::object_maker( Book, val )
end
class Image
attr_accessor :file_name
end
YAML::add_domain_type( 'whytheluckystiff.net,2003', 'img' ) do |taguri, val|
YAML::object_maker( Image, 'file_name' => "i/" + val )
end
end
#
# Convert the book to HTML
#
if __FILE__ == $0
unless ARGV[0]
puts "Usage: #{$0} [/path/to/save/html]"
exit
end
site_path = ARGV[0]
book = WhyTheLuckyStiff::Book::load( 'poignant.yml' )
chapter = nil
# Write index page
index_tpl = ERB::new( File.open( 'index.erb' ).read )
File.open( File.join( site_path, 'index.html' ), 'w' ) do |out|
out << index_tpl.result
end
book.chapters = book.chapters[0,3] if ARGV.include? '-fast'
# Write chapter pages
chapter_tpl = ERB::new( File.open( 'chapter.erb' ).read )
book.chapters.each do |chapter|
File.open( File.join( site_path, "chapter-#{ chapter.index }.html" ), 'w' ) do |out|
out << chapter_tpl.result
end
end
exit if ARGV.include? '-fast'
# Write expansion pak pages
expak_tpl = ERB::new( File.open( 'expansion-pak.erb' ).read )
book.expansion_paks.each do |pak|
File.open( File.join( site_path, "expansion-pak-#{ pak.index }.html" ), 'w' ) do |out|
out << expak_tpl.result( binding )
end
end
# Write printable version
print_tpl = ERB::new( File.open( 'print.erb' ).read )
File.open( File.join( site_path, "print.html" ), 'w' ) do |out|
out << print_tpl.result
end
# Copy css + images into site
copy_list = ["guide.css"] +
Dir["i/*"].find_all { |image| image =~ /\.(gif|jpg|png)$/ }
File.makedirs( File.join( site_path, "i" ) )
copy_list.each do |copy_file|
File.copy( copy_file, File.join( site_path, copy_file ) )
end
end
#!/usr/bin/env ruby
require 'fox'
begin
require 'opengl'
rescue LoadError
require 'fox/missingdep'
MSG = <
# RUBY_VERSION[0].digit == '1.8.2'[0].digit == 1
#
#
#
# ?6.digit == 6
#
#
#
# ?A.digit == 17
#
def digit
self - ?0
end
end
##
# Stellt einen einfachen Scanner für die lexikalische Analyse der Sprache Pas-0 dar.
#
# @author Andreas Kunert
# Ruby port by murphy
class Scanner
include TokenConsts
attr_reader :line, :pos
# To allow Scanner.new without parameters.
DUMMY_INPUT = 'dummy file'
def DUMMY_INPUT.getc
nil
end
##
# Erzeugt einen Scanner, der als Eingabe das übergebene IO benutzt.
def initialize input = DUMMY_INPUT
@line = 1
@pos = 0
begin
@input = input
@next_char = @input.getc
rescue IOError # TODO show the reason!
Error.ioError
raise
end
end
##
# Liest das n chste Zeichen von der Eingabe.
def read_next_char
begin
@pos += 1
@current_char = @next_char
@next_char = @input.getc
rescue IOError
Error.ioError
raise
end
end
##
# Sucht das nächste Symbol, identifiziert es, instantiiert ein entsprechendes
# PascalSymbol-Objekt und gibt es zurück.
# @see Symbol
# @return das gefundene Symbol als PascalSymbol-Objekt
def get_symbol
current_symbol = nil
until current_symbol
read_next_char
if @current_char.alpha?
identifier = @current_char.chr
while @next_char.alpha? or @next_char.digit?
identifier << @next_char
read_next_char
end
current_symbol = handle_identifier(identifier.upcase)
elsif @current_char.digit?
current_symbol = number
else
case @current_char
when ?\s
# ignore
when ?\n
new_line
when nil
current_symbol = PascalSymbol.new EOP
when ?{
comment
when ?:
if @next_char == ?=
read_next_char
current_symbol = PascalSymbol.new BECOMES
else
current_symbol = PascalSymbol.new COLON
end
when ?<
if (@next_char == ?=)
read_next_char
current_symbol = PascalSymbol.new LEQSY
elsif (@next_char == ?>)
read_next_char
current_symbol = PascalSymbol.new NEQSY
else
current_symbol = PascalSymbol.new LSSSY
end
when ?>
if (@next_char == ?=)
read_next_char
current_symbol = PascalSymbol.new GEQSY
else
current_symbol = PascalSymbol.new GRTSY
end
when ?. then current_symbol = PascalSymbol.new PERIOD
when ?( then current_symbol = PascalSymbol.new LPARENT
when ?, then current_symbol = PascalSymbol.new COMMA
when ?* then current_symbol = PascalSymbol.new TIMES
when ?/ then current_symbol = PascalSymbol.new SLASH
when ?+ then current_symbol = PascalSymbol.new PLUS
when ?- then current_symbol = PascalSymbol.new MINUS
when ?= then current_symbol = PascalSymbol.new EQLSY
when ?) then current_symbol = PascalSymbol.new RPARENT
when ?; then current_symbol = PascalSymbol.new SEMICOLON
else
Error.error(100, @line, @pos) if @current_char > ?\s
end
end
end
current_symbol
end
private
##
# Versucht, in dem gegebenen String ein Schlüsselwort zu erkennen.
# Sollte dabei ein Keyword gefunden werden, so gibt er ein PascalSymbol-Objekt zurück, das
# das entsprechende Keyword repräsentiert. Ansonsten besteht die Rückgabe aus
# einem SymbolIdent-Objekt (abgeleitet von PascalSymbol), das den String 1:1 enthält
# @see symbol
# @return falls Keyword gefunden, zugehöriges PascalSymbol, sonst SymbolIdent
def handle_identifier identifier
if sym = KEYWORD_SYMBOLS[identifier]
PascalSymbol.new sym
else
SymbolIdent.new identifier
end
end
MAXINT = 2**31 - 1
MAXINT_DIV_10 = MAXINT / 10
MAXINT_MOD_10 = MAXINT % 10
##
# Versucht, aus dem gegebenen Zeichen und den folgenden eine Zahl zusammenzusetzen.
# Dabei wird der relativ intuitive Algorithmus benutzt, die endgültige Zahl bei
# jeder weiteren Ziffer mit 10 zu multiplizieren und diese dann mit der Ziffer zu
# addieren. Sonderfälle bestehen dann nur noch in der Behandlung von reellen Zahlen.
# Script size is #{kilosize}" puts "
Last script update: #{last_modif}"
#__END__
# DO NOT REMOVE THE PRECEEDING LINE.
# Everything else in this file will be ignored.
#CODE
# @@PLEAC@@_7.7
while line = gets do
# do something with line.
end
# or
while gets do
# do something with $_
end
# or more rubyish
$stdun.each do |line|
# do stuff with line
end
# ARGF may makes this more easy
# this is skipped if ARGV.size==0
ARGV.each do |filename|
# closing and exception handling are done by the block
open(filename) do |fd|
fd.each do |line|
# do stuff with line
end
end rescue abort("can't open %s" % filename)
end
# globbing is done in the Dir module
ARGV = Dir["*.[Cch]"] if ARGV.empty?
# note: optparse is the preferred way to handle this
if (ARGV[0] == '-c')
chop_first += 1
ARGV.shift
end
# processing numerical options
if ARGV[0] =~ /^-(\d+)$/
columns = $1
ARGV.shift
end
# again, better to use optparse:
require 'optparse'
nostdout = 0
append = 0
unbuffer = 0
ignore_ints = 0
ARGV.options do |opt|
opt.on('-n') { nostdout +=1 }
opt.on('-a') { append +=1 }
opt.on('-u') { unbuffer +=1 }
opt.on('-i') { ignore_ints +=1 }
opt.parse!
end or abort("usage: " + __FILE__ + " [-ainu] [filenames]")
# no need to do undef $/, we have File.read
str = File.read(ARGV[0])
# again we have File.read
str = File.read(ARGV[0])
# not sure what this should do:
# I believe open the file, print filename, lineno and line:
ARGF.each_with_index do |line, idx|
print ARGF.filename, ":", idx, ";", line
end
# print all the lines in every file passed via command line that contains login
ARGF.each do |line|
puts line if line =~ /login/
end
#
# even this would fit
#%ruby -ne "print if /f/" 2.log
#
ARGF.each { |l| puts l.downcase! }
#------------------
#!/usr/bin/ruby -p
# just like perl's -p
$_.downcase!
#
# I don't know who should I trust.
# perl's version splits on \w+ while python's on \w.
chunks = 0
File.read(ARGV[0]).split.each do |word|
next if word =~ /^#/
break if ["__DATA__", "__END__"].member? word
chunks += 1
end
print "Found ", chunks, " chunks\n"
# @@PLEAC@@_7.8
old = File.open(old_file)
new = File.open(new_file, "w")
while old.gets do
# change $_, then...
new.print $_
end
old.close
new.close
File.rename(old_file, "old.orig")
File.rename(new_file, old_file)
while old.gets do
if $. == 20 then # we are at the 20th line
new.puts "Extra line 1"
new.puts "Extra line 2"
end
new.print $_
end
while old.gets do
next if 20..30 # skip the 20th line to the 30th
# Ruby (and Perl) permit to write if 20..30
# instead of if (20 <= $.) and ($. <= 30)
new.print $_
end
# @@PLEAC@@_7.9
#% ruby -i.orig -pe 'FILTER COMMAND' file1 file2 file3 ...
#
#-----------------------------
##!/usr/bin/ruby -i.orig -p
# filter commands go here
#-----------------------------
#% ruby -pi.orig -e 'gsub!(/DATE/){Time.now)'
# effectively becomes:
ARGV << 'I'
oldfile = ""
while gets
if ARGF.filename != oldfile
newfile = ARGF.filename
File.rename(newfile, newfile + ".orig")
$stdout = File.open(newfile,'w')
oldfile = newfile
end
gsub!(/DATE/){Time.now}
print
end
$stdout = STDOUT
#-----------------------------
#% ruby -i.old -pe 'gsub!(%r{\bhisvar\b}, 'hervar')' *.[Cchy]
#-----------------------------
# set up to iterate over the *.c files in the current directory,
# editing in place and saving the old file with a .orig extension
$-i = '.orig' # set up -i mode
ARGV.replace(Dir['*.[Cchy]'])
while gets
if $. == 1
print "This line should appear at the top of each file\n"
end
gsub!(/\b(p)earl\b/i, '\1erl') # Correct typos, preserving case
print
ARGF.close if ARGF.eof
end
# @@PLEAC@@_7.10
File.open('itest', 'r+') do |f| # open file for update
lines = f.readlines # read into array of lines
lines.each do |it| # modify lines
it.gsub!(/foo/, 'QQQ')
end
f.pos = 0 # back to start
f.print lines # write out modified lines
f.truncate(f.pos) # truncate to new length
end # file is automatically closed
#-----------------------------
File.open('itest', 'r+') do |f|
out = ""
f.each do |line|
out << line.gsub(/DATE/) {Time.now}
end
f.pos = 0
f.print out
f.truncate(f.pos)
end
# @@PLEAC@@_7.11
File.open('infile', 'r+') do |f|
f.flock File::LOCK_EX
# update file
end
#-----------------------------
File::LOCK_SH # shared lock (for reading)
File::LOCK_EX # exclusive lock (for writing)
File::LOCK_NB # non-blocking request
File::LOCK_UN # free lock
#-----------------------------
unless f.flock File::LOCK_EX | File::LOCK_NB
warn "can't get immediate lock: blocking ..."
f.flock File::LOCK_EX
end
#-----------------------------
File.open('numfile', File::RDWR|File::CREAT) do |f|
f.flock(File::LOCK_EX)
num = f.gets.to_i || 0
f.pos = 0
f.truncate 0
f.puts num + 1q
end
# @@PLEAC@@_7.12
output_handle.sync = true
# Please note that like in Perl, $stderr is already unbuffered
#-----------------------------
#!/usr/bin/ruby -w
# seeme - demo stdio output buffering
$stdout.sync = ARGV.size > 0
print "Now you don't see it..."
sleep 2
puts "now you do"
#-----------------------------
$stderr.sync = true
afile.sync = false
#-----------------------------
# assume 'remote_con' is an interactive socket handle,
# but 'disk_file' is a handle to a regular file.
remote_con.sync = true # unbuffer for clarity
disk_file.sync = false # buffered for speed
#-----------------------------
require 'socket'
sock = TCPSocket.new('www.ruby-lang.org', 80)
sock.sync = true
sock.puts "GET /en/ HTTP/1.0 \n\n"
resp = sock.read
print "DOC IS: #{resp}\n"
# @@PLEAC@@_7.13
#-----------------------------
# assumes fh1, fh2, fh2 are oen IO objects
nfound = select([$stdin, fh1, fh2, fh3], nil, nil, 0)
nfound[0].each do |file|
case file
when fh1
# do something with fh1
when fh2
# do something with fh2
when fh3
# do something with fh3
end
end
#-----------------------------
input_files = []
# repeat next line for all in-files to poll
input_files << fh1
if nfound = select(input_files, nil, nil, 0)
# input ready on files in nfound[0]
end
# @@PLEAC@@_8.0
#-----------------------------
# datafile is a file or IO object
datafile.readlines.each { |line|
line.chomp!
size = line.length
puts size
}
#-----------------------------
datafile.readlines.each { |line|
puts line.chomp!.length
}
#-----------------------------
lines = datafile.readlines
#-----------------------------
whole_file = file.read
#-----------------------------
# ruby -040 -e 'word = gets; puts "First word is #{word}"'
#-----------------------------
# ruby -ne 'BEGIN { $/="%%\n" }; $_.chomp; puts $_ if( $_=~/Unix/i)' fortune.dat
#-----------------------------
handle.print "one", "two", "three" # "onetwothree"
puts "Baa baa black sheep." # sent to $stdout
#-----------------------------
buffer = handle.read(4096)
rv = buffer.length
#-----------------------------
handle.truncate(length)
open("/tmp#{$$}.pid", 'w') { |handle| handle.truncate(length) }
#-----------------------------
pos = datafile.pos # tell is an alias of pos
puts "I'm #{pos} bytes from the start of datafile"
#-----------------------------
logfile.seek(0, IO::SEEK_END)
datafile.seek(pos) # IO::SEEK_SET is the default
out.seek(-20, IO::SEEK_CUR)
#-----------------------------
written = datafile.syswrite(mystring)
raise RunTimeError unless written == mystring.length
block = infile.sysread(256) # no equivalent to perl offset parameter in sysread
puts "only read #{block.length} bytes" if 256 != block.length
#-----------------------------
pos = handle.sysseek(0, IO::SEEK_CUR) # don't change position
# @@PLEAC@@_8.1
while (line = fh.gets)
line.chomp!
nextline = nil
line.gsub!(/\\$/) { |match| nextline = fh.gets; '' }
if (nextline != nil)
line += nextline
redo
end
# process full record in line here
end
#-----------------------------
# DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) \
# $(TEXINFOS) $(INFOS) $(MANS) $(DATA)
# DEP_DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) \
# $(TEXINFOS) $(INFO_DEPS) $(MANS) $(DATA) \
# $(EXTRA_DIST)
#-----------------------------
line.gsub!(/\\\s*$/, '') {
# as before
}
# @@PLEAC@@_8.2
#-----------------------------
count = `wc -l < #{filename}`
fail "wc failed: #{$?}" if $? != 0
count.chomp!
#-----------------------------
count = 0
File.open(file, 'r') { |fh|
count += 1 while fh.gets
}
# count now holds the number of lines read
#-----------------------------
count = 0
while (chunk = file.sysread(2**16))
count += chunk.count("\n")
end rescue EOFError
#-----------------------------
File.open(filename,'r') { |fh|
count += 1 while fh.gets
}
# count now holds the number of lines read
#-----------------------------
# As ruby doesn't quite have an equivalent to using a for
# statement as in perl, I threw this in
count = File.readlines(filename).size
#-----------------------------
1 while file.gets
count = $.
#-----------------------------
$/ = ''
open(filename, 'r') { |fh|
1 while fh.gets
para_count = $.
} rescue fail("can't open #{filename}: $!")
#-----------------------------
# ^^PLEAC^^_8.3
#-----------------------------
while (gets)
split.each { |chunk|
# do something with chunk
}
end
#-----------------------------
while (gets)
gsub(/(\w[\w'-]*)/) { |word|
# do something with word
}
end
#-----------------------------
# Make a word frequency count
# normally hashes can be created using {} or just Hash.new
# but we want the default value of an entry to be 0 instead
# of nil. (nil can't be incremented)
seen = Hash.new(0)
while (gets)
gsub(/(\w[\w'-]*)/) { |word|
seen[word.downcase] += 1
}
end
# output hash in a descending numeric sort of its values
seen.sort { |a,b| b[1] <=> a[1] }.each do |k,v|
printf("%5d %s\n", v, k )
end
#-----------------------------
# Line frequency count
seen = Hash.new(0)
while (gets)
seen[$_.downcase] += 1
end
seen.sort { |a,b| b[1] <=> a[1] }.each do |k,v|
printf("%5d %s\n", v, k )
end
#-----------------------------
# @@PLEAC@@_8.4
#-----------------------------
# instead of file handle FILE, we can just
# use a string containing the filename
File.readlines(file).each { |line|
# do something with line
}
#-----------------------------
File.readlines(file).reverse_each { |line|
# do something with line
}
#-----------------------------
# the variable lines might have been created
# this way
# lines = File.readlines(file)
#
# normally one would use the reverse_each, but
# if you insist on using a numerical index to
# iterate over the lines array...
(lines.size - 1).downto(0) { |i|
line = lines[i]
}
#-----------------------------
# the second readlines argument is a the
# record separator $/, just like perl, a blank
# separator splits the records into paragraphs
File.readlines(file, '').each { |paragraph|
# do something with paragraph
puts "->Paragraph #{paragraph}"
}
#-----------------------------
# @@PLEAC@@_8.6
$/ = "%\n";
srand;
File.open('/usr/share/fortune/humorists').each do |line|
adage = line if rand($.) < 1
end
puts adage;
# @@PLEAC@@_8.10
begin
fh = File.open(file, "r+")
addr = fh.tell unless fh.eof while fh.gets
fh.truncate(addr)
rescue SystemCallError
$stderr.puts "#$!"
end
# @@PLEAC@@_9.0
entry = File.stat("/usr/bin/vi")
entry = File.stat("/usr/bin")
entry = File.stat(INFILE)
entry = File.stat("/usr/bin/vi")
ctime = entry.ctime
size = entry.size
f = File.open(filename, "r")
## There is no -T equivalent in Ruby, but we can still test emptiness
if test(?s, filename)
puts "#{filename} doesn't have text in it."
exit
end
Dir.new("/usr/bin").each do |filename|
puts "Inside /usr/bin is something called #{filename}"
end
# @@PLEAC@@_9.1
file = File.stat("filename")
readtime, writetime = file.atime, file.mtime
file.utime(readtime, writetime)
SECONDS_PER_DAY = 60 * 60 * 24
file = File.stat("filename")
atime, mtime = file.atime, file.mtime
atime -= 7 * SECONDS_PER_DAY
mtime -= 7 * SECONDS_PER_DAY
File.utime(atime, mtime, file)
mtime = File.stat(file).mtime
File.utime(Time.new, mtime, file)
File.utime(Time.new, File.stat("testfile").mtime, file)
#-----------------------------
#!/usr/bin/ruby -w
## uvi - vi a file without changing it's access times
if ARGV.length != 1
puts "usage: uvi filename"
exit
end
file = ARGV[0]
atime, mtime = File.stat(file).atime, File.stat(file).mtime
system(ENV["EDITOR"] || "vi", file)
File.utime(atime, mtime, file)
#-----------------------------
# @@PLEAC@@_9.2
File.unlink(FILENAME)
err_flg = false
filenames.each do |file|
begin
File.unlink(file)
rescue
err_flg = $!
end
end
err_flg and raise "Couldn't unlink all of #{filenames.join(" ")}: #{err_flg}"
File.unlink(file)
count = filenames.length
filenames.each do |file|
begin
File.unlink(file)
rescue
count -= 1
end
end
if count != filenames.length
STDERR.puts "could only delete #{count} of #{filenames.length} files"
end
# @@PLEAC@@_9.3
require "ftools"
File.copy(oldfile, newfile)
infile = File.open(oldfile, "r")
outfile = File.open(newfile, "w")
blksize = infile.stat.blksize
# This doesn't handle partial writes or ^Z
# like the Perl version does.
while (line = infile.read(blksize))
outfile.write(line)
end
infile.close
outfile.close
system("cp #{oldfile} #{newfile}") # unix
system("copy #{oldfile} #{newfile}") # dos, vms
require "ftools"
File.copy("datafile.dat", "datafile.bak")
File.move("datafile.new", "datafile.dat")
# @@PLEAC@@_9.4
$seen = {} # must use global var to be seen inside of method below
def do_my_thing(filename)
dev, ino = File.stat(filename).dev, File.stat(filename).ino
unless $seen[[dev, ino]]
# do something with $filename because we haven't
# seen it before
end
$seen[[dev, ino]] = $seen[[dev, ino]].to_i + 1
end
files.each do |filename|
dev, ino = File.stat(filename).dev, File.stat(filename).ino
if !$seen.has_key?([dev, ino])
$seen[[dev, ino]] = []
end
$seen[[dev, ino]].push(filename)
end
$seen.keys.sort.each do |devino|
ino, dev = devino
if $seen[devino].length > 1
# $seen[devino] is a list of filenames for the same file
end
end
# @@PLEAC@@_9.5
Dir.open(dirname) do |dir|
dir.each do |file|
# do something with dirname/file
puts file
end
end
# Dir.close is automatic
# No -T equivalent in Ruby
dir.each do |file|
next if file =~ /^\.\.?$/
# ...
end
def plainfiles(dir)
dh = Dir.open(dir)
dh.entries.grep(/^[^.]/).
map {|file| "#{dir}/#{file}"}.
find_all {|file| test(?f, file)}.
sort
end
# @@PLEAC@@_9.6
list = Dir.glob("*.c")
dir = Dir.open(path)
files = dir.entries.grep(/\.c$/)
dir.close
files = Dir.glob("*.c")
files = Dir.open(path).entries.grep(/\.[ch]$/i)
dir = Dir.new(path)
files = dir.entries.grep(/\.[ch]$/i)
begin
d = Dir.open(dir)
rescue Errno::ENOENT
raise "Couldn't open #{dir} for reading: #{$!}"
end
files = []
d.each do |file|
puts file
next unless file =~ /\.[ch]$/i
filename = "#{dir}/#{file}"
# There is no -T equivalent in Ruby, but we can still test emptiness
files.push(filename) if test(?s, filename)
end
dirs.entries.grep(/^\d+$/).
map { |file| [file, "#{path}/#{file}"]} .
select { |file| test(?d, file[1]) }.
sort { |a,b| a[0] <=> b[0] }.
map { |file| file[1] }
# @@PLEAC@@_9.7
require 'find'
Find.find(dirlist) do |file|
# do whatever
end
require 'find'
argv = ARGV.empty? ? %w{.} : ARGV
Find.find(*argv) do |file|
print file, (test(?d, file) ? "/\n" : "\n")
end
require 'find'
argv = ARGV.empty? ? %w{.} : ARGV
sum = 0
Find.find(*argv) do |file|
size = test(?s, file) || 0
sum += size
end
puts "#{argv.join(' ')} contains #{sum} bytes"
require 'find'
argv = ARGV.empty? ? %w{.} : ARGV
saved_size, saved_name = -1, ""
Find.find(*argv) do |file|
size = test(?s, file) || 0
next unless test(?f, file) && size > saved_size
saved_size = size
saved_name = file
end
puts "Biggest file #{saved_name} in #{argv.join(' ')} is #{saved_size}"
require 'find'
argv = ARGV.empty? ? %w{.} : ARGV
age, name = nil
Find.find(*argv) do |file|
mtime = File.stat(file).mtime
next if age && age > mtime
age = mtime
name = file
end
puts "#{name} #{age}"
#-----------------------------
#!/usr/bin/ruby -w
# fdirs - find all directories
require 'find'
argv = ARGV.empty? ? %w{.} : ARGV
File.find(*argv) { |file| puts file if test(?d, file) }
#-----------------------------
# @@PLEAC@@_9.8
require 'fileutils'
puts "Usage #{$0} dir ..." if ARGV.empty?
ARGV.each do |dir|
FileUtils.rmtree(dir)
end
# @@PLEAC@@_9.9
require 'ftools'
names.each do |file|
newname = file
begin
File.move(file, newname)
rescue Errno::EPERM
$stderr.puts "Couldn't rename #{file} to #{newname}: #{$!}"
end
end
require 'ftools'
op = ARGV.empty? ? (raise "Usage: rename expr [files]\n") : ARGV.shift
argv = ARGV.empty? ? $stdin.readlines.map { |f| f.chomp } : ARGV
argv.each do |file|
was = file
file = eval("file.#{op}")
File.move(was, file) unless was == file
end
# @@PLEAC@@_9.10
base = File.basename(path)
dir = File.dirname(path)
# ruby has no fileparse equivalent
dir, base = File.split(path)
ext = base.scan(/\..*$/).to_s
path = '/usr/lib/libc.a'
file = File.basename(path)
dir = File.dirname(path)
puts "dir is #{dir}, file is #{file}"
# dir is /usr/lib, file is libc.a
path = '/usr/lib/libc.a'
dir, filename = File.split(path)
name, ext = filename.split(/(?=\.)/)
puts "dir is #{dir}, name is #{name}, ext is #{ext}"
# NOTE: The Ruby code prints
# dir is /usr/lib, name is libc, extension is .a
# while the Perl code prints a '/' after the directory name
# dir is /usr/lib/, name is libc, extension is .a
# No fileparse_set_fstype() equivalent in ruby
def extension(path)
ext = path.scan(/\..*$/).to_s
ext.sub(/^\./, "")
end
# @@PLEAC@@_9.11
#-----------------------------
#!/usr/bin/ruby -w
# symirror - build spectral forest of symlinks
require 'find'
require 'fileutils'
raise "usage: #{$0} realdir mirrordir" unless ARGV.size == 2
srcdir,dstdir = ARGV
srcmode = File::stat(srcdir).mode
Dir.mkdir(dstdir, srcmode & 07777) unless test(?d, dstdir)
# fix relative paths
Dir.chdir(srcdir) {srcdir = Dir.pwd}
Dir.chdir(dstdir) {dstdir = Dir.pwd}
Find.find(srcdir) do |srcfile|
if test(?d, srcfile)
dest = srcfile.sub(/^#{srcdir}/, dstdir)
dmode = File::stat(srcfile).mode & 07777
Dir.mkdir(dest, dmode) unless test(?d, dest)
a = Dir["#{srcfile}/*"].reject{|f| test(?d, f)}
FileUtils.ln_s(a, dest)
end
end
# @@PLEAC@@_9.12
# we use the Getopt/Declare library here for convenience:
# http://raa.ruby-lang.org/project/getoptdeclare/
#-----------------------------
#!/usr/bin/ruby -w
# lst - list sorted directory contents (depth first)
require 'find'
require 'etc'
require "Getopt/Declare"
# Note: in the option-spec below there must by at least one hard
# tab in between each -option and its description. For example
# -i <%= flash[:notice] %> puts "Hello, World!" > #include <test.h> _dff.skjd<%CONTENT%>
TABLE
PAGE = Template.new <<-PAGE
<%LINE_NUMBERS%>
<%CONTENT%>
#{opts[:text]}"
end
end
def bc_open(opts) # :nodoc:
opts[:block] = true
@in_bc = opts
opts[:lang] ? '' : ""
end
def bc_close(opts) # :nodoc:
opts = @in_bc
@in_bc = nil
opts[:lang] ? '' : "\n"
end
def escape_pre(text) # :nodoc:
if @in_bc ||= nil
text
else
html_esc(text, :html_escape_preformatted)
end
end
end
end
module TextileDoc # :nodoc:
attr_accessor :filter_coderay
end
end
end
CodeRay::ForRedCloth.install coderay-1.1.3/lib/coderay/helpers/ 0000775 0000000 0000000 00000000000 13664404461 0017010 5 ustar 00root root 0000000 0000000 coderay-1.1.3/lib/coderay/helpers/file_type.rb 0000664 0000000 0000000 00000010052 13664404461 0021313 0 ustar 00root root 0000000 0000000 module CodeRay
# = FileType
#
# A simple filetype recognizer.
#
# == Usage
#
# # determine the type of the given
# lang = FileType[file_name]
#
# # return :text if the file type is unknown
# lang = FileType.fetch file_name, :text
#
# # try the shebang line, too
# lang = FileType.fetch file_name, :text, true
module FileType
UnknownFileType = Class.new Exception
class << self
# Try to determine the file type of the file.
#
# +filename+ is a relative or absolute path to a file.
#
# The file itself is only accessed when +read_shebang+ is set to true.
# That means you can get filetypes from files that don't exist.
def [] filename, read_shebang = false
name = File.basename filename
ext = File.extname(name).sub(/^\./, '') # from last dot, delete the leading dot
ext2 = filename.to_s[/\.(.*)/, 1] # from first dot
type =
TypeFromExt[ext] ||
TypeFromExt[ext.downcase] ||
(TypeFromExt[ext2] if ext2) ||
(TypeFromExt[ext2.downcase] if ext2) ||
TypeFromName[name] ||
TypeFromName[name.downcase]
type ||= type_from_shebang(filename) if read_shebang
type
end
# This works like Hash#fetch.
#
# If the filetype cannot be found, the +default+ value
# is returned.
def fetch filename, default = nil, read_shebang = false
if default && block_given?
warn 'Block supersedes default value argument; use either.'
end
if type = self[filename, read_shebang]
type
else
return yield if block_given?
return default if default
raise UnknownFileType, 'Could not determine type of %p.' % filename
end
end
protected
def type_from_shebang filename
return unless File.exist? filename
File.open filename, 'r' do |f|
if first_line = f.gets
if type = first_line[TypeFromShebang]
type.to_sym
end
end
end
end
end
TypeFromExt = {
'c' => :c,
'cfc' => :xml,
'cfm' => :xml,
'clj' => :clojure,
'css' => :css,
'diff' => :diff,
'dpr' => :delphi,
'erb' => :erb,
'gemspec' => :ruby,
'go' => :go,
'groovy' => :groovy,
'gvy' => :groovy,
'h' => :c,
'haml' => :haml,
'htm' => :html,
'html' => :html,
'html.erb' => :erb,
'java' => :java,
'js' => :java_script,
'json' => :json,
'lua' => :lua,
'mab' => :ruby,
'pas' => :delphi,
'patch' => :diff,
'phtml' => :php,
'php' => :php,
'php3' => :php,
'php4' => :php,
'php5' => :php,
'prawn' => :ruby,
'py' => :python,
'py3' => :python,
'pyw' => :python,
'rake' => :ruby,
'raydebug' => :raydebug,
'rb' => :ruby,
'rbw' => :ruby,
'rhtml' => :erb,
'rjs' => :ruby,
'rpdf' => :ruby,
'ru' => :ruby, # config.ru
'rxml' => :ruby,
'sass' => :sass,
'sql' => :sql,
'taskpaper' => :taskpaper,
'template' => :json, # AWS CloudFormation template
'tmproj' => :xml,
'xaml' => :xml,
'xhtml' => :html,
'xml' => :xml,
'yaml' => :yaml,
'yml' => :yaml,
}
for cpp_alias in %w[cc cpp cp cxx c++ C hh hpp h++ cu]
TypeFromExt[cpp_alias] = :cpp
end
TypeFromShebang = /\b(?:ruby|perl|python|sh)\b/
TypeFromName = {
'Capfile' => :ruby,
'Rakefile' => :ruby,
'Rantfile' => :ruby,
'Gemfile' => :ruby,
'Guardfile' => :ruby,
'Vagrantfile' => :ruby,
'Appraisals' => :ruby
}
end
end
coderay-1.1.3/lib/coderay/helpers/plugin.rb 0000664 0000000 0000000 00000002154 13664404461 0020635 0 ustar 00root root 0000000 0000000 module CodeRay
# = Plugin
#
# Plugins have to include this module.
#
# IMPORTANT: Use extend for this module.
#
# See CodeRay::PluginHost for examples.
module Plugin
attr_reader :plugin_id
# Register this class for the given +id+.
#
# Example:
# class MyPlugin < PluginHost::BaseClass
# register_for :my_id
# ...
# end
#
# See PluginHost.register.
def register_for id
@plugin_id = id
plugin_host.register self, id
end
# Returns the title of the plugin, or sets it to the
# optional argument +title+.
def title title = nil
if title
@title = title.to_s
else
@title ||= name[/([^:]+)$/, 1]
end
end
# The PluginHost for this Plugin class.
def plugin_host host = nil
if host.is_a? PluginHost
const_set :PLUGIN_HOST, host
end
self::PLUGIN_HOST
end
def aliases
plugin_host.plugin_hash.inject [] do |aliases, (key, _)|
aliases << key if plugin_host[key] == self
aliases
end
end
end
end
coderay-1.1.3/lib/coderay/helpers/plugin_host.rb 0000664 0000000 0000000 00000012527 13664404461 0021677 0 ustar 00root root 0000000 0000000 module CodeRay
# = PluginHost
#
# A simple subclass/subfolder plugin system.
#
# Example:
# class Generators
# extend PluginHost
# plugin_path 'app/generators'
# end
#
# class Generator
# extend Plugin
# PLUGIN_HOST = Generators
# end
#
# class FancyGenerator < Generator
# register_for :fancy
# end
#
# Generators[:fancy] #-> FancyGenerator
# # or
# CodeRay.require_plugin 'Generators/fancy'
# # or
# Generators::Fancy
module PluginHost
# Raised if Encoders::[] fails because:
# * a file could not be found
# * the requested Plugin is not registered
PluginNotFound = Class.new LoadError
HostNotFound = Class.new LoadError
PLUGIN_HOSTS = []
PLUGIN_HOSTS_BY_ID = {} # dummy hash
# Loads all plugins using list and load.
def load_all
for plugin in list
load plugin
end
end
# Returns the Plugin for +id+.
#
# Example:
# yaml_plugin = MyPluginHost[:yaml]
def [] id, *args, &blk
plugin = validate_id(id)
begin
plugin = plugin_hash.[](plugin, *args, &blk)
end while plugin.is_a? String
plugin
end
alias load []
# Tries to +load+ the missing plugin by translating +const+ to the
# underscore form (eg. LinesOfCode becomes lines_of_code).
def const_missing const
id = const.to_s.
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
downcase
load id
end
class << self
# Adds the module/class to the PLUGIN_HOSTS list.
def extended mod
PLUGIN_HOSTS << mod
end
end
# The path where the plugins can be found.
def plugin_path *args
unless args.empty?
@plugin_path = File.expand_path File.join(*args)
end
@plugin_path ||= ''
end
# Map a plugin_id to another.
#
# Usage: Put this in a file plugin_path/_map.rb.
#
# class MyColorHost < PluginHost
# map :navy => :dark_blue,
# :maroon => :brown,
# :luna => :moon
# end
def map hash
for from, to in hash
from = validate_id from
to = validate_id to
plugin_hash[from] = to unless plugin_hash.has_key? from
end
end
# Define the default plugin to use when no plugin is found
# for a given id, or return the default plugin.
#
# See also map.
#
# class MyColorHost < PluginHost
# map :navy => :dark_blue
# default :gray
# end
#
# MyColorHost.default # loads and returns the Gray plugin
def default id = nil
if id
id = validate_id id
raise "The default plugin can't be named \"default\"." if id == :default
plugin_hash[:default] = id
else
load :default
end
end
# Every plugin must register itself for +id+ by calling register_for,
# which calls this method.
#
# See Plugin#register_for.
def register plugin, id
plugin_hash[validate_id(id)] = plugin
end
# A Hash of plugion_id => Plugin pairs.
def plugin_hash
@plugin_hash ||= (@plugin_hash = make_plugin_hash).tap { load_plugin_map }
end
# Returns an array of all .rb files in the plugin path.
#
# The extension .rb is not included.
def list
Dir[path_to('*')].select do |file|
File.basename(file)[/^(?!_)\w+\.rb$/]
end.map do |file|
File.basename(file, '.rb').to_sym
end
end
# Returns an array of all Plugins.
#
# Note: This loads all plugins using load_all.
def all_plugins
load_all
plugin_hash.values.grep(Class)
end
# Loads the map file (see map).
#
# This is done automatically when plugin_path is called.
def load_plugin_map
mapfile = path_to '_map'
if File.exist? mapfile
require mapfile
true
else
false
end
end
protected
# Return a plugin hash that automatically loads plugins.
def make_plugin_hash
Hash.new do |h, plugin_id|
id = validate_id(plugin_id)
path = path_to id
begin
require path
rescue LoadError => boom
if h.has_key?(:default)
h[:default]
else
raise PluginNotFound, '%p could not load plugin %p: %s' % [self, id, boom]
end
else
# Plugin should have registered by now
if h.has_key? id
h[id]
else
raise PluginNotFound, "No #{self.name} plugin for #{id.inspect} found in #{path}."
end
end
end
end
# Returns the expected path to the plugin file for the given id.
def path_to plugin_id
File.join plugin_path, "#{plugin_id}.rb"
end
# Converts +id+ to a valid plugin ID String, or returns +nil+.
#
# Raises +ArgumentError+ for all other objects, or if the
# given String includes non-alphanumeric characters (\W).
def validate_id id
case id
when Symbol
id.to_s
when String
if id[/\w+/] == id
id.downcase
else
raise ArgumentError, "Invalid id given: #{id}"
end
else
raise ArgumentError, "Symbol or String expected, but #{id.class} given."
end
end
end
end
coderay-1.1.3/lib/coderay/helpers/word_list.rb 0000664 0000000 0000000 00000003176 13664404461 0021352 0 ustar 00root root 0000000 0000000 module CodeRay
# = WordList
#
# A Hash subclass designed for mapping word lists to token types.
#
# A WordList is a Hash with some additional features.
# It is intended to be used for keyword recognition.
#
# WordList is optimized to be used in Scanners,
# typically to decide whether a given ident is a special token.
#
# For case insensitive words use WordList::CaseIgnoring.
#
# Example:
#
# # define word arrays
# RESERVED_WORDS = %w[
# asm break case continue default do else
# ]
#
# PREDEFINED_TYPES = %w[
# int long short char void
# ]
#
# # make a WordList
# IDENT_KIND = WordList.new(:ident).
# add(RESERVED_WORDS, :reserved).
# add(PREDEFINED_TYPES, :predefined_type)
#
# ...
#
# def scan_tokens tokens, options
# ...
#
# elsif scan(/[A-Za-z_][A-Za-z_0-9]*/)
# # use it
# kind = IDENT_KIND[match]
# ...
class WordList < Hash
# Create a new WordList with +default+ as default value.
def initialize default = false
super default
end
# Add words to the list and associate them with +value+.
#
# Returns +self+, so you can concat add calls.
def add words, value = true
words.each { |word| self[word] = value }
self
end
end
# A CaseIgnoring WordList is like a WordList, only that
# keys are compared case-insensitively (normalizing keys using +downcase+).
class WordList::CaseIgnoring < WordList
def [] key
super key.downcase
end
def []= key, value
super key.downcase, value
end
end
end
coderay-1.1.3/lib/coderay/scanners.rb 0000664 0000000 0000000 00000001227 13664404461 0017511 0 ustar 00root root 0000000 0000000 require 'strscan'
module CodeRay
autoload :WordList, coderay_path('helpers', 'word_list')
# = Scanners
#
# This module holds the Scanner class and its subclasses.
# For example, the Ruby scanner is named CodeRay::Scanners::Ruby
# can be found in coderay/scanners/ruby.
#
# Scanner also provides methods and constants for the register
# mechanism and the [] method that returns the Scanner class
# belonging to the given lang.
#
# See PluginHost.
module Scanners
extend PluginHost
plugin_path File.dirname(__FILE__), 'scanners'
autoload :Scanner, CodeRay.coderay_path('scanners', 'scanner')
end
end
coderay-1.1.3/lib/coderay/scanners/ 0000775 0000000 0000000 00000000000 13664404461 0017162 5 ustar 00root root 0000000 0000000 coderay-1.1.3/lib/coderay/scanners/_map.rb 0000664 0000000 0000000 00000000766 13664404461 0020434 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
map \
:'c++' => :cpp,
:cplusplus => :cpp,
:ecmascript => :java_script,
:ecma_script => :java_script,
:rhtml => :erb,
:eruby => :erb,
:irb => :ruby,
:javascript => :java_script,
:js => :java_script,
:pascal => :delphi,
:patch => :diff,
:plain => :text,
:plaintext => :text,
:xhtml => :html,
:yml => :yaml
default :text
end
end
coderay-1.1.3/lib/coderay/scanners/c.rb 0000664 0000000 0000000 00000013003 13664404461 0017726 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# Scanner for C.
class C < Scanner
register_for :c
file_extension 'c'
KEYWORDS = [
'asm', 'break', 'case', 'continue', 'default', 'do',
'else', 'enum', 'for', 'goto', 'if', 'return',
'sizeof', 'struct', 'switch', 'typedef', 'union', 'while',
'restrict', # added in C99
] # :nodoc:
PREDEFINED_TYPES = [
'int', 'long', 'short', 'char',
'signed', 'unsigned', 'float', 'double',
'bool', 'complex', # added in C99
] # :nodoc:
PREDEFINED_CONSTANTS = [
'EOF', 'NULL',
'true', 'false', # added in C99
] # :nodoc:
DIRECTIVES = [
'auto', 'extern', 'register', 'static', 'void',
'const', 'volatile', # added in C89
'inline', # added in C99
] # :nodoc:
IDENT_KIND = WordList.new(:ident).
add(KEYWORDS, :keyword).
add(PREDEFINED_TYPES, :predefined_type).
add(DIRECTIVES, :directive).
add(PREDEFINED_CONSTANTS, :predefined_constant) # :nodoc:
ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
protected
def scan_tokens encoder, options
state = :initial
label_expected = true
case_expected = false
label_expected_before_preproc_line = nil
in_preproc_line = false
until eos?
case state
when :initial
if match = scan(/ \s+ | \\\n /x)
if in_preproc_line && match != "\\\n" && match.index(?\n)
in_preproc_line = false
label_expected = label_expected_before_preproc_line
end
encoder.text_token match, :space
elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
encoder.text_token match, :comment
elsif match = scan(/ [-+*=<>?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x)
label_expected = match =~ /[;\{\}]/
if case_expected
label_expected = true if match == ':'
case_expected = false
end
encoder.text_token match, :operator
elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
kind = IDENT_KIND[match]
if kind == :ident && label_expected && !in_preproc_line && scan(/:(?!:)/)
kind = :label
match << matched
else
label_expected = false
if kind == :keyword
case match
when 'case', 'default'
case_expected = true
end
end
end
encoder.text_token match, kind
elsif match = scan(/L?"/)
encoder.begin_group :string
if match[0] == ?L
encoder.text_token 'L', :modifier
match = '"'
end
encoder.text_token match, :delimiter
state = :string
elsif match = scan(/ \# \s* if \s* 0 /x)
match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos?
encoder.text_token match, :comment
elsif match = scan(/#[ \t]*(\w*)/)
encoder.text_token match, :preprocessor
in_preproc_line = true
label_expected_before_preproc_line = label_expected
state = :include_expected if self[1] == 'include'
elsif match = scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox)
label_expected = false
encoder.text_token match, :char
elsif match = scan(/\$/)
encoder.text_token match, :ident
elsif match = scan(/0[xX][0-9A-Fa-f]+/)
label_expected = false
encoder.text_token match, :hex
elsif match = scan(/(?:0[0-7]+)(?![89.eEfF])/)
label_expected = false
encoder.text_token match, :octal
elsif match = scan(/(?:\d+)(?![.eEfF])L?L?/)
label_expected = false
encoder.text_token match, :integer
elsif match = scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/)
label_expected = false
encoder.text_token match, :float
else
encoder.text_token getch, :error
end
when :string
if match = scan(/[^\\\n"]+/)
encoder.text_token match, :content
elsif match = scan(/"/)
encoder.text_token match, :delimiter
encoder.end_group :string
state = :initial
label_expected = false
elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
encoder.text_token match, :char
elsif match = scan(/ \\ | $ /x)
encoder.end_group :string
encoder.text_token match, :error unless match.empty?
state = :initial
label_expected = false
else
raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
end
when :include_expected
if match = scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/)
encoder.text_token match, :include
state = :initial
elsif match = scan(/\s+/)
encoder.text_token match, :space
state = :initial if match.index ?\n
else
state = :initial
end
else
raise_inspect 'Unknown state', encoder
end
end
if state == :string
encoder.end_group :string
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/clojure.rb 0000664 0000000 0000000 00000024415 13664404461 0021160 0 ustar 00root root 0000000 0000000 # encoding: utf-8
module CodeRay
module Scanners
# Clojure scanner by Licenser.
class Clojure < Scanner
register_for :clojure
file_extension 'clj'
SPECIAL_FORMS = %w[
def if do let quote var fn loop recur throw try catch monitor-enter monitor-exit .
new
] # :nodoc:
CORE_FORMS = %w[
+ - -> ->> .. / * <= < = == >= > accessor aclone add-classpath add-watch
agent agent-error agent-errors aget alength alias all-ns alter alter-meta!
alter-var-root amap ancestors and apply areduce array-map aset aset-boolean
aset-byte aset-char aset-double aset-float aset-int aset-long aset-short
assert assoc assoc! assoc-in associative? atom await await-for bases bean
bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or
bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array
booleans bound-fn bound-fn* bound? butlast byte byte-array bytes case cast char
char-array char-escape-string char-name-string char? chars class class?
clear-agent-errors clojure-version coll? comment commute comp comparator
compare compare-and-set! compile complement concat cond condp conj conj!
cons constantly construct-proxy contains? count counted? create-ns
create-struct cycle dec decimal? declare definline defmacro defmethod defmulti
defn defn- defonce defprotocol defrecord defstruct deftype delay delay?
deliver denominator deref derive descendants disj disj! dissoc dissoc!
distinct distinct? doall doc dorun doseq dosync dotimes doto double
double-array doubles drop drop-last drop-while empty empty? ensure
enumeration-seq error-handler error-mode eval even? every? extend
extend-protocol extend-type extenders extends? false? ffirst file-seq
filter find find-doc find-ns find-var first float float-array float?
floats flush fn fn? fnext for force format future future-call future-cancel
future-cancelled? future-done? future? gen-class gen-interface gensym get
get-in get-method get-proxy-class get-thread-bindings get-validator hash
hash-map hash-set identical? identity if-let if-not ifn? import in-ns
inc init-proxy instance? int int-array integer? interleave intern
interpose into into-array ints io! isa? iterate iterator-seq juxt key
keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list*
list? load load-file load-reader load-string loaded-libs locking long
long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy
map map? mapcat max max-key memfn memoize merge merge-with meta methods
min min-key mod name namespace neg? newline next nfirst nil? nnext not
not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns
ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth
nthnext num number? numerator object-array odd? or parents partial
partition pcalls peek persistent! pmap pop pop! pop-thread-bindings
pos? pr pr-str prefer-method prefers print print-namespace-doc
print-str printf println println-str prn prn-str promise proxy
proxy-mappings proxy-super push-thread-bindings pvalues quot rand
rand-int range ratio? rationalize re-find re-groups re-matcher
re-matches re-pattern re-seq read read-line read-string reduce ref
ref-history-count ref-max-history ref-min-history ref-set refer
refer-clojure reify release-pending-sends rem remove remove-all-methods
remove-method remove-ns remove-watch repeat repeatedly replace replicate
require reset! reset-meta! resolve rest restart-agent resultset-seq
reverse reversible? rseq rsubseq satisfies? second select-keys send
send-off seq seq? seque sequence sequential? set set-error-handler!
set-error-mode! set-validator! set? short short-array shorts
shutdown-agents slurp some sort sort-by sorted-map sorted-map-by
sorted-set sorted-set-by sorted? special-form-anchor special-symbol?
split-at split-with str string? struct struct-map subs subseq subvec
supers swap! symbol symbol? sync syntax-symbol-anchor take take-last
take-nth take-while test the-ns thread-bound? time to-array to-array-2d
trampoline transient tree-seq true? type unchecked-add unchecked-dec
unchecked-divide unchecked-inc unchecked-multiply unchecked-negate
unchecked-remainder unchecked-subtract underive update-in update-proxy
use val vals var-get var-set var? vary-meta vec vector vector-of vector?
when when-first when-let when-not while with-bindings with-bindings*
with-in-str with-local-vars with-meta with-open with-out-str
with-precision xml-seq zero? zipmap
] # :nodoc:
PREDEFINED_CONSTANTS = %w[
true false nil *1 *2 *3 *agent* *clojure-version* *command-line-args*
*compile-files* *compile-path* *e *err* *file* *flush-on-newline*
*in* *ns* *out* *print-dup* *print-length* *print-level* *print-meta*
*print-readably* *read-eval* *warn-on-reflection*
] # :nodoc:
IDENT_KIND = WordList.new(:ident).
add(SPECIAL_FORMS, :keyword).
add(CORE_FORMS, :keyword).
add(PREDEFINED_CONSTANTS, :predefined_constant)
KEYWORD_NEXT_TOKEN_KIND = WordList.new(nil).
add(%w[ def defn defn- definline defmacro defmulti defmethod defstruct defonce declare ], :function).
add(%w[ ns ], :namespace).
add(%w[ defprotocol defrecord ], :class)
BASIC_IDENTIFIER = /[a-zA-Z$%*\/_+!?&<>\-=]=?[a-zA-Z0-9$&*+!\/_?<>\-\#]*/
IDENTIFIER = /(?!-\d)(?:(?:#{BASIC_IDENTIFIER}\.)*#{BASIC_IDENTIFIER}(?:\/#{BASIC_IDENTIFIER})?\.?)|\.\.?/
SYMBOL = /::?#{IDENTIFIER}/o
DIGIT = /\d/
DIGIT10 = DIGIT
DIGIT16 = /[0-9a-f]/i
DIGIT8 = /[0-7]/
DIGIT2 = /[01]/
RADIX16 = /\#x/i
RADIX8 = /\#o/i
RADIX2 = /\#b/i
RADIX10 = /\#d/i
EXACTNESS = /#i|#e/i
SIGN = /[\+-]?/
EXP_MARK = /[esfdl]/i
EXP = /#{EXP_MARK}#{SIGN}#{DIGIT}+/
SUFFIX = /#{EXP}?/
PREFIX10 = /#{RADIX10}?#{EXACTNESS}?|#{EXACTNESS}?#{RADIX10}?/
PREFIX16 = /#{RADIX16}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX16}/
PREFIX8 = /#{RADIX8}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX8}/
PREFIX2 = /#{RADIX2}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX2}/
UINT10 = /#{DIGIT10}+#*/
UINT16 = /#{DIGIT16}+#*/
UINT8 = /#{DIGIT8}+#*/
UINT2 = /#{DIGIT2}+#*/
DECIMAL = /#{DIGIT10}+#+\.#*#{SUFFIX}|#{DIGIT10}+\.#{DIGIT10}*#*#{SUFFIX}|\.#{DIGIT10}+#*#{SUFFIX}|#{UINT10}#{EXP}/
UREAL10 = /#{UINT10}\/#{UINT10}|#{DECIMAL}|#{UINT10}/
UREAL16 = /#{UINT16}\/#{UINT16}|#{UINT16}/
UREAL8 = /#{UINT8}\/#{UINT8}|#{UINT8}/
UREAL2 = /#{UINT2}\/#{UINT2}|#{UINT2}/
REAL10 = /#{SIGN}#{UREAL10}/
REAL16 = /#{SIGN}#{UREAL16}/
REAL8 = /#{SIGN}#{UREAL8}/
REAL2 = /#{SIGN}#{UREAL2}/
IMAG10 = /i|#{UREAL10}i/
IMAG16 = /i|#{UREAL16}i/
IMAG8 = /i|#{UREAL8}i/
IMAG2 = /i|#{UREAL2}i/
COMPLEX10 = /#{REAL10}@#{REAL10}|#{REAL10}\+#{IMAG10}|#{REAL10}-#{IMAG10}|\+#{IMAG10}|-#{IMAG10}|#{REAL10}/
COMPLEX16 = /#{REAL16}@#{REAL16}|#{REAL16}\+#{IMAG16}|#{REAL16}-#{IMAG16}|\+#{IMAG16}|-#{IMAG16}|#{REAL16}/
COMPLEX8 = /#{REAL8}@#{REAL8}|#{REAL8}\+#{IMAG8}|#{REAL8}-#{IMAG8}|\+#{IMAG8}|-#{IMAG8}|#{REAL8}/
COMPLEX2 = /#{REAL2}@#{REAL2}|#{REAL2}\+#{IMAG2}|#{REAL2}-#{IMAG2}|\+#{IMAG2}|-#{IMAG2}|#{REAL2}/
NUM10 = /#{PREFIX10}?#{COMPLEX10}/
NUM16 = /#{PREFIX16}#{COMPLEX16}/
NUM8 = /#{PREFIX8}#{COMPLEX8}/
NUM2 = /#{PREFIX2}#{COMPLEX2}/
NUM = /#{NUM10}|#{NUM16}|#{NUM8}|#{NUM2}/
protected
def scan_tokens encoder, options
state = :initial
kind = nil
until eos?
case state
when :initial
if match = scan(/ \s+ | \\\n | , /x)
encoder.text_token match, :space
elsif match = scan(/['`\(\[\)\]\{\}]|\#[({]|~@?|[@\^]/)
encoder.text_token match, :operator
elsif match = scan(/;.*/)
encoder.text_token match, :comment # TODO: recognize (comment ...) too
elsif match = scan(/\#?\\(?:newline|space|.?)/)
encoder.text_token match, :char
elsif match = scan(/\#[ft]/)
encoder.text_token match, :predefined_constant
elsif match = scan(/#{IDENTIFIER}/o)
kind = IDENT_KIND[match]
encoder.text_token match, kind
if rest? && kind == :keyword
if kind = KEYWORD_NEXT_TOKEN_KIND[match]
encoder.text_token match, :space if match = scan(/\s+/o)
encoder.text_token match, kind if match = scan(/#{IDENTIFIER}/o)
end
end
elsif match = scan(/#{SYMBOL}/o)
encoder.text_token match, :symbol
elsif match = scan(/\./)
encoder.text_token match, :operator
elsif match = scan(/ \# \^ #{IDENTIFIER} /ox)
encoder.text_token match, :type
elsif match = scan(/ (\#)? " /x)
state = self[1] ? :regexp : :string
encoder.begin_group state
encoder.text_token match, :delimiter
elsif match = scan(/#{NUM}/o) and not matched.empty?
encoder.text_token match, match[/[.e\/]/i] ? :float : :integer
else
encoder.text_token getch, :error
end
when :string, :regexp
if match = scan(/[^"\\]+|\\.?/)
encoder.text_token match, :content
elsif match = scan(/"/)
encoder.text_token match, :delimiter
encoder.end_group state
state = :initial
else
raise_inspect "else case \" reached; %p not handled." % peek(1),
encoder, state
end
else
raise 'else case reached'
end
end
if [:string, :regexp].include? state
encoder.end_group state
end
encoder
end
end
end
end coderay-1.1.3/lib/coderay/scanners/cpp.rb 0000664 0000000 0000000 00000015115 13664404461 0020274 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# Scanner for C++.
#
# Aliases: +cplusplus+, c++
class CPlusPlus < Scanner
register_for :cpp
file_extension 'cpp'
title 'C++'
#-- http://www.cppreference.com/wiki/keywords/start
KEYWORDS = [
'and', 'and_eq', 'asm', 'bitand', 'bitor', 'break',
'case', 'catch', 'class', 'compl', 'const_cast',
'continue', 'default', 'delete', 'do', 'dynamic_cast', 'else',
'enum', 'export', 'for', 'goto', 'if', 'namespace', 'new',
'not', 'not_eq', 'or', 'or_eq', 'reinterpret_cast', 'return',
'sizeof', 'static_assert', 'static_cast', 'struct', 'switch',
'template', 'throw', 'try', 'typedef', 'typeid', 'typename', 'union',
'while', 'xor', 'xor_eq',
] # :nodoc:
PREDEFINED_TYPES = [
'bool', 'char', 'char16_t', 'char32_t', 'double', 'float',
'int', 'long', 'short', 'signed', 'unsigned',
'wchar_t', 'string',
] # :nodoc:
PREDEFINED_CONSTANTS = [
'false', 'true',
'EOF', 'NULL', 'nullptr'
] # :nodoc:
PREDEFINED_VARIABLES = [
'this',
] # :nodoc:
DIRECTIVES = [
'alignas', 'alignof', 'auto', 'const', 'constexpr', 'decltype', 'explicit',
'extern', 'final', 'friend', 'inline', 'mutable', 'noexcept', 'operator',
'override', 'private', 'protected', 'public', 'register', 'static',
'thread_local', 'using', 'virtual', 'void', 'volatile',
] # :nodoc:
IDENT_KIND = WordList.new(:ident).
add(KEYWORDS, :keyword).
add(PREDEFINED_TYPES, :predefined_type).
add(PREDEFINED_VARIABLES, :local_variable).
add(DIRECTIVES, :directive).
add(PREDEFINED_CONSTANTS, :predefined_constant) # :nodoc:
ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
protected
def scan_tokens encoder, options
state = :initial
label_expected = true
case_expected = false
label_expected_before_preproc_line = nil
in_preproc_line = false
until eos?
case state
when :initial
if match = scan(/ \s+ | \\\n /x)
if in_preproc_line && match != "\\\n" && match.index(?\n)
in_preproc_line = false
label_expected = label_expected_before_preproc_line
end
encoder.text_token match, :space
elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
encoder.text_token match, :comment
elsif match = scan(/ \# \s* if \s* 0 /x)
match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos?
encoder.text_token match, :comment
elsif match = scan(/ [-+*=<>?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x)
label_expected = match =~ /[;\{\}]/
if case_expected
label_expected = true if match == ':'
case_expected = false
end
encoder.text_token match, :operator
elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
kind = IDENT_KIND[match]
if kind == :ident && label_expected && !in_preproc_line && scan(/:(?!:)/)
kind = :label
match << matched
else
label_expected = false
if kind == :keyword
case match
when 'class'
state = :class_name_expected
when 'case', 'default'
case_expected = true
end
end
end
encoder.text_token match, kind
elsif match = scan(/\$/)
encoder.text_token match, :ident
elsif match = scan(/L?"/)
encoder.begin_group :string
if match[0] == ?L
encoder.text_token match, 'L', :modifier
match = '"'
end
state = :string
encoder.text_token match, :delimiter
elsif match = scan(/#[ \t]*(\w*)/)
encoder.text_token match, :preprocessor
in_preproc_line = true
label_expected_before_preproc_line = label_expected
state = :include_expected if self[1] == 'include'
elsif match = scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox)
label_expected = false
encoder.text_token match, :char
elsif match = scan(/0[xX][0-9A-Fa-f]+/)
label_expected = false
encoder.text_token match, :hex
elsif match = scan(/(?:0[0-7]+)(?![89.eEfF])/)
label_expected = false
encoder.text_token match, :octal
elsif match = scan(/(?:\d+)(?![.eEfF])L?L?/)
label_expected = false
encoder.text_token match, :integer
elsif match = scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/)
label_expected = false
encoder.text_token match, :float
else
encoder.text_token getch, :error
end
when :string
if match = scan(/[^\\"]+/)
encoder.text_token match, :content
elsif match = scan(/"/)
encoder.text_token match, :delimiter
encoder.end_group :string
state = :initial
label_expected = false
elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
encoder.text_token match, :char
elsif match = scan(/ \\ | $ /x)
encoder.end_group :string
encoder.text_token match, :error unless match.empty?
state = :initial
label_expected = false
else
raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
end
when :include_expected
if match = scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/)
encoder.text_token match, :include
state = :initial
elsif match = scan(/\s+/)
encoder.text_token match, :space
state = :initial if match.index ?\n
else
state = :initial
end
when :class_name_expected
if match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
encoder.text_token match, :class
state = :initial
elsif match = scan(/\s+/)
encoder.text_token match, :space
else
encoder.text_token getch, :error
state = :initial
end
else
raise_inspect 'Unknown state', encoder
end
end
if state == :string
encoder.end_group :string
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/css.rb 0000664 0000000 0000000 00000013575 13664404461 0020312 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
class CSS < Scanner
register_for :css
KINDS_NOT_LOC = [
:comment,
:class, :pseudo_class, :tag,
:id, :directive,
:key, :value, :operator, :color, :float, :string,
:error, :important, :type,
] # :nodoc:
module RE # :nodoc:
Hex = /[0-9a-fA-F]/
Unicode = /\\#{Hex}{1,6}\b/ # differs from standard because it allows uppercase hex too
Escape = /#{Unicode}|\\[^\n0-9a-fA-F]/
NMChar = /[-_a-zA-Z0-9]/
NMStart = /[_a-zA-Z]/
String1 = /"(?:[^\n\\"]+|\\\n|#{Escape})*"?/ # TODO: buggy regexp
String2 = /'(?:[^\n\\']+|\\\n|#{Escape})*'?/ # TODO: buggy regexp
String = /#{String1}|#{String2}/
HexColor = /#(?:#{Hex}{6}|#{Hex}{3})/
Num = /-?(?:[0-9]*\.[0-9]+|[0-9]+)n?/
Name = /#{NMChar}+/
Ident = /-?#{NMStart}#{NMChar}*/
AtKeyword = /@#{Ident}/
Percentage = /#{Num}%/
reldimensions = %w[em ex px]
absdimensions = %w[in cm mm pt pc]
Unit = Regexp.union(*(reldimensions + absdimensions + %w[s dpi dppx deg]))
Dimension = /#{Num}#{Unit}/
Function = /(?:url|alpha|attr|counters?)\((?:[^)\n]|\\\))*\)?/
Id = /(?!#{HexColor}\b(?!-))##{Name}/
Class = /\.#{Name}/
PseudoClass = /::?#{Ident}/
AttributeSelector = /\[[^\]]*\]?/
end
protected
def setup
@state = :initial
@value_expected = false
end
def scan_tokens encoder, options
states = Array(options[:state] || @state).dup
value_expected = @value_expected
until eos?
if match = scan(/\s+/)
encoder.text_token match, :space
elsif case states.last
when :initial, :media
if match = scan(/(?>#{RE::Ident})(?!\()|\*/ox)
encoder.text_token match, :tag
next
elsif match = scan(RE::Class)
encoder.text_token match, :class
next
elsif match = scan(RE::Id)
encoder.text_token match, :id
next
elsif match = scan(RE::PseudoClass)
encoder.text_token match, :pseudo_class
next
elsif match = scan(RE::AttributeSelector)
# TODO: Improve highlighting inside of attribute selectors.
encoder.text_token match[0,1], :operator
encoder.text_token match[1..-2], :attribute_name if match.size > 2
encoder.text_token match[-1,1], :operator if match[-1] == ?]
next
elsif match = scan(/@media/)
encoder.text_token match, :directive
states.push :media_before_name
next
end
when :block
if match = scan(/(?>#{RE::Ident})(?!\()/ox)
if value_expected
encoder.text_token match, :value
else
encoder.text_token match, :key
end
next
end
when :media_before_name
if match = scan(RE::Ident)
encoder.text_token match, :type
states[-1] = :media_after_name
next
end
when :media_after_name
if match = scan(/\{/)
encoder.text_token match, :operator
states[-1] = :media
next
end
else
#:nocov:
raise_inspect 'Unknown state', encoder
#:nocov:
end
elsif match = scan(/\/\*(?:.*?\*\/|\z)/m)
encoder.text_token match, :comment
elsif match = scan(/\{/)
value_expected = false
encoder.text_token match, :operator
states.push :block
elsif match = scan(/\}/)
value_expected = false
encoder.text_token match, :operator
if states.last == :block || states.last == :media
states.pop
end
elsif match = scan(/#{RE::String}/o)
encoder.begin_group :string
encoder.text_token match[0, 1], :delimiter
encoder.text_token match[1..-2], :content if match.size > 2
encoder.text_token match[-1, 1], :delimiter if match.size >= 2
encoder.end_group :string
elsif match = scan(/#{RE::Function}/o)
encoder.begin_group :function
start = match[/^\w+\(/]
encoder.text_token start, :delimiter
if match[-1] == ?)
encoder.text_token match[start.size..-2], :content if match.size > start.size + 1
encoder.text_token ')', :delimiter
else
encoder.text_token match[start.size..-1], :content if match.size > start.size
end
encoder.end_group :function
elsif match = scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox)
encoder.text_token match, :float
elsif match = scan(/#{RE::HexColor}/o)
encoder.text_token match, :color
elsif match = scan(/! *important/)
encoder.text_token match, :important
elsif match = scan(/(?:rgb|hsl)a?\([^()\n]*\)?/)
encoder.text_token match, :color
elsif match = scan(RE::AtKeyword)
encoder.text_token match, :directive
elsif match = scan(/ [+>~:;,.=()\/] /x)
if match == ':'
value_expected = true
elsif match == ';'
value_expected = false
end
encoder.text_token match, :operator
else
encoder.text_token getch, :error
end
end
if options[:keep_state]
@state = states
@value_expected = value_expected
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/debug.rb 0000664 0000000 0000000 00000003372 13664404461 0020602 0 ustar 00root root 0000000 0000000 require 'set'
module CodeRay
module Scanners
# = Debug Scanner
#
# Interprets the output of the Encoders::Debug encoder (basically the inverse function).
class Debug < Scanner
register_for :debug
title 'CodeRay Token Dump Import'
protected
def setup
super
@known_token_kinds = TokenKinds.keys.map(&:to_s).to_set
end
def scan_tokens encoder, options
opened_tokens = []
until eos?
if match = scan(/\s+/)
encoder.text_token match, :space
elsif match = scan(/ (\w+) \( ( [^\)\\]* ( \\. [^\)\\]* )* ) \)? /x)
if @known_token_kinds.include? self[1]
encoder.text_token self[2].gsub(/\\(.)/m, '\1'), self[1].to_sym
else
encoder.text_token matched, :unknown
end
elsif match = scan(/ (\w+) ([<\[]) /x)
if @known_token_kinds.include? self[1]
kind = self[1].to_sym
else
kind = :unknown
end
opened_tokens << kind
case self[2]
when '<'
encoder.begin_group kind
when '['
encoder.begin_line kind
else
raise 'CodeRay bug: This case should not be reached.'
end
elsif !opened_tokens.empty? && match = scan(/ > /x)
encoder.end_group opened_tokens.pop
elsif !opened_tokens.empty? && match = scan(/ \] /x)
encoder.end_line opened_tokens.pop
else
encoder.text_token getch, :space
end
end
encoder.end_group opened_tokens.pop until opened_tokens.empty?
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/delphi.rb 0000664 0000000 0000000 00000011207 13664404461 0020755 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# Scanner for the Delphi language (Object Pascal).
#
# Alias: +pascal+
class Delphi < Scanner
register_for :delphi
file_extension 'pas'
KEYWORDS = [
'and', 'array', 'as', 'at', 'asm', 'at', 'begin', 'case', 'class',
'const', 'constructor', 'destructor', 'dispinterface', 'div', 'do',
'downto', 'else', 'end', 'except', 'exports', 'file', 'finalization',
'finally', 'for', 'function', 'goto', 'if', 'implementation', 'in',
'inherited', 'initialization', 'inline', 'interface', 'is', 'label',
'library', 'mod', 'nil', 'not', 'object', 'of', 'or', 'out', 'packed',
'procedure', 'program', 'property', 'raise', 'record', 'repeat',
'resourcestring', 'set', 'shl', 'shr', 'string', 'then', 'threadvar',
'to', 'try', 'type', 'unit', 'until', 'uses', 'var', 'while', 'with',
'xor', 'on',
] # :nodoc:
DIRECTIVES = [
'absolute', 'abstract', 'assembler', 'at', 'automated', 'cdecl',
'contains', 'deprecated', 'dispid', 'dynamic', 'export',
'external', 'far', 'forward', 'implements', 'local',
'near', 'nodefault', 'on', 'overload', 'override',
'package', 'pascal', 'platform', 'private', 'protected', 'public',
'published', 'read', 'readonly', 'register', 'reintroduce',
'requires', 'resident', 'safecall', 'stdcall', 'stored', 'varargs',
'virtual', 'write', 'writeonly',
] # :nodoc:
IDENT_KIND = WordList::CaseIgnoring.new(:ident).
add(KEYWORDS, :keyword).
add(DIRECTIVES, :directive) # :nodoc:
NAME_FOLLOWS = WordList::CaseIgnoring.new(false).
add(%w(procedure function .)) # :nodoc:
protected
def scan_tokens encoder, options
state = :initial
last_token = ''
until eos?
if state == :initial
if match = scan(/ \s+ /x)
encoder.text_token match, :space
next
elsif match = scan(%r! \{ \$ [^}]* \}? | \(\* \$ (?: .*? \*\) | .* ) !mx)
encoder.text_token match, :preprocessor
next
elsif match = scan(%r! // [^\n]* | \{ [^}]* \}? | \(\* (?: .*? \*\) | .* ) !mx)
encoder.text_token match, :comment
next
elsif match = scan(/ <[>=]? | >=? | :=? | [-+=*\/;,@\^|\(\)\[\]] | \.\. /x)
encoder.text_token match, :operator
elsif match = scan(/\./)
encoder.text_token match, :operator
next if last_token == 'end'
elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
encoder.text_token match, NAME_FOLLOWS[last_token] ? :ident : IDENT_KIND[match]
elsif match = skip(/ ' ( [^\n']|'' ) (?:'|$) /x)
encoder.begin_group :char
encoder.text_token "'", :delimiter
encoder.text_token self[1], :content
encoder.text_token "'", :delimiter
encoder.end_group :char
next
elsif match = scan(/ ' /x)
encoder.begin_group :string
encoder.text_token match, :delimiter
state = :string
elsif match = scan(/ \# (?: \d+ | \$[0-9A-Fa-f]+ ) /x)
encoder.text_token match, :char
elsif match = scan(/ \$ [0-9A-Fa-f]+ /x)
encoder.text_token match, :hex
elsif match = scan(/ (?: \d+ ) (?![eE]|\.[^.]) /x)
encoder.text_token match, :integer
elsif match = scan(/ \d+ (?: \.\d+ (?: [eE][+-]? \d+ )? | [eE][+-]? \d+ ) /x)
encoder.text_token match, :float
else
encoder.text_token getch, :error
next
end
elsif state == :string
if match = scan(/[^\n']+/)
encoder.text_token match, :content
elsif match = scan(/''/)
encoder.text_token match, :char
elsif match = scan(/'/)
encoder.text_token match, :delimiter
encoder.end_group :string
state = :initial
next
elsif match = scan(/\n/)
encoder.end_group :string
encoder.text_token match, :space
state = :initial
else
raise "else case \' reached; %p not handled." % peek(1), encoder
end
else
raise 'else-case reached', encoder
end
last_token = match
end
if state == :string
encoder.end_group state
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/diff.rb 0000664 0000000 0000000 00000017722 13664404461 0020430 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# Scanner for output of the diff command.
#
# Alias: +patch+
class Diff < Scanner
register_for :diff
title 'diff output'
DEFAULT_OPTIONS = {
:highlight_code => true,
:inline_diff => true,
}
protected
def scan_tokens encoder, options
line_kind = nil
state = :initial
deleted_lines_count = 0
scanners = Hash.new do |h, lang|
h[lang] = Scanners[lang].new '', :keep_tokens => true, :keep_state => true
end
content_scanner = scanners[:plain]
content_scanner_entry_state = nil
until eos?
if match = scan(/\n/)
deleted_lines_count = 0 unless line_kind == :delete
if line_kind
encoder.end_line line_kind
line_kind = nil
end
encoder.text_token match, :space
next
end
case state
when :initial
if match = scan(/--- |\+\+\+ |=+|_+/)
encoder.begin_line line_kind = :head
encoder.text_token match, :head
if match = scan(/[^\x00\n]+?(?=$|[\t\n]| \(revision)/)
encoder.text_token match, :filename
if options[:highlight_code] && match != '/dev/null'
file_type = CodeRay::FileType.fetch(match, :text)
file_type = :text if file_type == :diff
content_scanner = scanners[file_type]
content_scanner_entry_state = nil
end
end
next unless match = scan(/.+/)
encoder.text_token match, :plain
elsif match = scan(/Index: |Property changes on: /)
encoder.begin_line line_kind = :head
encoder.text_token match, :head
next unless match = scan(/.+/)
encoder.text_token match, :plain
elsif match = scan(/Added: /)
encoder.begin_line line_kind = :head
encoder.text_token match, :head
next unless match = scan(/.+/)
encoder.text_token match, :plain
state = :added
elsif match = scan(/\\ .*/)
encoder.text_token match, :comment
elsif match = scan(/@@(?>[^@\n]+)@@/)
content_scanner.state = :initial unless match?(/\n\+/)
content_scanner_entry_state = nil
if check(/\n|$/)
encoder.begin_line line_kind = :change
else
encoder.begin_group :change
end
encoder.text_token match[0,2], :change
encoder.text_token match[2...-2], :plain
encoder.text_token match[-2,2], :change
encoder.end_group :change unless line_kind
next unless match = scan(/.+/)
if options[:highlight_code]
content_scanner.tokenize match, :tokens => encoder
else
encoder.text_token match, :plain
end
next
elsif match = scan(/\+/)
encoder.begin_line line_kind = :insert
encoder.text_token match, :insert
next unless match = scan(/.+/)
if options[:highlight_code]
content_scanner.tokenize match, :tokens => encoder
else
encoder.text_token match, :plain
end
next
elsif match = scan(/-/)
deleted_lines_count += 1
if options[:inline_diff] && deleted_lines_count == 1 && (changed_lines_count = 1 + check(/.*(?:\n\-.*)*/).count("\n")) && changed_lines_count <= 100_000 && match?(/(?>.*(?:\n\-.*){#{changed_lines_count - 1}}(?:\n\+.*){#{changed_lines_count}})$(?!\n\+)/)
deleted_lines = Array.new(changed_lines_count) { |i| skip(/\n\-/) if i > 0; scan(/.*/) }
inserted_lines = Array.new(changed_lines_count) { |i| skip(/\n\+/) ; scan(/.*/) }
deleted_lines_tokenized = []
inserted_lines_tokenized = []
for deleted_line, inserted_line in deleted_lines.zip(inserted_lines)
pre, deleted_part, inserted_part, post = diff deleted_line, inserted_line
content_scanner_entry_state = content_scanner.state
deleted_lines_tokenized << content_scanner.tokenize([pre, deleted_part, post], :tokens => Tokens.new)
content_scanner.state = content_scanner_entry_state || :initial
inserted_lines_tokenized << content_scanner.tokenize([pre, inserted_part, post], :tokens => Tokens.new)
end
for pre, deleted_part, post in deleted_lines_tokenized
encoder.begin_line :delete
encoder.text_token '-', :delete
encoder.tokens pre
unless deleted_part.empty?
encoder.begin_group :eyecatcher
encoder.tokens deleted_part
encoder.end_group :eyecatcher
end
encoder.tokens post
encoder.end_line :delete
encoder.text_token "\n", :space
end
for pre, inserted_part, post in inserted_lines_tokenized
encoder.begin_line :insert
encoder.text_token '+', :insert
encoder.tokens pre
unless inserted_part.empty?
encoder.begin_group :eyecatcher
encoder.tokens inserted_part
encoder.end_group :eyecatcher
end
encoder.tokens post
changed_lines_count -= 1
if changed_lines_count > 0
encoder.end_line :insert
encoder.text_token "\n", :space
end
end
line_kind = :insert
elsif match = scan(/.*/)
encoder.begin_line line_kind = :delete
encoder.text_token '-', :delete
if options[:highlight_code]
if deleted_lines_count == 1
content_scanner_entry_state = content_scanner.state
end
content_scanner.tokenize match, :tokens => encoder unless match.empty?
if !match?(/\n-/)
if match?(/\n\+/)
content_scanner.state = content_scanner_entry_state || :initial
end
content_scanner_entry_state = nil
end
else
encoder.text_token match, :plain
end
end
next
elsif match = scan(/ .*/)
if options[:highlight_code]
content_scanner.tokenize match, :tokens => encoder
else
encoder.text_token match, :plain
end
next
elsif match = scan(/.+/)
encoder.begin_line line_kind = :comment
encoder.text_token match, :plain
else
raise_inspect 'else case rached'
end
when :added
if match = scan(/ \+/)
encoder.begin_line line_kind = :insert
encoder.text_token match, :insert
next unless match = scan(/.+/)
encoder.text_token match, :plain
else
state = :initial
next
end
end
end
encoder.end_line line_kind if line_kind
encoder
end
private
def diff a, b
# i will be the index of the leftmost difference from the left.
i_max = [a.size, b.size].min
i = 0
i += 1 while i < i_max && a[i] == b[i]
# j_min will be the index of the leftmost difference from the right.
j_min = i - i_max
# j will be the index of the rightmost difference from the right which
# does not precede the leftmost one from the left.
j = -1
j -= 1 while j >= j_min && a[j] == b[j]
return a[0...i], a[i..j], b[i..j], (j < -1) ? a[j + 1..-1] : ''
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/erb.rb 0000664 0000000 0000000 00000003416 13664404461 0020263 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
load :html
load :ruby
# Scanner for HTML ERB templates.
class ERB < Scanner
register_for :erb
title 'HTML ERB Template'
KINDS_NOT_LOC = HTML::KINDS_NOT_LOC
ERB_RUBY_BLOCK = /
(<%(?!%)[-=\#]?)
((?>
[^\-%]* # normal*
(?> # special
(?: %(?!>) | -(?!%>) )
[^\-%]* # normal*
)*
))
((?: -?%> )?)
/x # :nodoc:
START_OF_ERB = /
<%(?!%)
/x # :nodoc:
protected
def setup
@ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true
@html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true, :keep_state => true
end
def reset_instance
super
@html_scanner.reset
end
def scan_tokens encoder, options
until eos?
if (match = scan_until(/(?=#{START_OF_ERB})/o) || scan_rest) and not match.empty?
@html_scanner.tokenize match, :tokens => encoder
elsif match = scan(/#{ERB_RUBY_BLOCK}/o)
start_tag = self[1]
code = self[2]
end_tag = self[3]
encoder.begin_group :inline
encoder.text_token start_tag, :inline_delimiter
if start_tag == '<%#'
encoder.text_token code, :comment
else
@ruby_scanner.tokenize code, :tokens => encoder
end unless code.empty?
encoder.text_token end_tag, :inline_delimiter unless end_tag.empty?
encoder.end_group :inline
else
raise_inspect 'else-case reached!', encoder
end
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/go.rb 0000664 0000000 0000000 00000015000 13664404461 0020110 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
class Go < Scanner
register_for :go
file_extension 'go'
# http://golang.org/ref/spec#Keywords
KEYWORDS = [
'break', 'default', 'func', 'interface', 'select',
'case', 'defer', 'go', 'map', 'struct',
'chan', 'else', 'goto', 'package', 'switch',
'const', 'fallthrough', 'if', 'range', 'type',
'continue', 'for', 'import', 'return', 'var',
] # :nodoc:
# http://golang.org/ref/spec#Types
PREDEFINED_TYPES = [
'bool',
'uint8', 'uint16', 'uint32', 'uint64',
'int8', 'int16', 'int32', 'int64',
'float32', 'float64',
'complex64', 'complex128',
'byte', 'rune', 'string', 'error',
'uint', 'int', 'uintptr',
] # :nodoc:
PREDEFINED_CONSTANTS = [
'nil', 'iota',
'true', 'false',
] # :nodoc:
PREDEFINED_FUNCTIONS = %w[
append cap close complex copy delete imag len
make new panic print println real recover
] # :nodoc:
IDENT_KIND = WordList.new(:ident).
add(KEYWORDS, :keyword).
add(PREDEFINED_TYPES, :predefined_type).
add(PREDEFINED_CONSTANTS, :predefined_constant).
add(PREDEFINED_FUNCTIONS, :predefined) # :nodoc:
ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
protected
def scan_tokens encoder, options
state = :initial
label_expected = true
case_expected = false
label_expected_before_preproc_line = nil
in_preproc_line = false
until eos?
case state
when :initial
if match = scan(/ \s+ | \\\n /x)
if in_preproc_line && match != "\\\n" && match.index(?\n)
in_preproc_line = false
case_expected = false
label_expected = label_expected_before_preproc_line
end
encoder.text_token match, :space
elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
encoder.text_token match, :comment
elsif match = scan(/ - (?![\d.]) | [+*=<>?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x)
if case_expected
label_expected = true if match == ':'
case_expected = false
end
encoder.text_token match, :operator
elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
kind = IDENT_KIND[match]
if kind == :ident && label_expected && !in_preproc_line && scan(/:(?!:)/)
kind = :label
label_expected = false
match << matched
else
label_expected = false
if kind == :keyword
case match
when 'case', 'default'
case_expected = true
end
end
end
encoder.text_token match, kind
elsif match = scan(/L?"/)
encoder.begin_group :string
if match[0] == ?L
encoder.text_token 'L', :modifier
match = '"'
end
encoder.text_token match, :delimiter
state = :string
elsif match = scan(/ ` ([^`]+)? (`)? /x)
encoder.begin_group :shell
encoder.text_token '`', :delimiter
encoder.text_token self[1], :content if self[1]
encoder.text_token self[2], :delimiter if self[2]
encoder.end_group :shell
elsif match = scan(/ \# \s* if \s* 0 /x)
match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos?
encoder.text_token match, :comment
elsif match = scan(/#[ \t]*(\w*)/)
encoder.text_token match, :preprocessor
in_preproc_line = true
label_expected_before_preproc_line = label_expected
state = :include_expected if self[1] == 'include'
elsif match = scan(/ L?' (?: [^\'\n\\] | \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) )? '? /ox)
label_expected = false
encoder.text_token match, :char
elsif match = scan(/\$/)
encoder.text_token match, :ident
elsif match = scan(/-?\d*(\.\d*)?([eE][+-]?\d+)?i/)
label_expected = false
encoder.text_token match, :imaginary
elsif match = scan(/-?0[xX][0-9A-Fa-f]+/)
label_expected = false
encoder.text_token match, :hex
elsif match = scan(/-?(?:0[0-7]+)(?![89.eEfF])/)
label_expected = false
encoder.text_token match, :octal
elsif match = scan(/-?(?:\d*\.\d+|\d+\.)(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+/)
label_expected = false
encoder.text_token match, :float
elsif match = scan(/-?(?:\d+)(?![.eEfF])L?L?/)
label_expected = false
encoder.text_token match, :integer
else
encoder.text_token getch, :error
end
when :string
if match = scan(/[^\\\n"]+/)
encoder.text_token match, :content
elsif match = scan(/"/)
encoder.text_token match, :delimiter
encoder.end_group :string
state = :initial
label_expected = false
elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
encoder.text_token match, :char
elsif match = scan(/ \\ /x)
encoder.text_token match, :error
elsif match = scan(/$/)
encoder.end_group :string
state = :initial
label_expected = false
else
raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
end
when :include_expected
if match = scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/)
encoder.text_token match, :include
state = :initial
elsif match = scan(/\s+/)
encoder.text_token match, :space
state = :initial if match.index ?\n
else
state = :initial
end
else
raise_inspect 'Unknown state', encoder
end
end
if state == :string
encoder.end_group :string
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/groovy.rb 0000664 0000000 0000000 00000022566 13664404461 0021047 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
load :java
# Scanner for Groovy.
class Groovy < Java
register_for :groovy
# TODO: check list of keywords
GROOVY_KEYWORDS = %w[
as assert def in
] # :nodoc:
KEYWORDS_EXPECTING_VALUE = WordList.new.add %w[
case instanceof new return throw typeof while as assert in
] # :nodoc:
GROOVY_MAGIC_VARIABLES = %w[ it ] # :nodoc:
IDENT_KIND = Java::IDENT_KIND.dup.
add(GROOVY_KEYWORDS, :keyword).
add(GROOVY_MAGIC_VARIABLES, :local_variable) # :nodoc:
ESCAPE = / [bfnrtv$\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x # :nodoc: no 4-byte unicode chars? U[a-fA-F0-9]{8}
REGEXP_ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} | \d | [bBdDsSwW\/] /x # :nodoc:
# TODO: interpretation inside ', ", /
STRING_CONTENT_PATTERN = {
"'" => /(?>\\[^\\'\n]+|[^\\'\n]+)+/,
'"' => /[^\\$"\n]+/,
"'''" => /(?>[^\\']+|'(?!''))+/,
'"""' => /(?>[^\\$"]+|"(?!""))+/,
'/' => /[^\\$\/\n]+/,
} # :nodoc:
protected
def setup
@state = :initial
end
def scan_tokens encoder, options
state = options[:state] || @state
inline_block_stack = []
inline_block_paren_depth = nil
string_delimiter = nil
import_clause = class_name_follows = last_token = after_def = false
value_expected = true
until eos?
case state
when :initial
if match = scan(/ \s+ | \\\n /x)
encoder.text_token match, :space
if match.index ?\n
import_clause = after_def = false
value_expected = true unless value_expected
end
next
elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
value_expected = true
after_def = false
encoder.text_token match, :comment
elsif bol? && match = scan(/ \#!.* /x)
encoder.text_token match, :doctype
elsif import_clause && match = scan(/ (?!as) #{IDENT} (?: \. #{IDENT} )* (?: \.\* )? /ox)
after_def = value_expected = false
encoder.text_token match, :include
elsif match = scan(/ #{IDENT} | \[\] /ox)
kind = IDENT_KIND[match]
value_expected = (kind == :keyword) && KEYWORDS_EXPECTING_VALUE[match]
if last_token == '.'
kind = :ident
elsif class_name_follows
kind = :class
class_name_follows = false
elsif after_def && check(/\s*[({]/)
kind = :method
after_def = false
elsif kind == :ident && last_token != '?' && check(/:/)
kind = :key
else
class_name_follows = true if match == 'class' || (import_clause && match == 'as')
import_clause = match == 'import'
after_def = true if match == 'def'
end
encoder.text_token match, kind
elsif match = scan(/;/)
import_clause = after_def = false
value_expected = true
encoder.text_token match, :operator
elsif match = scan(/\{/)
class_name_follows = after_def = false
value_expected = true
encoder.text_token match, :operator
if !inline_block_stack.empty?
inline_block_paren_depth += 1
end
# TODO: ~'...', ~"..." and ~/.../ style regexps
elsif match = scan(/ \.\. | \*?\.(?!\d)@? | \.& | \?:? | [,?:(\[] | -[->] | \+\+ |
&& | \|\| | \*\*=? | ==?~ | <=?>? | [-+*%^~&|>=!]=? | <<=? | >>>?=? /x)
value_expected = true
value_expected = :regexp if match == '~'
after_def = false
encoder.text_token match, :operator
elsif match = scan(/ [)\]}] /x)
value_expected = after_def = false
if !inline_block_stack.empty? && match == '}'
inline_block_paren_depth -= 1
if inline_block_paren_depth == 0 # closing brace of inline block reached
encoder.text_token match, :inline_delimiter
encoder.end_group :inline
state, string_delimiter, inline_block_paren_depth = inline_block_stack.pop
next
end
end
encoder.text_token match, :operator
elsif check(/[\d.]/)
after_def = value_expected = false
if match = scan(/0[xX][0-9A-Fa-f]+/)
encoder.text_token match, :hex
elsif match = scan(/(?>0[0-7]+)(?![89.eEfF])/)
encoder.text_token match, :octal
elsif match = scan(/\d+[fFdD]|\d*\.\d+(?:[eE][+-]?\d+)?[fFdD]?|\d+[eE][+-]?\d+[fFdD]?/)
encoder.text_token match, :float
elsif match = scan(/\d+[lLgG]?/)
encoder.text_token match, :integer
end
elsif match = scan(/'''|"""/)
after_def = value_expected = false
state = :multiline_string
encoder.begin_group :string
string_delimiter = match
encoder.text_token match, :delimiter
# TODO: record.'name' syntax
elsif match = scan(/["']/)
after_def = value_expected = false
state = match == '/' ? :regexp : :string
encoder.begin_group state
string_delimiter = match
encoder.text_token match, :delimiter
elsif value_expected && match = scan(/\//)
after_def = value_expected = false
encoder.begin_group :regexp
state = :regexp
string_delimiter = '/'
encoder.text_token match, :delimiter
elsif match = scan(/ @ #{IDENT} /ox)
after_def = value_expected = false
encoder.text_token match, :annotation
elsif match = scan(/\//)
after_def = false
value_expected = true
encoder.text_token match, :operator
else
encoder.text_token getch, :error
end
when :string, :regexp, :multiline_string
if match = scan(STRING_CONTENT_PATTERN[string_delimiter])
encoder.text_token match, :content
elsif match = scan(state == :multiline_string ? /'''|"""/ : /["'\/]/)
encoder.text_token match, :delimiter
if state == :regexp
# TODO: regexp modifiers? s, m, x, i?
modifiers = scan(/[ix]+/)
encoder.text_token modifiers, :modifier if modifiers && !modifiers.empty?
end
state = :string if state == :multiline_string
encoder.end_group state
string_delimiter = nil
after_def = value_expected = false
state = :initial
next
elsif (state == :string || state == :multiline_string) &&
(match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox))
if string_delimiter[0] == ?' && !(match == "\\\\" || match == "\\'")
encoder.text_token match, :content
else
encoder.text_token match, :char
end
elsif state == :regexp && match = scan(/ \\ (?: #{REGEXP_ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
encoder.text_token match, :char
elsif match = scan(/ \$ #{IDENT} /mox)
encoder.begin_group :inline
encoder.text_token '$', :inline_delimiter
match = match[1..-1]
encoder.text_token match, IDENT_KIND[match]
encoder.end_group :inline
next
elsif match = scan(/ \$ \{ /x)
encoder.begin_group :inline
encoder.text_token match, :inline_delimiter
inline_block_stack << [state, string_delimiter, inline_block_paren_depth]
inline_block_paren_depth = 1
state = :initial
next
elsif match = scan(/ \$ /mx)
encoder.text_token match, :content
elsif match = scan(/ \\. /mx)
encoder.text_token match, :content # TODO: Shouldn't this be :error?
elsif match = scan(/ \\ | \n /x)
encoder.end_group state == :regexp ? :regexp : :string
encoder.text_token match, :error
after_def = value_expected = false
state = :initial
else
raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
end
else
raise_inspect 'Unknown state', encoder
end
last_token = match unless [:space, :comment, :doctype].include? kind
end
if [:multiline_string, :string, :regexp].include? state
encoder.end_group state == :regexp ? :regexp : :string
end
if options[:keep_state]
@state = state
end
until inline_block_stack.empty?
state, = *inline_block_stack.pop
encoder.end_group :inline
encoder.end_group state == :regexp ? :regexp : :string
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/haml.rb 0000664 0000000 0000000 00000012074 13664404461 0020434 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
load :ruby
load :html
load :java_script
class HAML < Scanner
register_for :haml
title 'HAML Template'
KINDS_NOT_LOC = HTML::KINDS_NOT_LOC
protected
def setup
super
@ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true
@embedded_ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true, :state => @ruby_scanner.interpreted_string_state
@html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true
end
def scan_tokens encoder, options
match = nil
code = ''
until eos?
if bol?
if match = scan(/!!!.*/)
encoder.text_token match, :doctype
next
end
if match = scan(/(?>( *)(\/(?!\[if)|-\#|:javascript|:ruby|:\w+) *)(?=\n)/)
encoder.text_token match, :comment
code = self[2]
if match = scan(/(?:\n+#{self[1]} .*)+/)
case code
when '/', '-#'
encoder.text_token match, :comment
when ':javascript'
# TODO: recognize #{...} snippets inside JavaScript
@java_script_scanner ||= CodeRay.scanner :java_script, :tokens => @tokens, :keep_tokens => true
@java_script_scanner.tokenize match, :tokens => encoder
when ':ruby'
@ruby_scanner.tokenize match, :tokens => encoder
when /:\w+/
encoder.text_token match, :comment
else
raise 'else-case reached: %p' % [code]
end
end
end
if match = scan(/ +/)
encoder.text_token match, :space
end
if match = scan(/\/.*/)
encoder.text_token match, :comment
next
end
if match = scan(/\\/)
encoder.text_token match, :plain
if match = scan(/.+/)
@html_scanner.tokenize match, :tokens => encoder
end
next
end
tag = false
if match = scan(/%[-\w:]+\/?/)
encoder.text_token match, :tag
# if match = scan(/( +)(.+)/)
# encoder.text_token self[1], :space
# @embedded_ruby_scanner.tokenize self[2], :tokens => encoder
# end
tag = true
end
while match = scan(/([.#])[-\w]*\w/)
encoder.text_token match, self[1] == '#' ? :constant : :class
tag = true
end
if tag && match = scan(/(\()([^)]+)?(\))?/)
# TODO: recognize title=@title, class="widget_#{@widget.number}"
encoder.text_token self[1], :plain
@html_scanner.tokenize self[2], :tokens => encoder, :state => :attribute if self[2]
encoder.text_token self[3], :plain if self[3]
end
if tag && match = scan(/\{/)
encoder.text_token match, :plain
code = ''
level = 1
while true
code << scan(/([^\{\},\n]|, *\n?)*/)
case match = getch
when '{'
level += 1
code << match
when '}'
level -= 1
if level > 0
code << match
else
break
end
when "\n", ",", nil
break
end
end
@ruby_scanner.tokenize code, :tokens => encoder unless code.empty?
encoder.text_token match, :plain if match
end
if tag && match = scan(/(\[)([^\]\n]+)?(\])?/)
encoder.text_token self[1], :plain
@ruby_scanner.tokenize self[2], :tokens => encoder if self[2]
encoder.text_token self[3], :plain if self[3]
end
if tag && match = scan(/\//)
encoder.text_token match, :tag
end
if scan(/(>?[-=]|[&!]=|(& |!)|~)( *)([^,\n\|]+(?:(, *|\|(?=.|\n.*\|$))\n?[^,\n\|]*)*)?/)
encoder.text_token self[1] + self[3], :plain
if self[4]
if self[2]
@embedded_ruby_scanner.tokenize self[4], :tokens => encoder
else
@ruby_scanner.tokenize self[4], :tokens => encoder
end
end
elsif match = scan(/((?:<|>)(?![!?\/\w]))?(.+)?/)
encoder.text_token self[1], :plain if self[1]
# TODO: recognize #{...} snippets
@html_scanner.tokenize self[2], :tokens => encoder if self[2]
end
elsif match = scan(/.+/)
@html_scanner.tokenize match, :tokens => encoder
end
if match = scan(/\n/)
encoder.text_token match, :space
end
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/html.rb 0000664 0000000 0000000 00000021277 13664404461 0020464 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# HTML Scanner
#
# Alias: +xhtml+
#
# See also: Scanners::XML
class HTML < Scanner
register_for :html
KINDS_NOT_LOC = [
:comment, :doctype, :preprocessor,
:tag, :attribute_name, :operator,
:attribute_value, :string,
:plain, :entity, :error,
] # :nodoc:
EVENT_ATTRIBUTES = %w(
onabort onafterprint onbeforeprint onbeforeunload onblur oncanplay
oncanplaythrough onchange onclick oncontextmenu oncuechange ondblclick
ondrag ondragdrop ondragend ondragenter ondragleave ondragover
ondragstart ondrop ondurationchange onemptied onended onerror onfocus
onformchange onforminput onhashchange oninput oninvalid onkeydown
onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart
onmessage onmousedown onmousemove onmouseout onmouseover onmouseup
onmousewheel onmove onoffline ononline onpagehide onpageshow onpause
onplay onplaying onpopstate onprogress onratechange onreadystatechange
onredo onreset onresize onscroll onseeked onseeking onselect onshow
onstalled onstorage onsubmit onsuspend ontimeupdate onundo onunload
onvolumechange onwaiting
)
IN_ATTRIBUTE = WordList::CaseIgnoring.new(nil).
add(EVENT_ATTRIBUTES, :script).
add(['style'], :style)
ATTR_NAME = /[\w.:-]+/ # :nodoc:
TAG_END = /\/?>/ # :nodoc:
HEX = /[0-9a-fA-F]/ # :nodoc:
ENTITY = /
&
(?:
\w+
|
\#
(?:
\d+
|
x#{HEX}+
)
)
;
/ox # :nodoc:
PLAIN_STRING_CONTENT = {
"'" => /[^&'>\n]+/,
'"' => /[^&">\n]+/,
} # :nodoc:
def reset
super
@state = :initial
@plain_string_content = nil
end
protected
def setup
@state = :initial
@plain_string_content = nil
@in_tag = nil
end
def scan_java_script encoder, code
if code && !code.empty?
@java_script_scanner ||= Scanners::JavaScript.new '', :keep_tokens => true
@java_script_scanner.tokenize code, :tokens => encoder
end
end
def scan_css encoder, code, state = [:initial]
if code && !code.empty?
@css_scanner ||= Scanners::CSS.new '', :keep_tokens => true
@css_scanner.tokenize code, :tokens => encoder, :state => state
end
end
def scan_tokens encoder, options
state = options[:state] || @state
plain_string_content = @plain_string_content
in_tag = @in_tag
in_attribute = nil
encoder.begin_group :string if state == :attribute_value_string
until eos?
if state != :in_special_tag && match = scan(/\s+/m)
encoder.text_token match, :space
else
case state
when :initial
if match = scan(//m)
encoder.text_token match[0..-4], :plain
encoder.text_token ']]>', :inline_delimiter
elsif match = scan(/.+/)
encoder.text_token match, :error
end
elsif match = scan(/|.*)/m)
encoder.text_token match, :comment
elsif match = scan(/|.*)|\]>/m)
encoder.text_token match, :doctype
elsif match = scan(/<\?xml(?:.*?\?>|.*)/m)
encoder.text_token match, :preprocessor
elsif match = scan(/<\?(?:.*?\?>|.*)/m)
encoder.text_token match, :comment
elsif match = scan(/<\/[-\w.:]*>?/m)
in_tag = nil
encoder.text_token match, :tag
elsif match = scan(/<(?:(script|style)|[-\w.:]+)(>)?/m)
encoder.text_token match, :tag
in_tag = self[1]
if self[2]
state = :in_special_tag if in_tag
else
state = :attribute
end
elsif match = scan(/[^<>&]+/)
encoder.text_token match, :plain
elsif match = scan(/#{ENTITY}/ox)
encoder.text_token match, :entity
elsif match = scan(/[<>&]/)
in_tag = nil
encoder.text_token match, :error
else
raise_inspect '[BUG] else-case reached with state %p' % [state], encoder
end
when :attribute
if match = scan(/#{TAG_END}/o)
encoder.text_token match, :tag
in_attribute = nil
if in_tag
state = :in_special_tag
else
state = :initial
end
elsif match = scan(/#{ATTR_NAME}/o)
in_attribute = IN_ATTRIBUTE[match]
encoder.text_token match, :attribute_name
state = :attribute_equal
else
in_tag = nil
encoder.text_token getch, :error
end
when :attribute_equal
if match = scan(/=/) #/
encoder.text_token match, :operator
state = :attribute_value
else
state = :attribute
next
end
when :attribute_value
if match = scan(/#{ATTR_NAME}/o)
encoder.text_token match, :attribute_value
state = :attribute
elsif match = scan(/["']/)
if in_attribute == :script || in_attribute == :style
encoder.begin_group :string
encoder.text_token match, :delimiter
if scan(/javascript:[ \t]*/)
encoder.text_token matched, :comment
end
code = scan_until(match == '"' ? /(?="|\z)/ : /(?='|\z)/)
if in_attribute == :script
scan_java_script encoder, code
else
scan_css encoder, code, [:block]
end
match = scan(/["']/)
encoder.text_token match, :delimiter if match
encoder.end_group :string
state = :attribute
in_attribute = nil
else
encoder.begin_group :string
state = :attribute_value_string
plain_string_content = PLAIN_STRING_CONTENT[match]
encoder.text_token match, :delimiter
end
elsif match = scan(/#{TAG_END}/o)
encoder.text_token match, :tag
state = :initial
else
encoder.text_token getch, :error
end
when :attribute_value_string
if match = scan(plain_string_content)
encoder.text_token match, :content
elsif match = scan(/['"]/)
encoder.text_token match, :delimiter
encoder.end_group :string
state = :attribute
elsif match = scan(/#{ENTITY}/ox)
encoder.text_token match, :entity
elsif match = scan(/&/)
encoder.text_token match, :content
elsif match = scan(/[\n>]/)
encoder.end_group :string
state = :initial
encoder.text_token match, :error
end
when :in_special_tag
case in_tag
when 'script', 'style'
encoder.text_token match, :space if match = scan(/[ \t]*\n/)
if scan(/(\s*)|(.*))/m)
code = self[2] || self[4]
closing = self[3]
encoder.text_token self[1], :comment
else
code = scan_until(/(?=(?:\n\s*)?<\/#{in_tag}>)|\z/)
closing = false
end
unless code.empty?
encoder.begin_group :inline
if in_tag == 'script'
scan_java_script encoder, code
else
scan_css encoder, code
end
encoder.end_group :inline
end
encoder.text_token closing, :comment if closing
state = :initial
else
raise 'unknown special tag: %p' % [in_tag]
end
else
raise_inspect 'Unknown state: %p' % [state], encoder
end
end
end
if options[:keep_state]
@state = state
@plain_string_content = plain_string_content
@in_tag = in_tag
end
encoder.end_group :string if state == :attribute_value_string
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/java.rb 0000664 0000000 0000000 00000013053 13664404461 0020432 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# Scanner for Java.
class Java < Scanner
register_for :java
autoload :BuiltinTypes, CodeRay.coderay_path('scanners', 'java', 'builtin_types')
# http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html
KEYWORDS = %w[
assert break case catch continue default do else
finally for if instanceof import new package
return switch throw try typeof while
debugger export
] # :nodoc:
RESERVED = %w[ const goto ] # :nodoc:
CONSTANTS = %w[ false null true ] # :nodoc:
MAGIC_VARIABLES = %w[ this super ] # :nodoc:
TYPES = %w[
boolean byte char class double enum float int interface long
short void var
] << '[]' # :nodoc: because int[] should be highlighted as a type
DIRECTIVES = %w[
abstract extends final implements native private protected public
static strictfp synchronized throws transient volatile
] # :nodoc:
IDENT_KIND = WordList.new(:ident).
add(KEYWORDS, :keyword).
add(RESERVED, :reserved).
add(CONSTANTS, :predefined_constant).
add(MAGIC_VARIABLES, :local_variable).
add(TYPES, :type).
add(BuiltinTypes::List, :predefined_type).
add(BuiltinTypes::List.select { |builtin| builtin[/(Error|Exception)$/] }, :exception).
add(DIRECTIVES, :directive) # :nodoc:
ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
STRING_CONTENT_PATTERN = {
"'" => /[^\\']+/,
'"' => /[^\\"]+/,
'/' => /[^\\\/]+/,
} # :nodoc:
IDENT = RUBY_VERSION < '1.9' ? /[a-zA-Z_][A-Za-z_0-9]*/ : Regexp.new('[[[:alpha:]]_][[[:alnum:]]_]*') # :nodoc:
protected
def scan_tokens encoder, options
state = :initial
string_delimiter = nil
package_name_expected = false
class_name_follows = false
last_token_dot = false
until eos?
case state
when :initial
if match = scan(/ \s+ | \\\n /x)
encoder.text_token match, :space
next
elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
encoder.text_token match, :comment
next
elsif package_name_expected && match = scan(/ #{IDENT} (?: \. #{IDENT} )* /ox)
encoder.text_token match, package_name_expected
elsif match = scan(/ #{IDENT} | \[\] /ox)
kind = IDENT_KIND[match]
if last_token_dot
kind = :ident
elsif class_name_follows
kind = :class
class_name_follows = false
else
case match
when 'import'
package_name_expected = :include
when 'package'
package_name_expected = :namespace
when 'class', 'interface'
class_name_follows = true
end
end
encoder.text_token match, kind
elsif match = scan(/ \.(?!\d) | [,?:()\[\]}] | -- | \+\+ | && | \|\| | \*\*=? | [-+*\/%^~&|<>=!]=? | <<=? | >>>?=? /x)
encoder.text_token match, :operator
elsif match = scan(/;/)
package_name_expected = false
encoder.text_token match, :operator
elsif match = scan(/\{/)
class_name_follows = false
encoder.text_token match, :operator
elsif check(/[\d.]/)
if match = scan(/0[xX][0-9A-Fa-f]+/)
encoder.text_token match, :hex
elsif match = scan(/(?>0[0-7]+)(?![89.eEfF])/)
encoder.text_token match, :octal
elsif match = scan(/\d+[fFdD]|\d*\.\d+(?:[eE][+-]?\d+)?[fFdD]?|\d+[eE][+-]?\d+[fFdD]?/)
encoder.text_token match, :float
elsif match = scan(/\d+[lL]?/)
encoder.text_token match, :integer
end
elsif match = scan(/["']/)
state = :string
encoder.begin_group state
string_delimiter = match
encoder.text_token match, :delimiter
elsif match = scan(/ @ #{IDENT} /ox)
encoder.text_token match, :annotation
else
encoder.text_token getch, :error
end
when :string
if match = scan(STRING_CONTENT_PATTERN[string_delimiter])
encoder.text_token match, :content
elsif match = scan(/["'\/]/)
encoder.text_token match, :delimiter
encoder.end_group state
state = :initial
string_delimiter = nil
elsif state == :string && (match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox))
if string_delimiter == "'" && !(match == "\\\\" || match == "\\'")
encoder.text_token match, :content
else
encoder.text_token match, :char
end
elsif match = scan(/\\./m)
encoder.text_token match, :content
elsif match = scan(/ \\ | $ /x)
encoder.end_group state
state = :initial
encoder.text_token match, :error unless match.empty?
else
raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
end
else
raise_inspect 'Unknown state', encoder
end
last_token_dot = match == '.'
end
if state == :string
encoder.end_group state
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/java/ 0000775 0000000 0000000 00000000000 13664404461 0020103 5 ustar 00root root 0000000 0000000 coderay-1.1.3/lib/coderay/scanners/java/builtin_types.rb 0000664 0000000 0000000 00000121502 13664404461 0023323 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
module Java::BuiltinTypes # :nodoc:
#:nocov:
List = %w[
AbstractAction AbstractBorder AbstractButton AbstractCellEditor AbstractCollection
AbstractColorChooserPanel AbstractDocument AbstractExecutorService AbstractInterruptibleChannel
AbstractLayoutCache AbstractList AbstractListModel AbstractMap AbstractMethodError AbstractPreferences
AbstractQueue AbstractQueuedSynchronizer AbstractSelectableChannel AbstractSelectionKey AbstractSelector
AbstractSequentialList AbstractSet AbstractSpinnerModel AbstractTableModel AbstractUndoableEdit
AbstractWriter AccessControlContext AccessControlException AccessController AccessException Accessible
AccessibleAction AccessibleAttributeSequence AccessibleBundle AccessibleComponent AccessibleContext
AccessibleEditableText AccessibleExtendedComponent AccessibleExtendedTable AccessibleExtendedText
AccessibleHyperlink AccessibleHypertext AccessibleIcon AccessibleKeyBinding AccessibleObject
AccessibleRelation AccessibleRelationSet AccessibleResourceBundle AccessibleRole AccessibleSelection
AccessibleState AccessibleStateSet AccessibleStreamable AccessibleTable AccessibleTableModelChange
AccessibleText AccessibleTextSequence AccessibleValue AccountException AccountExpiredException
AccountLockedException AccountNotFoundException Acl AclEntry AclNotFoundException Action ActionEvent
ActionListener ActionMap ActionMapUIResource Activatable ActivateFailedException ActivationDesc
ActivationException ActivationGroup ActivationGroupDesc ActivationGroupID ActivationGroup_Stub
ActivationID ActivationInstantiator ActivationMonitor ActivationSystem Activator ActiveEvent
ActivityCompletedException ActivityRequiredException Adjustable AdjustmentEvent AdjustmentListener
Adler32 AffineTransform AffineTransformOp AlgorithmParameterGenerator AlgorithmParameterGeneratorSpi
AlgorithmParameters AlgorithmParameterSpec AlgorithmParametersSpi AllPermission AlphaComposite
AlreadyBoundException AlreadyConnectedException AncestorEvent AncestorListener AnnotatedElement
Annotation AnnotationFormatError AnnotationTypeMismatchException AppConfigurationEntry Appendable Applet
AppletContext AppletInitializer AppletStub Arc2D Area AreaAveragingScaleFilter ArithmeticException Array
ArrayBlockingQueue ArrayIndexOutOfBoundsException ArrayList Arrays ArrayStoreException ArrayType
AssertionError AsyncBoxView AsynchronousCloseException AtomicBoolean AtomicInteger AtomicIntegerArray
AtomicIntegerFieldUpdater AtomicLong AtomicLongArray AtomicLongFieldUpdater AtomicMarkableReference
AtomicReference AtomicReferenceArray AtomicReferenceFieldUpdater AtomicStampedReference Attribute
AttributeChangeNotification AttributeChangeNotificationFilter AttributedCharacterIterator
AttributedString AttributeException AttributeInUseException AttributeList AttributeModificationException
AttributeNotFoundException Attributes AttributeSet AttributeSetUtilities AttributeValueExp AudioClip
AudioFileFormat AudioFileReader AudioFileWriter AudioFormat AudioInputStream AudioPermission AudioSystem
AuthenticationException AuthenticationNotSupportedException Authenticator AuthorizeCallback
AuthPermission AuthProvider Autoscroll AWTError AWTEvent AWTEventListener AWTEventListenerProxy
AWTEventMulticaster AWTException AWTKeyStroke AWTPermission BackingStoreException
BadAttributeValueExpException BadBinaryOpValueExpException BadLocationException BadPaddingException
BadStringOperationException BandCombineOp BandedSampleModel BaseRowSet BasicArrowButton BasicAttribute
BasicAttributes BasicBorders BasicButtonListener BasicButtonUI BasicCheckBoxMenuItemUI BasicCheckBoxUI
BasicColorChooserUI BasicComboBoxEditor BasicComboBoxRenderer BasicComboBoxUI BasicComboPopup
BasicControl BasicDesktopIconUI BasicDesktopPaneUI BasicDirectoryModel BasicEditorPaneUI
BasicFileChooserUI BasicFormattedTextFieldUI BasicGraphicsUtils BasicHTML BasicIconFactory
BasicInternalFrameTitlePane BasicInternalFrameUI BasicLabelUI BasicListUI BasicLookAndFeel
BasicMenuBarUI BasicMenuItemUI BasicMenuUI BasicOptionPaneUI BasicPanelUI BasicPasswordFieldUI
BasicPermission BasicPopupMenuSeparatorUI BasicPopupMenuUI BasicProgressBarUI BasicRadioButtonMenuItemUI
BasicRadioButtonUI BasicRootPaneUI BasicScrollBarUI BasicScrollPaneUI BasicSeparatorUI BasicSliderUI
BasicSpinnerUI BasicSplitPaneDivider BasicSplitPaneUI BasicStroke BasicTabbedPaneUI BasicTableHeaderUI
BasicTableUI BasicTextAreaUI BasicTextFieldUI BasicTextPaneUI BasicTextUI BasicToggleButtonUI
BasicToolBarSeparatorUI BasicToolBarUI BasicToolTipUI BasicTreeUI BasicViewportUI BatchUpdateException
BeanContext BeanContextChild BeanContextChildComponentProxy BeanContextChildSupport
BeanContextContainerProxy BeanContextEvent BeanContextMembershipEvent BeanContextMembershipListener
BeanContextProxy BeanContextServiceAvailableEvent BeanContextServiceProvider
BeanContextServiceProviderBeanInfo BeanContextServiceRevokedEvent BeanContextServiceRevokedListener
BeanContextServices BeanContextServicesListener BeanContextServicesSupport BeanContextSupport
BeanDescriptor BeanInfo Beans BevelBorder Bidi BigDecimal BigInteger BinaryRefAddr BindException Binding
BitSet Blob BlockingQueue BlockView BMPImageWriteParam Book Boolean BooleanControl Border BorderFactory
BorderLayout BorderUIResource BoundedRangeModel Box BoxLayout BoxView BreakIterator
BrokenBarrierException Buffer BufferCapabilities BufferedImage BufferedImageFilter BufferedImageOp
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter BufferOverflowException
BufferStrategy BufferUnderflowException Button ButtonGroup ButtonModel ButtonUI Byte
ByteArrayInputStream ByteArrayOutputStream ByteBuffer ByteChannel ByteLookupTable ByteOrder CachedRowSet
CacheRequest CacheResponse Calendar Callable CallableStatement Callback CallbackHandler
CancelablePrintJob CancellationException CancelledKeyException CannotProceedException
CannotRedoException CannotUndoException Canvas CardLayout Caret CaretEvent CaretListener CellEditor
CellEditorListener CellRendererPane Certificate CertificateEncodingException CertificateException
CertificateExpiredException CertificateFactory CertificateFactorySpi CertificateNotYetValidException
CertificateParsingException CertPath CertPathBuilder CertPathBuilderException CertPathBuilderResult
CertPathBuilderSpi CertPathParameters CertPathTrustManagerParameters CertPathValidator
CertPathValidatorException CertPathValidatorResult CertPathValidatorSpi CertSelector CertStore
CertStoreException CertStoreParameters CertStoreSpi ChangedCharSetException ChangeEvent ChangeListener
Channel Channels Character CharacterCodingException CharacterIterator CharArrayReader CharArrayWriter
CharBuffer CharConversionException CharSequence Charset CharsetDecoder CharsetEncoder CharsetProvider
Checkbox CheckboxGroup CheckboxMenuItem CheckedInputStream CheckedOutputStream Checksum Choice
ChoiceCallback ChoiceFormat Chromaticity Cipher CipherInputStream CipherOutputStream CipherSpi Class
ClassCastException ClassCircularityError ClassDefinition ClassDesc ClassFileTransformer ClassFormatError
ClassLoader ClassLoaderRepository ClassLoadingMXBean ClassNotFoundException Clip Clipboard
ClipboardOwner Clob Cloneable CloneNotSupportedException Closeable ClosedByInterruptException
ClosedChannelException ClosedSelectorException CMMException CoderMalfunctionError CoderResult CodeSigner
CodeSource CodingErrorAction CollationElementIterator CollationKey Collator Collection
CollectionCertStoreParameters Collections Color ColorChooserComponentFactory ColorChooserUI
ColorConvertOp ColorModel ColorSelectionModel ColorSpace ColorSupported ColorType ColorUIResource
ComboBoxEditor ComboBoxModel ComboBoxUI ComboPopup CommunicationException Comparable Comparator
CompilationMXBean Compiler CompletionService Component ComponentAdapter ComponentColorModel
ComponentEvent ComponentInputMap ComponentInputMapUIResource ComponentListener ComponentOrientation
ComponentSampleModel ComponentUI ComponentView Composite CompositeContext CompositeData
CompositeDataSupport CompositeName CompositeType CompositeView CompoundBorder CompoundControl
CompoundEdit CompoundName Compression ConcurrentHashMap ConcurrentLinkedQueue ConcurrentMap
ConcurrentModificationException Condition Configuration ConfigurationException ConfirmationCallback
ConnectException ConnectIOException Connection ConnectionEvent ConnectionEventListener
ConnectionPendingException ConnectionPoolDataSource ConsoleHandler Constructor Container
ContainerAdapter ContainerEvent ContainerListener ContainerOrderFocusTraversalPolicy ContentHandler
ContentHandlerFactory ContentModel Context ContextNotEmptyException ContextualRenderedImageFactory
Control ControlFactory ControllerEventListener ConvolveOp CookieHandler Copies CopiesSupported
CopyOnWriteArrayList CopyOnWriteArraySet CountDownLatch CounterMonitor CounterMonitorMBean CRC32
CredentialException CredentialExpiredException CredentialNotFoundException CRL CRLException CRLSelector
CropImageFilter CSS CubicCurve2D Currency Cursor Customizer CyclicBarrier DatabaseMetaData DataBuffer
DataBufferByte DataBufferDouble DataBufferFloat DataBufferInt DataBufferShort DataBufferUShort
DataFlavor DataFormatException DatagramChannel DatagramPacket DatagramSocket DatagramSocketImpl
DatagramSocketImplFactory DataInput DataInputStream DataLine DataOutput DataOutputStream DataSource
DataTruncation DatatypeConfigurationException DatatypeConstants DatatypeFactory Date DateFormat
DateFormatSymbols DateFormatter DateTimeAtCompleted DateTimeAtCreation DateTimeAtProcessing
DateTimeSyntax DebugGraphics DecimalFormat DecimalFormatSymbols DefaultBoundedRangeModel
DefaultButtonModel DefaultCaret DefaultCellEditor DefaultColorSelectionModel DefaultComboBoxModel
DefaultDesktopManager DefaultEditorKit DefaultFocusManager DefaultFocusTraversalPolicy DefaultFormatter
DefaultFormatterFactory DefaultHighlighter DefaultKeyboardFocusManager DefaultListCellRenderer
DefaultListModel DefaultListSelectionModel DefaultLoaderRepository DefaultMenuLayout DefaultMetalTheme
DefaultMutableTreeNode DefaultPersistenceDelegate DefaultSingleSelectionModel DefaultStyledDocument
DefaultTableCellRenderer DefaultTableColumnModel DefaultTableModel DefaultTextUI DefaultTreeCellEditor
DefaultTreeCellRenderer DefaultTreeModel DefaultTreeSelectionModel Deflater DeflaterOutputStream Delayed
DelayQueue DelegationPermission Deprecated Descriptor DescriptorAccess DescriptorSupport DESedeKeySpec
DesignMode DESKeySpec DesktopIconUI DesktopManager DesktopPaneUI Destination Destroyable
DestroyFailedException DGC DHGenParameterSpec DHKey DHParameterSpec DHPrivateKey DHPrivateKeySpec
DHPublicKey DHPublicKeySpec Dialog Dictionary DigestException DigestInputStream DigestOutputStream
Dimension Dimension2D DimensionUIResource DirContext DirectColorModel DirectoryManager DirObjectFactory
DirStateFactory DisplayMode DnDConstants Doc DocAttribute DocAttributeSet DocFlavor DocPrintJob Document
DocumentBuilder DocumentBuilderFactory Documented DocumentEvent DocumentFilter DocumentListener
DocumentName DocumentParser DomainCombiner DOMLocator DOMResult DOMSource Double DoubleBuffer
DragGestureEvent DragGestureListener DragGestureRecognizer DragSource DragSourceAdapter
DragSourceContext DragSourceDragEvent DragSourceDropEvent DragSourceEvent DragSourceListener
DragSourceMotionListener Driver DriverManager DriverPropertyInfo DropTarget DropTargetAdapter
DropTargetContext DropTargetDragEvent DropTargetDropEvent DropTargetEvent DropTargetListener DSAKey
DSAKeyPairGenerator DSAParameterSpec DSAParams DSAPrivateKey DSAPrivateKeySpec DSAPublicKey
DSAPublicKeySpec DTD DTDConstants DuplicateFormatFlagsException Duration DynamicMBean ECField ECFieldF2m
ECFieldFp ECGenParameterSpec ECKey ECParameterSpec ECPoint ECPrivateKey ECPrivateKeySpec ECPublicKey
ECPublicKeySpec EditorKit Element ElementIterator ElementType Ellipse2D EllipticCurve EmptyBorder
EmptyStackException EncodedKeySpec Encoder EncryptedPrivateKeyInfo Entity Enum
EnumConstantNotPresentException EnumControl Enumeration EnumMap EnumSet EnumSyntax EOFException Error
ErrorListener ErrorManager EtchedBorder Event EventContext EventDirContext EventHandler EventListener
EventListenerList EventListenerProxy EventObject EventQueue EventSetDescriptor Exception
ExceptionInInitializerError ExceptionListener Exchanger ExecutionException Executor
ExecutorCompletionService Executors ExecutorService ExemptionMechanism ExemptionMechanismException
ExemptionMechanismSpi ExpandVetoException ExportException Expression ExtendedRequest ExtendedResponse
Externalizable FactoryConfigurationError FailedLoginException FeatureDescriptor Fidelity Field
FieldPosition FieldView File FileCacheImageInputStream FileCacheImageOutputStream FileChannel
FileChooserUI FileDescriptor FileDialog FileFilter FileHandler FileImageInputStream
FileImageOutputStream FileInputStream FileLock FileLockInterruptionException FilenameFilter FileNameMap
FileNotFoundException FileOutputStream FilePermission FileReader FileSystemView FileView FileWriter
Filter FilteredImageSource FilteredRowSet FilterInputStream FilterOutputStream FilterReader FilterWriter
Finishings FixedHeightLayoutCache FlatteningPathIterator FlavorEvent FlavorException FlavorListener
FlavorMap FlavorTable Float FloatBuffer FloatControl FlowLayout FlowView Flushable FocusAdapter
FocusEvent FocusListener FocusManager FocusTraversalPolicy Font FontFormatException FontMetrics
FontRenderContext FontUIResource Format FormatConversionProvider FormatFlagsConversionMismatchException
Formattable FormattableFlags Formatter FormatterClosedException FormSubmitEvent FormView Frame Future
FutureTask GapContent GarbageCollectorMXBean GatheringByteChannel GaugeMonitor GaugeMonitorMBean
GeneralPath GeneralSecurityException GenericArrayType GenericDeclaration GenericSignatureFormatError
GlyphJustificationInfo GlyphMetrics GlyphVector GlyphView GradientPaint GraphicAttribute Graphics
Graphics2D GraphicsConfigTemplate GraphicsConfiguration GraphicsDevice GraphicsEnvironment GrayFilter
GregorianCalendar GridBagConstraints GridBagLayout GridLayout Group Guard GuardedObject GZIPInputStream
GZIPOutputStream Handler HandshakeCompletedEvent HandshakeCompletedListener HasControls HashAttributeSet
HashDocAttributeSet HashMap HashPrintJobAttributeSet HashPrintRequestAttributeSet
HashPrintServiceAttributeSet HashSet Hashtable HeadlessException HierarchyBoundsAdapter
HierarchyBoundsListener HierarchyEvent HierarchyListener Highlighter HostnameVerifier HTML HTMLDocument
HTMLEditorKit HTMLFrameHyperlinkEvent HTMLWriter HttpRetryException HttpsURLConnection HttpURLConnection
HyperlinkEvent HyperlinkListener ICC_ColorSpace ICC_Profile ICC_ProfileGray ICC_ProfileRGB Icon
IconUIResource IconView Identity IdentityHashMap IdentityScope IIOByteBuffer IIOException IIOImage
IIOInvalidTreeException IIOMetadata IIOMetadataController IIOMetadataFormat IIOMetadataFormatImpl
IIOMetadataNode IIOParam IIOParamController IIOReadProgressListener IIOReadUpdateListener
IIOReadWarningListener IIORegistry IIOServiceProvider IIOWriteProgressListener IIOWriteWarningListener
IllegalAccessError IllegalAccessException IllegalArgumentException IllegalBlockingModeException
IllegalBlockSizeException IllegalCharsetNameException IllegalClassFormatException
IllegalComponentStateException IllegalFormatCodePointException IllegalFormatConversionException
IllegalFormatException IllegalFormatFlagsException IllegalFormatPrecisionException
IllegalFormatWidthException IllegalMonitorStateException IllegalPathStateException
IllegalSelectorException IllegalStateException IllegalThreadStateException Image ImageCapabilities
ImageConsumer ImageFilter ImageGraphicAttribute ImageIcon ImageInputStream ImageInputStreamImpl
ImageInputStreamSpi ImageIO ImageObserver ImageOutputStream ImageOutputStreamImpl ImageOutputStreamSpi
ImageProducer ImageReader ImageReaderSpi ImageReaderWriterSpi ImageReadParam ImageTranscoder
ImageTranscoderSpi ImageTypeSpecifier ImageView ImageWriteParam ImageWriter ImageWriterSpi
ImagingOpException IncompatibleClassChangeError IncompleteAnnotationException IndexColorModel
IndexedPropertyChangeEvent IndexedPropertyDescriptor IndexOutOfBoundsException Inet4Address Inet6Address
InetAddress InetSocketAddress Inflater InflaterInputStream InheritableThreadLocal Inherited
InitialContext InitialContextFactory InitialContextFactoryBuilder InitialDirContext InitialLdapContext
InlineView InputContext InputEvent InputMap InputMapUIResource InputMethod InputMethodContext
InputMethodDescriptor InputMethodEvent InputMethodHighlight InputMethodListener InputMethodRequests
InputMismatchException InputStream InputStreamReader InputSubset InputVerifier Insets InsetsUIResource
InstanceAlreadyExistsException InstanceNotFoundException InstantiationError InstantiationException
Instrument Instrumentation InsufficientResourcesException IntBuffer Integer IntegerSyntax InternalError
InternalFrameAdapter InternalFrameEvent InternalFrameFocusTraversalPolicy InternalFrameListener
InternalFrameUI InternationalFormatter InterruptedException InterruptedIOException
InterruptedNamingException InterruptibleChannel IntrospectionException Introspector
InvalidActivityException InvalidAlgorithmParameterException InvalidApplicationException
InvalidAttributeIdentifierException InvalidAttributesException InvalidAttributeValueException
InvalidClassException InvalidDnDOperationException InvalidKeyException InvalidKeySpecException
InvalidMarkException InvalidMidiDataException InvalidNameException InvalidObjectException
InvalidOpenTypeException InvalidParameterException InvalidParameterSpecException
InvalidPreferencesFormatException InvalidPropertiesFormatException InvalidRelationIdException
InvalidRelationServiceException InvalidRelationTypeException InvalidRoleInfoException
InvalidRoleValueException InvalidSearchControlsException InvalidSearchFilterException
InvalidTargetObjectTypeException InvalidTransactionException InvocationEvent InvocationHandler
InvocationTargetException IOException ItemEvent ItemListener ItemSelectable Iterable Iterator
IvParameterSpec JApplet JarEntry JarException JarFile JarInputStream JarOutputStream JarURLConnection
JButton JCheckBox JCheckBoxMenuItem JColorChooser JComboBox JComponent JdbcRowSet JDesktopPane JDialog
JEditorPane JFileChooser JFormattedTextField JFrame JInternalFrame JLabel JLayeredPane JList JMenu
JMenuBar JMenuItem JMException JMRuntimeException JMXAuthenticator JMXConnectionNotification
JMXConnector JMXConnectorFactory JMXConnectorProvider JMXConnectorServer JMXConnectorServerFactory
JMXConnectorServerMBean JMXConnectorServerProvider JMXPrincipal JMXProviderException
JMXServerErrorException JMXServiceURL JobAttributes JobHoldUntil JobImpressions JobImpressionsCompleted
JobImpressionsSupported JobKOctets JobKOctetsProcessed JobKOctetsSupported JobMediaSheets
JobMediaSheetsCompleted JobMediaSheetsSupported JobMessageFromOperator JobName JobOriginatingUserName
JobPriority JobPrioritySupported JobSheets JobState JobStateReason JobStateReasons Joinable JoinRowSet
JOptionPane JPanel JPasswordField JPEGHuffmanTable JPEGImageReadParam JPEGImageWriteParam JPEGQTable
JPopupMenu JProgressBar JRadioButton JRadioButtonMenuItem JRootPane JScrollBar JScrollPane JSeparator
JSlider JSpinner JSplitPane JTabbedPane JTable JTableHeader JTextArea JTextComponent JTextField
JTextPane JToggleButton JToolBar JToolTip JTree JViewport JWindow KerberosKey KerberosPrincipal
KerberosTicket Kernel Key KeyAdapter KeyAgreement KeyAgreementSpi KeyAlreadyExistsException
KeyboardFocusManager KeyEvent KeyEventDispatcher KeyEventPostProcessor KeyException KeyFactory
KeyFactorySpi KeyGenerator KeyGeneratorSpi KeyListener KeyManagementException KeyManager
KeyManagerFactory KeyManagerFactorySpi Keymap KeyPair KeyPairGenerator KeyPairGeneratorSpi KeyRep
KeySpec KeyStore KeyStoreBuilderParameters KeyStoreException KeyStoreSpi KeyStroke Label LabelUI
LabelView LanguageCallback LastOwnerException LayeredHighlighter LayoutFocusTraversalPolicy
LayoutManager LayoutManager2 LayoutQueue LDAPCertStoreParameters LdapContext LdapName
LdapReferralException Lease Level LimitExceededException Line Line2D LineBorder LineBreakMeasurer
LineEvent LineListener LineMetrics LineNumberInputStream LineNumberReader LineUnavailableException
LinkageError LinkedBlockingQueue LinkedHashMap LinkedHashSet LinkedList LinkException LinkLoopException
LinkRef List ListCellRenderer ListDataEvent ListDataListener ListenerNotFoundException ListIterator
ListModel ListResourceBundle ListSelectionEvent ListSelectionListener ListSelectionModel ListUI ListView
LoaderHandler Locale LocateRegistry Lock LockSupport Logger LoggingMXBean LoggingPermission LoginContext
LoginException LoginModule LogManager LogRecord LogStream Long LongBuffer LookAndFeel LookupOp
LookupTable Mac MacSpi MalformedInputException MalformedLinkException MalformedObjectNameException
MalformedParameterizedTypeException MalformedURLException ManagementFactory ManagementPermission
ManageReferralControl ManagerFactoryParameters Manifest Map MappedByteBuffer MarshalException
MarshalledObject MaskFormatter Matcher MatchResult Math MathContext MatteBorder MBeanAttributeInfo
MBeanConstructorInfo MBeanException MBeanFeatureInfo MBeanInfo MBeanNotificationInfo MBeanOperationInfo
MBeanParameterInfo MBeanPermission MBeanRegistration MBeanRegistrationException MBeanServer
MBeanServerBuilder MBeanServerConnection MBeanServerDelegate MBeanServerDelegateMBean MBeanServerFactory
MBeanServerForwarder MBeanServerInvocationHandler MBeanServerNotification MBeanServerNotificationFilter
MBeanServerPermission MBeanTrustPermission Media MediaName MediaPrintableArea MediaSize MediaSizeName
MediaTracker MediaTray Member MemoryCacheImageInputStream MemoryCacheImageOutputStream MemoryHandler
MemoryImageSource MemoryManagerMXBean MemoryMXBean MemoryNotificationInfo MemoryPoolMXBean MemoryType
MemoryUsage Menu MenuBar MenuBarUI MenuComponent MenuContainer MenuDragMouseEvent MenuDragMouseListener
MenuElement MenuEvent MenuItem MenuItemUI MenuKeyEvent MenuKeyListener MenuListener MenuSelectionManager
MenuShortcut MessageDigest MessageDigestSpi MessageFormat MetaEventListener MetalBorders MetalButtonUI
MetalCheckBoxIcon MetalCheckBoxUI MetalComboBoxButton MetalComboBoxEditor MetalComboBoxIcon
MetalComboBoxUI MetalDesktopIconUI MetalFileChooserUI MetalIconFactory MetalInternalFrameTitlePane
MetalInternalFrameUI MetalLabelUI MetalLookAndFeel MetalMenuBarUI MetalPopupMenuSeparatorUI
MetalProgressBarUI MetalRadioButtonUI MetalRootPaneUI MetalScrollBarUI MetalScrollButton
MetalScrollPaneUI MetalSeparatorUI MetalSliderUI MetalSplitPaneUI MetalTabbedPaneUI MetalTextFieldUI
MetalTheme MetalToggleButtonUI MetalToolBarUI MetalToolTipUI MetalTreeUI MetaMessage Method
MethodDescriptor MGF1ParameterSpec MidiChannel MidiDevice MidiDeviceProvider MidiEvent MidiFileFormat
MidiFileReader MidiFileWriter MidiMessage MidiSystem MidiUnavailableException MimeTypeParseException
MinimalHTMLWriter MissingFormatArgumentException MissingFormatWidthException MissingResourceException
Mixer MixerProvider MLet MLetMBean ModelMBean ModelMBeanAttributeInfo ModelMBeanConstructorInfo
ModelMBeanInfo ModelMBeanInfoSupport ModelMBeanNotificationBroadcaster ModelMBeanNotificationInfo
ModelMBeanOperationInfo ModificationItem Modifier Monitor MonitorMBean MonitorNotification
MonitorSettingException MouseAdapter MouseDragGestureRecognizer MouseEvent MouseInfo MouseInputAdapter
MouseInputListener MouseListener MouseMotionAdapter MouseMotionListener MouseWheelEvent
MouseWheelListener MultiButtonUI MulticastSocket MultiColorChooserUI MultiComboBoxUI MultiDesktopIconUI
MultiDesktopPaneUI MultiDoc MultiDocPrintJob MultiDocPrintService MultiFileChooserUI
MultiInternalFrameUI MultiLabelUI MultiListUI MultiLookAndFeel MultiMenuBarUI MultiMenuItemUI
MultiOptionPaneUI MultiPanelUI MultiPixelPackedSampleModel MultipleDocumentHandling MultipleMaster
MultiPopupMenuUI MultiProgressBarUI MultiRootPaneUI MultiScrollBarUI MultiScrollPaneUI MultiSeparatorUI
MultiSliderUI MultiSpinnerUI MultiSplitPaneUI MultiTabbedPaneUI MultiTableHeaderUI MultiTableUI
MultiTextUI MultiToolBarUI MultiToolTipUI MultiTreeUI MultiViewportUI MutableAttributeSet
MutableComboBoxModel MutableTreeNode Name NameAlreadyBoundException NameCallback NameClassPair
NameNotFoundException NameParser NamespaceChangeListener NamespaceContext Naming NamingEnumeration
NamingEvent NamingException NamingExceptionEvent NamingListener NamingManager NamingSecurityException
NavigationFilter NegativeArraySizeException NetPermission NetworkInterface NoClassDefFoundError
NoConnectionPendingException NodeChangeEvent NodeChangeListener NoInitialContextException
NoninvertibleTransformException NonReadableChannelException NonWritableChannelException
NoPermissionException NoRouteToHostException NoSuchAlgorithmException NoSuchAttributeException
NoSuchElementException NoSuchFieldError NoSuchFieldException NoSuchMethodError NoSuchMethodException
NoSuchObjectException NoSuchPaddingException NoSuchProviderException NotActiveException
NotBoundException NotCompliantMBeanException NotContextException Notification NotificationBroadcaster
NotificationBroadcasterSupport NotificationEmitter NotificationFilter NotificationFilterSupport
NotificationListener NotificationResult NotOwnerException NotSerializableException NotYetBoundException
NotYetConnectedException NullCipher NullPointerException Number NumberFormat NumberFormatException
NumberFormatter NumberOfDocuments NumberOfInterveningJobs NumberUp NumberUpSupported NumericShaper
OAEPParameterSpec Object ObjectChangeListener ObjectFactory ObjectFactoryBuilder ObjectInput
ObjectInputStream ObjectInputValidation ObjectInstance ObjectName ObjectOutput ObjectOutputStream
ObjectStreamClass ObjectStreamConstants ObjectStreamException ObjectStreamField ObjectView ObjID
Observable Observer OceanTheme OpenDataException OpenMBeanAttributeInfo OpenMBeanAttributeInfoSupport
OpenMBeanConstructorInfo OpenMBeanConstructorInfoSupport OpenMBeanInfo OpenMBeanInfoSupport
OpenMBeanOperationInfo OpenMBeanOperationInfoSupport OpenMBeanParameterInfo
OpenMBeanParameterInfoSupport OpenType OperatingSystemMXBean Operation OperationNotSupportedException
OperationsException Option OptionalDataException OptionPaneUI OrientationRequested OutOfMemoryError
OutputDeviceAssigned OutputKeys OutputStream OutputStreamWriter OverlappingFileLockException
OverlayLayout Override Owner Pack200 Package PackedColorModel Pageable PageAttributes
PagedResultsControl PagedResultsResponseControl PageFormat PageRanges PagesPerMinute PagesPerMinuteColor
Paint PaintContext PaintEvent Panel PanelUI Paper ParagraphView ParameterBlock ParameterDescriptor
ParameterizedType ParameterMetaData ParseException ParsePosition Parser ParserConfigurationException
ParserDelegator PartialResultException PasswordAuthentication PasswordCallback PasswordView Patch
PathIterator Pattern PatternSyntaxException PBEKey PBEKeySpec PBEParameterSpec PDLOverrideSupported
Permission PermissionCollection Permissions PersistenceDelegate PersistentMBean PhantomReference Pipe
PipedInputStream PipedOutputStream PipedReader PipedWriter PixelGrabber PixelInterleavedSampleModel
PKCS8EncodedKeySpec PKIXBuilderParameters PKIXCertPathBuilderResult PKIXCertPathChecker
PKIXCertPathValidatorResult PKIXParameters PlainDocument PlainView Point Point2D PointerInfo Policy
PolicyNode PolicyQualifierInfo Polygon PooledConnection Popup PopupFactory PopupMenu PopupMenuEvent
PopupMenuListener PopupMenuUI Port PortableRemoteObject PortableRemoteObjectDelegate
PortUnreachableException Position Predicate PreferenceChangeEvent PreferenceChangeListener Preferences
PreferencesFactory PreparedStatement PresentationDirection Principal Printable PrinterAbortException
PrinterException PrinterGraphics PrinterInfo PrinterIOException PrinterIsAcceptingJobs PrinterJob
PrinterLocation PrinterMakeAndModel PrinterMessageFromOperator PrinterMoreInfo
PrinterMoreInfoManufacturer PrinterName PrinterResolution PrinterState PrinterStateReason
PrinterStateReasons PrinterURI PrintEvent PrintException PrintGraphics PrintJob PrintJobAdapter
PrintJobAttribute PrintJobAttributeEvent PrintJobAttributeListener PrintJobAttributeSet PrintJobEvent
PrintJobListener PrintQuality PrintRequestAttribute PrintRequestAttributeSet PrintService
PrintServiceAttribute PrintServiceAttributeEvent PrintServiceAttributeListener PrintServiceAttributeSet
PrintServiceLookup PrintStream PrintWriter PriorityBlockingQueue PriorityQueue PrivateClassLoader
PrivateCredentialPermission PrivateKey PrivateMLet PrivilegedAction PrivilegedActionException
PrivilegedExceptionAction Process ProcessBuilder ProfileDataException ProgressBarUI ProgressMonitor
ProgressMonitorInputStream Properties PropertyChangeEvent PropertyChangeListener
PropertyChangeListenerProxy PropertyChangeSupport PropertyDescriptor PropertyEditor
PropertyEditorManager PropertyEditorSupport PropertyPermission PropertyResourceBundle
PropertyVetoException ProtectionDomain ProtocolException Provider ProviderException Proxy ProxySelector
PSource PSSParameterSpec PublicKey PushbackInputStream PushbackReader QName QuadCurve2D Query QueryEval
QueryExp Queue QueuedJobCount Random RandomAccess RandomAccessFile Raster RasterFormatException RasterOp
RC2ParameterSpec RC5ParameterSpec Rdn Readable ReadableByteChannel Reader ReadOnlyBufferException
ReadWriteLock RealmCallback RealmChoiceCallback Receiver Rectangle Rectangle2D RectangularShape
ReentrantLock ReentrantReadWriteLock Ref RefAddr Reference Referenceable ReferenceQueue
ReferenceUriSchemesSupported ReferralException ReflectionException ReflectPermission Refreshable
RefreshFailedException Region RegisterableService Registry RegistryHandler RejectedExecutionException
RejectedExecutionHandler Relation RelationException RelationNotFoundException RelationNotification
RelationService RelationServiceMBean RelationServiceNotRegisteredException RelationSupport
RelationSupportMBean RelationType RelationTypeNotFoundException RelationTypeSupport Remote RemoteCall
RemoteException RemoteObject RemoteObjectInvocationHandler RemoteRef RemoteServer RemoteStub
RenderableImage RenderableImageOp RenderableImageProducer RenderContext RenderedImage
RenderedImageFactory Renderer RenderingHints RepaintManager ReplicateScaleFilter RequestingUserName
RequiredModelMBean RescaleOp ResolutionSyntax Resolver ResolveResult ResourceBundle ResponseCache Result
ResultSet ResultSetMetaData Retention RetentionPolicy ReverbType RGBImageFilter RMIClassLoader
RMIClassLoaderSpi RMIClientSocketFactory RMIConnection RMIConnectionImpl RMIConnectionImpl_Stub
RMIConnector RMIConnectorServer RMIFailureHandler RMIIIOPServerImpl RMIJRMPServerImpl
RMISecurityException RMISecurityManager RMIServer RMIServerImpl RMIServerImpl_Stub
RMIServerSocketFactory RMISocketFactory Robot Role RoleInfo RoleInfoNotFoundException RoleList
RoleNotFoundException RoleResult RoleStatus RoleUnresolved RoleUnresolvedList RootPaneContainer
RootPaneUI RoundingMode RoundRectangle2D RowMapper RowSet RowSetEvent RowSetInternal RowSetListener
RowSetMetaData RowSetMetaDataImpl RowSetReader RowSetWarning RowSetWriter RSAKey RSAKeyGenParameterSpec
RSAMultiPrimePrivateCrtKey RSAMultiPrimePrivateCrtKeySpec RSAOtherPrimeInfo RSAPrivateCrtKey
RSAPrivateCrtKeySpec RSAPrivateKey RSAPrivateKeySpec RSAPublicKey RSAPublicKeySpec RTFEditorKit
RuleBasedCollator Runnable Runtime RuntimeErrorException RuntimeException RuntimeMBeanException
RuntimeMXBean RuntimeOperationsException RuntimePermission SampleModel Sasl SaslClient SaslClientFactory
SaslException SaslServer SaslServerFactory Savepoint SAXParser SAXParserFactory SAXResult SAXSource
SAXTransformerFactory Scanner ScatteringByteChannel ScheduledExecutorService ScheduledFuture
ScheduledThreadPoolExecutor Schema SchemaFactory SchemaFactoryLoader SchemaViolationException Scrollable
Scrollbar ScrollBarUI ScrollPane ScrollPaneAdjustable ScrollPaneConstants ScrollPaneLayout ScrollPaneUI
SealedObject SearchControls SearchResult SecretKey SecretKeyFactory SecretKeyFactorySpi SecretKeySpec
SecureCacheResponse SecureClassLoader SecureRandom SecureRandomSpi Security SecurityException
SecurityManager SecurityPermission Segment SelectableChannel SelectionKey Selector SelectorProvider
Semaphore SeparatorUI Sequence SequenceInputStream Sequencer SerialArray SerialBlob SerialClob
SerialDatalink SerialException Serializable SerializablePermission SerialJavaObject SerialRef
SerialStruct ServerCloneException ServerError ServerException ServerNotActiveException ServerRef
ServerRuntimeException ServerSocket ServerSocketChannel ServerSocketFactory ServiceNotFoundException
ServicePermission ServiceRegistry ServiceUI ServiceUIFactory ServiceUnavailableException Set
SetOfIntegerSyntax Severity Shape ShapeGraphicAttribute SheetCollate Short ShortBuffer
ShortBufferException ShortLookupTable ShortMessage Sides Signature SignatureException SignatureSpi
SignedObject Signer SimpleAttributeSet SimpleBeanInfo SimpleDateFormat SimpleDoc SimpleFormatter
SimpleTimeZone SimpleType SinglePixelPackedSampleModel SingleSelectionModel Size2DSyntax
SizeLimitExceededException SizeRequirements SizeSequence Skeleton SkeletonMismatchException
SkeletonNotFoundException SliderUI Socket SocketAddress SocketChannel SocketException SocketFactory
SocketHandler SocketImpl SocketImplFactory SocketOptions SocketPermission SocketSecurityException
SocketTimeoutException SoftBevelBorder SoftReference SortControl SortedMap SortedSet
SortingFocusTraversalPolicy SortKey SortResponseControl Soundbank SoundbankReader SoundbankResource
Source SourceDataLine SourceLocator SpinnerDateModel SpinnerListModel SpinnerModel SpinnerNumberModel
SpinnerUI SplitPaneUI Spring SpringLayout SQLData SQLException SQLInput SQLInputImpl SQLOutput
SQLOutputImpl SQLPermission SQLWarning SSLContext SSLContextSpi SSLEngine SSLEngineResult SSLException
SSLHandshakeException SSLKeyException SSLPeerUnverifiedException SSLPermission SSLProtocolException
SslRMIClientSocketFactory SslRMIServerSocketFactory SSLServerSocket SSLServerSocketFactory SSLSession
SSLSessionBindingEvent SSLSessionBindingListener SSLSessionContext SSLSocket SSLSocketFactory Stack
StackOverflowError StackTraceElement StandardMBean StartTlsRequest StartTlsResponse StateEdit
StateEditable StateFactory Statement StreamCorruptedException StreamHandler StreamPrintService
StreamPrintServiceFactory StreamResult StreamSource StreamTokenizer StrictMath String StringBuffer
StringBufferInputStream StringBuilder StringCharacterIterator StringContent
StringIndexOutOfBoundsException StringMonitor StringMonitorMBean StringReader StringRefAddr
StringSelection StringTokenizer StringValueExp StringWriter Stroke Struct Stub StubDelegate
StubNotFoundException Style StyleConstants StyleContext StyledDocument StyledEditorKit StyleSheet
Subject SubjectDelegationPermission SubjectDomainCombiner SupportedValuesAttribute SuppressWarnings
SwingConstants SwingPropertyChangeSupport SwingUtilities SyncFactory SyncFactoryException
SyncFailedException SynchronousQueue SyncProvider SyncProviderException SyncResolver SynthConstants
SynthContext Synthesizer SynthGraphicsUtils SynthLookAndFeel SynthPainter SynthStyle SynthStyleFactory
SysexMessage System SystemColor SystemFlavorMap TabableView TabbedPaneUI TabExpander TableCellEditor
TableCellRenderer TableColumn TableColumnModel TableColumnModelEvent TableColumnModelListener
TableHeaderUI TableModel TableModelEvent TableModelListener TableUI TableView TabSet TabStop TabularData
TabularDataSupport TabularType TagElement Target TargetDataLine TargetedNotification Templates
TemplatesHandler TextAction TextArea TextAttribute TextComponent TextEvent TextField TextHitInfo
TextInputCallback TextLayout TextListener TextMeasurer TextOutputCallback TextSyntax TextUI TexturePaint
Thread ThreadDeath ThreadFactory ThreadGroup ThreadInfo ThreadLocal ThreadMXBean ThreadPoolExecutor
Throwable Tie TileObserver Time TimeLimitExceededException TimeoutException Timer
TimerAlarmClockNotification TimerMBean TimerNotification TimerTask Timestamp TimeUnit TimeZone
TitledBorder ToolBarUI Toolkit ToolTipManager ToolTipUI TooManyListenersException Track
TransactionalWriter TransactionRequiredException TransactionRolledbackException Transferable
TransferHandler TransformAttribute Transformer TransformerConfigurationException TransformerException
TransformerFactory TransformerFactoryConfigurationError TransformerHandler Transmitter Transparency
TreeCellEditor TreeCellRenderer TreeExpansionEvent TreeExpansionListener TreeMap TreeModel
TreeModelEvent TreeModelListener TreeNode TreePath TreeSelectionEvent TreeSelectionListener
TreeSelectionModel TreeSet TreeUI TreeWillExpandListener TrustAnchor TrustManager TrustManagerFactory
TrustManagerFactorySpi Type TypeInfoProvider TypeNotPresentException Types TypeVariable UID UIDefaults
UIManager UIResource UndeclaredThrowableException UndoableEdit UndoableEditEvent UndoableEditListener
UndoableEditSupport UndoManager UnexpectedException UnicastRemoteObject UnknownError
UnknownFormatConversionException UnknownFormatFlagsException UnknownGroupException UnknownHostException
UnknownObjectException UnknownServiceException UnmappableCharacterException UnmarshalException
UnmodifiableClassException UnmodifiableSetException UnrecoverableEntryException
UnrecoverableKeyException Unreferenced UnresolvedAddressException UnresolvedPermission
UnsatisfiedLinkError UnsolicitedNotification UnsolicitedNotificationEvent
UnsolicitedNotificationListener UnsupportedAddressTypeException UnsupportedAudioFileException
UnsupportedCallbackException UnsupportedCharsetException UnsupportedClassVersionError
UnsupportedEncodingException UnsupportedFlavorException UnsupportedLookAndFeelException
UnsupportedOperationException URI URIException URIResolver URISyntax URISyntaxException URL
URLClassLoader URLConnection URLDecoder URLEncoder URLStreamHandler URLStreamHandlerFactory
UTFDataFormatException Util UtilDelegate Utilities UUID Validator ValidatorHandler ValueExp ValueHandler
ValueHandlerMultiFormat VariableHeightLayoutCache Vector VerifyError VetoableChangeListener
VetoableChangeListenerProxy VetoableChangeSupport View ViewFactory ViewportLayout ViewportUI
VirtualMachineError Visibility VMID VoiceStatus Void VolatileImage WeakHashMap WeakReference WebRowSet
WildcardType Window WindowAdapter WindowConstants WindowEvent WindowFocusListener WindowListener
WindowStateListener WrappedPlainView WritableByteChannel WritableRaster WritableRenderedImage
WriteAbortedException Writer X500Principal X500PrivateCredential X509Certificate X509CertSelector
X509CRL X509CRLEntry X509CRLSelector X509EncodedKeySpec X509ExtendedKeyManager X509Extension
X509KeyManager X509TrustManager XAConnection XADataSource XAException XAResource Xid XMLConstants
XMLDecoder XMLEncoder XMLFormatter XMLGregorianCalendar XMLParseException XmlReader XmlWriter XPath
XPathConstants XPathException XPathExpression XPathExpressionException XPathFactory
XPathFactoryConfigurationException XPathFunction XPathFunctionException XPathFunctionResolver
XPathVariableResolver ZipEntry ZipException ZipFile ZipInputStream ZipOutputStream ZoneView
]
#:nocov:
end
end
end
coderay-1.1.3/lib/coderay/scanners/java_script.rb 0000664 0000000 0000000 00000017420 13664404461 0022020 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# Scanner for JavaScript.
#
# Aliases: +ecmascript+, +ecma_script+, +javascript+
class JavaScript < Scanner
register_for :java_script
file_extension 'js'
# The actual JavaScript keywords.
KEYWORDS = %w[
break case catch continue default delete do else
finally for function if in instanceof new
return switch throw try typeof var void while with
] # :nodoc:
PREDEFINED_CONSTANTS = %w[
false null true undefined NaN Infinity
] # :nodoc:
MAGIC_VARIABLES = %w[ this arguments ] # :nodoc: arguments was introduced in JavaScript 1.4
KEYWORDS_EXPECTING_VALUE = WordList.new.add %w[
case delete in instanceof new return throw typeof with
] # :nodoc:
# Reserved for future use.
RESERVED_WORDS = %w[
abstract boolean byte char class debugger double enum export extends
final float goto implements import int interface long native package
private protected public short static super synchronized throws transient
volatile
] # :nodoc:
IDENT_KIND = WordList.new(:ident).
add(RESERVED_WORDS, :reserved).
add(PREDEFINED_CONSTANTS, :predefined_constant).
add(MAGIC_VARIABLES, :local_variable).
add(KEYWORDS, :keyword) # :nodoc:
ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
REGEXP_ESCAPE = / [bBdDsSwW] /x # :nodoc:
STRING_CONTENT_PATTERN = {
"'" => /[^\\']+/,
'"' => /[^\\"]+/,
'/' => /[^\\\/]+/,
} # :nodoc:
KEY_CHECK_PATTERN = {
"'" => / (?> [^\\']* (?: \\. [^\\']* )* ) ' \s* : /mx,
'"' => / (?> [^\\"]* (?: \\. [^\\"]* )* ) " \s* : /mx,
} # :nodoc:
protected
def setup
@state = :initial
end
def scan_tokens encoder, options
state, string_delimiter = options[:state] || @state
if string_delimiter
encoder.begin_group state
end
value_expected = true
key_expected = false
function_expected = false
until eos?
case state
when :initial
if match = scan(/ \s+ | \\\n /x)
value_expected = true if !value_expected && match.index(?\n)
encoder.text_token match, :space
elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .*() ) !mx)
value_expected = true
encoder.text_token match, :comment
state = :open_multi_line_comment if self[1]
elsif check(/\.?\d/)
key_expected = value_expected = false
if match = scan(/0[xX][0-9A-Fa-f]+/)
encoder.text_token match, :hex
elsif match = scan(/(?>0[0-7]+)(?![89.eEfF])/)
encoder.text_token match, :octal
elsif match = scan(/\d+[fF]|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/)
encoder.text_token match, :float
elsif match = scan(/\d+/)
encoder.text_token match, :integer
end
elsif value_expected && match = scan(/<([[:alpha:]]\w*) (?: [^\/>]*\/> | .*?<\/\1>)/xim)
# TODO: scan over nested tags
xml_scanner.tokenize match, :tokens => encoder
value_expected = false
elsif match = scan(/ [-+*=<>?:;,!&^|(\[{~%]+ | \.(?!\d) /x)
value_expected = true
last_operator = match[-1]
key_expected = (last_operator == ?{) || (last_operator == ?,)
function_expected = false
encoder.text_token match, :operator
elsif match = scan(/ [)\]}]+ /x)
function_expected = key_expected = value_expected = false
encoder.text_token match, :operator
elsif match = scan(/ [$a-zA-Z_][A-Za-z_0-9$]* /x)
kind = IDENT_KIND[match]
value_expected = (kind == :keyword) && KEYWORDS_EXPECTING_VALUE[match]
# TODO: labels
if kind == :ident
if match.index(?$) # $ allowed inside an identifier
kind = :predefined
elsif function_expected
kind = :function
elsif check(/\s*[=:]\s*function\b/)
kind = :function
elsif key_expected && check(/\s*:/)
kind = :key
end
end
function_expected = (kind == :keyword) && (match == 'function')
key_expected = false
encoder.text_token match, kind
elsif match = scan(/["']/)
if key_expected && check(KEY_CHECK_PATTERN[match])
state = :key
else
state = :string
end
encoder.begin_group state
string_delimiter = match
encoder.text_token match, :delimiter
elsif value_expected && (match = scan(/\//))
encoder.begin_group :regexp
state = :regexp
string_delimiter = '/'
encoder.text_token match, :delimiter
elsif match = scan(/ \/ /x)
value_expected = true
key_expected = false
encoder.text_token match, :operator
else
encoder.text_token getch, :error
end
when :string, :regexp, :key
if match = scan(STRING_CONTENT_PATTERN[string_delimiter])
encoder.text_token match, :content
elsif match = scan(/["'\/]/)
encoder.text_token match, :delimiter
if state == :regexp
modifiers = scan(/[gim]+/)
encoder.text_token modifiers, :modifier if modifiers && !modifiers.empty?
end
encoder.end_group state
string_delimiter = nil
key_expected = value_expected = false
state = :initial
elsif state != :regexp && (match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox))
if string_delimiter == "'" && !(match == "\\\\" || match == "\\'")
encoder.text_token match, :content
else
encoder.text_token match, :char
end
elsif state == :regexp && match = scan(/ \\ (?: #{ESCAPE} | #{REGEXP_ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
encoder.text_token match, :char
elsif match = scan(/\\./m)
encoder.text_token match, :content
elsif match = scan(/ \\ | $ /x)
encoder.end_group state
encoder.text_token match, :error unless match.empty?
string_delimiter = nil
key_expected = value_expected = false
state = :initial
else
raise_inspect "else case #{string_delimiter} reached; %p not handled." % peek(1), encoder
end
when :open_multi_line_comment
if match = scan(%r! .*? \*/ !mx)
state = :initial
else
match = scan(%r! .+ !mx)
end
value_expected = true
encoder.text_token match, :comment if match
else
#:nocov:
raise_inspect 'Unknown state: %p' % [state], encoder
#:nocov:
end
end
if options[:keep_state]
@state = state, string_delimiter
end
if [:string, :regexp].include? state
encoder.end_group state
end
encoder
end
protected
def reset_instance
super
@xml_scanner.reset if defined? @xml_scanner
end
def xml_scanner
@xml_scanner ||= CodeRay.scanner :xml, :tokens => @tokens, :keep_tokens => true, :keep_state => false
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/json.rb 0000664 0000000 0000000 00000005256 13664404461 0020470 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# Scanner for JSON (JavaScript Object Notation).
class JSON < Scanner
register_for :json
file_extension 'json'
KINDS_NOT_LOC = [
:float, :char, :content, :delimiter,
:error, :integer, :operator, :value,
] # :nodoc:
ESCAPE = / [bfnrt\\"\/] /x # :nodoc:
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x # :nodoc:
KEY = / (?> (?: [^\\"]+ | \\. )* ) " \s* : /x
protected
def setup
@state = :initial
end
# See http://json.org/ for a definition of the JSON lexic/grammar.
def scan_tokens encoder, options
state = options[:state] || @state
if [:string, :key].include? state
encoder.begin_group state
end
until eos?
case state
when :initial
if match = scan(/ \s+ /x)
encoder.text_token match, :space
elsif match = scan(/"/)
state = check(/#{KEY}/o) ? :key : :string
encoder.begin_group state
encoder.text_token match, :delimiter
elsif match = scan(/ [:,\[{\]}] /x)
encoder.text_token match, :operator
elsif match = scan(/ true | false | null /x)
encoder.text_token match, :value
elsif match = scan(/ -? (?: 0 | [1-9]\d* ) /x)
if scan(/ \.\d+ (?:[eE][-+]?\d+)? | [eE][-+]? \d+ /x)
match << matched
encoder.text_token match, :float
else
encoder.text_token match, :integer
end
else
encoder.text_token getch, :error
end
when :string, :key
if match = scan(/[^\\"]+/)
encoder.text_token match, :content
elsif match = scan(/"/)
encoder.text_token match, :delimiter
encoder.end_group state
state = :initial
elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
encoder.text_token match, :char
elsif match = scan(/\\./m)
encoder.text_token match, :content
elsif match = scan(/ \\ | $ /x)
encoder.end_group state
encoder.text_token match, :error unless match.empty?
state = :initial
else
raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
end
else
raise_inspect 'Unknown state: %p' % [state], encoder
end
end
if options[:keep_state]
@state = state
end
if [:string, :key].include? state
encoder.end_group state
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/lua.rb 0000664 0000000 0000000 00000025710 13664404461 0020275 0 ustar 00root root 0000000 0000000 # encoding: utf-8
module CodeRay
module Scanners
# Scanner for the Lua[http://lua.org] programming lanuage.
#
# The language’s complete syntax is defined in
# {the Lua manual}[http://www.lua.org/manual/5.2/manual.html],
# which is what this scanner tries to conform to.
class Lua < Scanner
register_for :lua
file_extension 'lua'
title 'Lua'
# Keywords used in Lua.
KEYWORDS = %w[and break do else elseif end
for function goto if in
local not or repeat return
then until while
]
# Constants set by the Lua core.
PREDEFINED_CONSTANTS = %w[false true nil]
# The expressions contained in this array are parts of Lua’s `basic'
# library. Although it’s not entirely necessary to load that library,
# it is highly recommended and one would have to provide own implementations
# of some of these expressions if one does not do so. They however aren’t
# keywords, neither are they constants, but nearly predefined, so they
# get tagged as `predefined' rather than anything else.
#
# This list excludes values of form `_UPPERCASE' because the Lua manual
# requires such identifiers to be reserved by Lua anyway and they are
# highlighted directly accordingly, without the need for specific
# identifiers to be listed here.
PREDEFINED_EXPRESSIONS = %w[
assert collectgarbage dofile error getmetatable
ipairs load loadfile next pairs pcall print
rawequal rawget rawlen rawset select setmetatable
tonumber tostring type xpcall
]
# Automatic token kind selection for normal words.
IDENT_KIND = CodeRay::WordList.new(:ident).
add(KEYWORDS, :keyword).
add(PREDEFINED_CONSTANTS, :predefined_constant).
add(PREDEFINED_EXPRESSIONS, :predefined)
protected
# Scanner initialization.
def setup
@state = :initial
@brace_depth = 0
end
# CodeRay entry hook. Starts parsing.
def scan_tokens(encoder, options)
state = options[:state] || @state
brace_depth = @brace_depth
num_equals = nil
until eos?
case state
when :initial
if match = scan(/\-\-\[\=*\[/) #--[[ long (possibly multiline) comment ]]
num_equals = match.count("=") # Number must match for comment end
encoder.begin_group(:comment)
encoder.text_token(match, :delimiter)
state = :long_comment
elsif match = scan(/--.*$/) # --Lua comment
encoder.text_token(match, :comment)
elsif match = scan(/\[=*\[/) # [[ long (possibly multiline) string ]]
num_equals = match.count("=") # Number must match for string end
encoder.begin_group(:string)
encoder.text_token(match, :delimiter)
state = :long_string
elsif match = scan(/::\s*[a-zA-Z_][a-zA-Z0-9_]+\s*::/) # ::goto_label::
encoder.text_token(match, :label)
elsif match = scan(/_[A-Z]+/) # _UPPERCASE are names reserved for Lua
encoder.text_token(match, :predefined)
elsif match = scan(/[a-zA-Z_][a-zA-Z0-9_]*/) # Normal letters (or letters followed by digits)
kind = IDENT_KIND[match]
# Extra highlighting for entities following certain keywords
if kind == :keyword and match == "function"
state = :function_expected
elsif kind == :keyword and match == "goto"
state = :goto_label_expected
elsif kind == :keyword and match == "local"
state = :local_var_expected
end
encoder.text_token(match, kind)
elsif match = scan(/\{/) # Opening table brace {
encoder.begin_group(:map)
encoder.text_token(match, brace_depth >= 1 ? :inline_delimiter : :delimiter)
brace_depth += 1
state = :map
elsif match = scan(/\}/) # Closing table brace }
if brace_depth == 1
brace_depth = 0
encoder.text_token(match, :delimiter)
encoder.end_group(:map)
elsif brace_depth == 0 # Mismatched brace
encoder.text_token(match, :error)
else
brace_depth -= 1
encoder.text_token(match, :inline_delimiter)
encoder.end_group(:map)
state = :map
end
elsif match = scan(/["']/) # String delimiters " and '
encoder.begin_group(:string)
encoder.text_token(match, :delimiter)
start_delim = match
state = :string
# ↓Prefix hex number ←|→ decimal number
elsif match = scan(/-? (?:0x\h* \. \h+ (?:p[+\-]?\d+)? | \d*\.\d+ (?:e[+\-]?\d+)?)/ix) # hexadecimal constants have no E power, decimal ones no P power
encoder.text_token(match, :float)
# ↓Prefix hex number ←|→ decimal number
elsif match = scan(/-? (?:0x\h+ (?:p[+\-]?\d+)? | \d+ (?:e[+\-]?\d+)?)/ix) # hexadecimal constants have no E power, decimal ones no P power
encoder.text_token(match, :integer)
elsif match = scan(/[\+\-\*\/%^\#=~<>\(\)\[\]:;,] | \.(?!\d)/x) # Operators
encoder.text_token(match, :operator)
elsif match = scan(/\s+/) # Space
encoder.text_token(match, :space)
else # Invalid stuff. Note that Lua doesn’t accept multibyte chars outside of strings, hence these are also errors.
encoder.text_token(getch, :error)
end
# It may be that we’re scanning a full-blown subexpression of a table
# (tables can contain full expressions in parts).
# If this is the case, return to :map scanning state.
state = :map if state == :initial && brace_depth >= 1
when :function_expected
if match = scan(/\(.*?\)/m) # x = function() # "Anonymous" function without explicit name
encoder.text_token(match, :operator)
state = :initial
elsif match = scan(/[a-zA-Z_] (?:[a-zA-Z0-9_\.] (?!\.\d))* [\.\:]/x) # function tbl.subtbl.foo() | function tbl:foo() # Colon only allowed as last separator
encoder.text_token(match, :ident)
elsif match = scan(/[a-zA-Z_][a-zA-Z0-9_]*/) # function foo()
encoder.text_token(match, :function)
state = :initial
elsif match = scan(/\s+/) # Between the `function' keyword and the ident may be any amount of whitespace
encoder.text_token(match, :space)
else
encoder.text_token(getch, :error)
state = :initial
end
when :goto_label_expected
if match = scan(/[a-zA-Z_][a-zA-Z0-9_]*/)
encoder.text_token(match, :label)
state = :initial
elsif match = scan(/\s+/) # Between the `goto' keyword and the label may be any amount of whitespace
encoder.text_token(match, :space)
else
encoder.text_token(getch, :error)
end
when :local_var_expected
if match = scan(/function/) # local function ...
encoder.text_token(match, :keyword)
state = :function_expected
elsif match = scan(/[a-zA-Z_][a-zA-Z0-9_]*/)
encoder.text_token(match, :local_variable)
elsif match = scan(/,/)
encoder.text_token(match, :operator)
elsif match = scan(/\=/)
encoder.text_token(match, :operator)
# After encountering the equal sign, arbitrary expressions are
# allowed again, so just return to the main state for further
# parsing.
state = :initial
elsif match = scan(/\n/)
encoder.text_token(match, :space)
state = :initial
elsif match = scan(/\s+/)
encoder.text_token(match, :space)
else
encoder.text_token(getch, :error)
end
when :long_comment
if match = scan(/.*?(?=\]={#{num_equals}}\])/m)
encoder.text_token(match, :content)
delim = scan(/\]={#{num_equals}}\]/)
encoder.text_token(delim, :delimiter)
else # No terminator found till EOF
encoder.text_token(rest, :error)
terminate
end
encoder.end_group(:comment)
state = :initial
when :long_string
if match = scan(/.*?(?=\]={#{num_equals}}\])/m) # Long strings do not interpret any escape sequences
encoder.text_token(match, :content)
delim = scan(/\]={#{num_equals}}\]/)
encoder.text_token(delim, :delimiter)
else # No terminator found till EOF
encoder.text_token(rest, :error)
terminate
end
encoder.end_group(:string)
state = :initial
when :string
if match = scan(/[^\\#{start_delim}\n]+/) # Everything except \ and the start delimiter character is string content (newlines are only allowed if preceeded by \ or \z)
encoder.text_token(match, :content)
elsif match = scan(/\\(?:['"abfnrtv\\]|z\s*|x\h\h|\d{1,3}|\n)/m)
encoder.text_token(match, :char)
elsif match = scan(Regexp.compile(start_delim))
encoder.text_token(match, :delimiter)
encoder.end_group(:string)
state = :initial
elsif match = scan(/\n/) # Lua forbids unescaped newlines in normal non-long strings
encoder.text_token("\\n\n", :error) # Visually appealing error indicator--otherwise users may wonder whether the highlighter cannot highlight multine strings
encoder.end_group(:string)
state = :initial
else
encoder.text_token(getch, :error)
end
when :map
if match = scan(/[,;]/)
encoder.text_token(match, :operator)
elsif match = scan(/[a-zA-Z_][a-zA-Z0-9_]* (?=\s*=)/x)
encoder.text_token(match, :key)
encoder.text_token(scan(/\s+/), :space) if check(/\s+/)
encoder.text_token(scan(/\=/), :operator)
state = :initial
elsif match = scan(/\s+/m)
encoder.text_token(match, :space)
else
# Note this clause doesn’t advance the scan pointer, it’s a kind of
# "retry with other options" (the :initial state then of course
# advances the pointer).
state = :initial
end
else
raise
end
end
if options[:keep_state]
@state = state
end
encoder.end_group :string if [:string].include? state
brace_depth.times { encoder.end_group :map }
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/php.rb 0000664 0000000 0000000 00000060552 13664404461 0020306 0 ustar 00root root 0000000 0000000 # encoding: utf-8
module CodeRay
module Scanners
load :html
# Scanner for PHP.
#
# Original by Stefan Walk.
class PHP < Scanner
register_for :php
file_extension 'php'
KINDS_NOT_LOC = HTML::KINDS_NOT_LOC
protected
def setup
@html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true, :keep_state => true
end
def reset_instance
super
@html_scanner.reset
end
module Words # :nodoc:
# according to http://www.php.net/manual/en/reserved.keywords.php
KEYWORDS = %w[
abstract and array as break case catch class clone const continue declare default do else elseif
enddeclare endfor endforeach endif endswitch endwhile extends final for foreach function global
goto if implements interface instanceof namespace new or private protected public static switch
throw try use var while xor
cfunction old_function
]
TYPES = %w[ int integer float double bool boolean string array object resource ]
LANGUAGE_CONSTRUCTS = %w[
die echo empty exit eval include include_once isset list
require require_once return print unset
]
CLASSES = %w[ Directory stdClass __PHP_Incomplete_Class exception php_user_filter Closure ]
# according to http://php.net/quickref.php on 2009-04-21;
# all functions with _ excluded (module functions) and selected additional functions
BUILTIN_FUNCTIONS = %w[
abs acos acosh addcslashes addslashes aggregate array arsort ascii2ebcdic asin asinh asort assert atan atan2
atanh basename bcadd bccomp bcdiv bcmod bcmul bcpow bcpowmod bcscale bcsqrt bcsub bin2hex bindec
bindtextdomain bzclose bzcompress bzdecompress bzerrno bzerror bzerrstr bzflush bzopen bzread bzwrite
calculhmac ceil chdir checkdate checkdnsrr chgrp chmod chop chown chr chroot clearstatcache closedir closelog
compact constant copy cos cosh count crc32 crypt current date dcgettext dcngettext deaggregate decbin dechex
decoct define defined deg2rad delete dgettext die dirname diskfreespace dl dngettext doubleval each
ebcdic2ascii echo empty end ereg eregi escapeshellarg escapeshellcmd eval exec exit exp explode expm1 extract
fclose feof fflush fgetc fgetcsv fgets fgetss file fileatime filectime filegroup fileinode filemtime fileowner
fileperms filepro filesize filetype floatval flock floor flush fmod fnmatch fopen fpassthru fprintf fputcsv
fputs fread frenchtojd fscanf fseek fsockopen fstat ftell ftok ftruncate fwrite getallheaders getcwd getdate
getenv gethostbyaddr gethostbyname gethostbynamel getimagesize getlastmod getmxrr getmygid getmyinode getmypid
getmyuid getopt getprotobyname getprotobynumber getrandmax getrusage getservbyname getservbyport gettext
gettimeofday gettype glob gmdate gmmktime gmstrftime gregoriantojd gzclose gzcompress gzdecode gzdeflate
gzencode gzeof gzfile gzgetc gzgets gzgetss gzinflate gzopen gzpassthru gzputs gzread gzrewind gzseek gztell
gzuncompress gzwrite hash header hebrev hebrevc hexdec htmlentities htmlspecialchars hypot iconv idate
implode include intval ip2long iptcembed iptcparse isset
jddayofweek jdmonthname jdtofrench jdtogregorian jdtojewish jdtojulian jdtounix jewishtojd join jpeg2wbmp
juliantojd key krsort ksort lcfirst lchgrp lchown levenshtein link linkinfo list localeconv localtime log
log10 log1p long2ip lstat ltrim mail main max md5 metaphone mhash microtime min mkdir mktime msql natcasesort
natsort next ngettext nl2br nthmac octdec opendir openlog
ord overload pack passthru pathinfo pclose pfsockopen phpcredits phpinfo phpversion pi png2wbmp popen pos pow
prev print printf putenv quotemeta rad2deg rand range rawurldecode rawurlencode readdir readfile readgzfile
readline readlink realpath recode rename require reset rewind rewinddir rmdir round rsort rtrim scandir
serialize setcookie setlocale setrawcookie settype sha1 shuffle signeurlpaiement sin sinh sizeof sleep snmpget
snmpgetnext snmprealwalk snmpset snmpwalk snmpwalkoid sort soundex split spliti sprintf sqrt srand sscanf stat
strcasecmp strchr strcmp strcoll strcspn strftime stripcslashes stripos stripslashes stristr strlen
strnatcasecmp strnatcmp strncasecmp strncmp strpbrk strpos strptime strrchr strrev strripos strrpos strspn
strstr strtok strtolower strtotime strtoupper strtr strval substr symlink syslog system tan tanh tempnam
textdomain time tmpfile touch trim uasort ucfirst ucwords uksort umask uniqid unixtojd unlink unpack
unserialize unset urldecode urlencode usleep usort vfprintf virtual vprintf vsprintf wordwrap
array_change_key_case array_chunk array_combine array_count_values array_diff array_diff_assoc
array_diff_key array_diff_uassoc array_diff_ukey array_fill array_fill_keys array_filter array_flip
array_intersect array_intersect_assoc array_intersect_key array_intersect_uassoc array_intersect_ukey
array_key_exists array_keys array_map array_merge array_merge_recursive array_multisort array_pad
array_pop array_product array_push array_rand array_reduce array_reverse array_search array_shift
array_slice array_splice array_sum array_udiff array_udiff_assoc array_udiff_uassoc array_uintersect
array_uintersect_assoc array_uintersect_uassoc array_unique array_unshift array_values array_walk
array_walk_recursive
assert_options base_convert base64_decode base64_encode
chunk_split class_exists class_implements class_parents
count_chars debug_backtrace debug_print_backtrace debug_zval_dump
error_get_last error_log error_reporting extension_loaded
file_exists file_get_contents file_put_contents load_file
func_get_arg func_get_args func_num_args function_exists
get_browser get_called_class get_cfg_var get_class get_class_methods get_class_vars
get_current_user get_declared_classes get_declared_interfaces get_defined_constants
get_defined_functions get_defined_vars get_extension_funcs get_headers get_html_translation_table
get_include_path get_included_files get_loaded_extensions get_magic_quotes_gpc get_magic_quotes_runtime
get_meta_tags get_object_vars get_parent_class get_required_filesget_resource_type
gc_collect_cycles gc_disable gc_enable gc_enabled
halt_compiler headers_list headers_sent highlight_file highlight_string
html_entity_decode htmlspecialchars_decode
in_array include_once inclued_get_data
is_a is_array is_binary is_bool is_buffer is_callable is_dir is_double is_executable is_file is_finite
is_float is_infinite is_int is_integer is_link is_long is_nan is_null is_numeric is_object is_readable
is_real is_resource is_scalar is_soap_fault is_string is_subclass_of is_unicode is_uploaded_file
is_writable is_writeable
locale_get_default locale_set_default
number_format override_function parse_str parse_url
php_check_syntax php_ini_loaded_file php_ini_scanned_files php_logo_guid php_sapi_name
php_strip_whitespace php_uname
preg_filter preg_grep preg_last_error preg_match preg_match_all preg_quote preg_replace
preg_replace_callback preg_split print_r
require_once register_shutdown_function register_tick_function
set_error_handler set_exception_handler set_file_buffer set_include_path
set_magic_quotes_runtime set_time_limit shell_exec
str_getcsv str_ireplace str_pad str_repeat str_replace str_rot13 str_shuffle str_split str_word_count
strip_tags substr_compare substr_count substr_replace
time_nanosleep time_sleep_until
token_get_all token_name trigger_error
unregister_tick_function use_soap_error_handler user_error
utf8_decode utf8_encode var_dump var_export
version_compare
zend_logo_guid zend_thread_id zend_version
create_function call_user_func_array
posix_access posix_ctermid posix_get_last_error posix_getcwd posix_getegid
posix_geteuid posix_getgid posix_getgrgid posix_getgrnam posix_getgroups
posix_getlogin posix_getpgid posix_getpgrp posix_getpid posix_getppid
posix_getpwnam posix_getpwuid posix_getrlimit posix_getsid posix_getuid
posix_initgroups posix_isatty posix_kill posix_mkfifo posix_mknod
posix_setegid posix_seteuid posix_setgid posix_setpgid posix_setsid
posix_setuid posix_strerror posix_times posix_ttyname posix_uname
pcntl_alarm pcntl_exec pcntl_fork pcntl_getpriority pcntl_setpriority
pcntl_signal pcntl_signal_dispatch pcntl_sigprocmask pcntl_sigtimedwait
pcntl_sigwaitinfo pcntl_wait pcntl_waitpid pcntl_wexitstatus pcntl_wifexited
pcntl_wifsignaled pcntl_wifstopped pcntl_wstopsig pcntl_wtermsig
]
# TODO: more built-in PHP functions?
EXCEPTIONS = %w[
E_ERROR E_WARNING E_PARSE E_NOTICE E_CORE_ERROR E_CORE_WARNING E_COMPILE_ERROR E_COMPILE_WARNING
E_USER_ERROR E_USER_WARNING E_USER_NOTICE E_DEPRECATED E_USER_DEPRECATED E_ALL E_STRICT
]
CONSTANTS = %w[
null true false self parent
__LINE__ __DIR__ __FILE__ __LINE__
__CLASS__ __NAMESPACE__ __METHOD__ __FUNCTION__
PHP_VERSION PHP_MAJOR_VERSION PHP_MINOR_VERSION PHP_RELEASE_VERSION PHP_VERSION_ID PHP_EXTRA_VERSION PHP_ZTS
PHP_DEBUG PHP_MAXPATHLEN PHP_OS PHP_SAPI PHP_EOL PHP_INT_MAX PHP_INT_SIZE DEFAULT_INCLUDE_PATH
PEAR_INSTALL_DIR PEAR_EXTENSION_DIR PHP_EXTENSION_DIR PHP_PREFIX PHP_BINDIR PHP_LIBDIR PHP_DATADIR
PHP_SYSCONFDIR PHP_LOCALSTATEDIR PHP_CONFIG_FILE_PATH PHP_CONFIG_FILE_SCAN_DIR PHP_SHLIB_SUFFIX
PHP_OUTPUT_HANDLER_START PHP_OUTPUT_HANDLER_CONT PHP_OUTPUT_HANDLER_END
__COMPILER_HALT_OFFSET__
EXTR_OVERWRITE EXTR_SKIP EXTR_PREFIX_SAME EXTR_PREFIX_ALL EXTR_PREFIX_INVALID EXTR_PREFIX_IF_EXISTS
EXTR_IF_EXISTS SORT_ASC SORT_DESC SORT_REGULAR SORT_NUMERIC SORT_STRING CASE_LOWER CASE_UPPER COUNT_NORMAL
COUNT_RECURSIVE ASSERT_ACTIVE ASSERT_CALLBACK ASSERT_BAIL ASSERT_WARNING ASSERT_QUIET_EVAL CONNECTION_ABORTED
CONNECTION_NORMAL CONNECTION_TIMEOUT INI_USER INI_PERDIR INI_SYSTEM INI_ALL M_E M_LOG2E M_LOG10E M_LN2 M_LN10
M_PI M_PI_2 M_PI_4 M_1_PI M_2_PI M_2_SQRTPI M_SQRT2 M_SQRT1_2 CRYPT_SALT_LENGTH CRYPT_STD_DES CRYPT_EXT_DES
CRYPT_MD5 CRYPT_BLOWFISH DIRECTORY_SEPARATOR SEEK_SET SEEK_CUR SEEK_END LOCK_SH LOCK_EX LOCK_UN LOCK_NB
HTML_SPECIALCHARS HTML_ENTITIES ENT_COMPAT ENT_QUOTES ENT_NOQUOTES INFO_GENERAL INFO_CREDITS
INFO_CONFIGURATION INFO_MODULES INFO_ENVIRONMENT INFO_VARIABLES INFO_LICENSE INFO_ALL CREDITS_GROUP
CREDITS_GENERAL CREDITS_SAPI CREDITS_MODULES CREDITS_DOCS CREDITS_FULLPAGE CREDITS_QA CREDITS_ALL STR_PAD_LEFT
STR_PAD_RIGHT STR_PAD_BOTH PATHINFO_DIRNAME PATHINFO_BASENAME PATHINFO_EXTENSION PATH_SEPARATOR CHAR_MAX
LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_ALL LC_MESSAGES ABDAY_1 ABDAY_2 ABDAY_3 ABDAY_4 ABDAY_5
ABDAY_6 ABDAY_7 DAY_1 DAY_2 DAY_3 DAY_4 DAY_5 DAY_6 DAY_7 ABMON_1 ABMON_2 ABMON_3 ABMON_4 ABMON_5 ABMON_6
ABMON_7 ABMON_8 ABMON_9 ABMON_10 ABMON_11 ABMON_12 MON_1 MON_2 MON_3 MON_4 MON_5 MON_6 MON_7 MON_8 MON_9
MON_10 MON_11 MON_12 AM_STR PM_STR D_T_FMT D_FMT T_FMT T_FMT_AMPM ERA ERA_YEAR ERA_D_T_FMT ERA_D_FMT ERA_T_FMT
ALT_DIGITS INT_CURR_SYMBOL CURRENCY_SYMBOL CRNCYSTR MON_DECIMAL_POINT MON_THOUSANDS_SEP MON_GROUPING
POSITIVE_SIGN NEGATIVE_SIGN INT_FRAC_DIGITS FRAC_DIGITS P_CS_PRECEDES P_SEP_BY_SPACE N_CS_PRECEDES
N_SEP_BY_SPACE P_SIGN_POSN N_SIGN_POSN DECIMAL_POINT RADIXCHAR THOUSANDS_SEP THOUSEP GROUPING YESEXPR NOEXPR
YESSTR NOSTR CODESET LOG_EMERG LOG_ALERT LOG_CRIT LOG_ERR LOG_WARNING LOG_NOTICE LOG_INFO LOG_DEBUG LOG_KERN
LOG_USER LOG_MAIL LOG_DAEMON LOG_AUTH LOG_SYSLOG LOG_LPR LOG_NEWS LOG_UUCP LOG_CRON LOG_AUTHPRIV LOG_LOCAL0
LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4 LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7 LOG_PID LOG_CONS LOG_ODELAY
LOG_NDELAY LOG_NOWAIT LOG_PERROR
]
PREDEFINED = %w[
$GLOBALS $_SERVER $_GET $_POST $_FILES $_REQUEST $_SESSION $_ENV
$_COOKIE $php_errormsg $HTTP_RAW_POST_DATA $http_response_header
$argc $argv
]
IDENT_KIND = WordList::CaseIgnoring.new(:ident).
add(KEYWORDS, :keyword).
add(TYPES, :predefined_type).
add(LANGUAGE_CONSTRUCTS, :keyword).
add(BUILTIN_FUNCTIONS, :predefined).
add(CLASSES, :predefined_constant).
add(EXCEPTIONS, :exception).
add(CONSTANTS, :predefined_constant)
VARIABLE_KIND = WordList.new(:local_variable).
add(PREDEFINED, :predefined)
end
module RE # :nodoc:
PHP_START = /
|
\?>
!xi
HTML_INDICATOR = / ]/i
IDENTIFIER = 'ä'[/[[:alpha:]]/] == 'ä' ? Regexp.new('[[:alpha:]_[^\0-\177]][[:alnum:]_[^\0-\177]]*') : Regexp.new('[a-z_\x7f-\xFF][a-z0-9_\x7f-\xFF]*', true)
VARIABLE = /\$#{IDENTIFIER}/
OPERATOR = /
\.(?!\d)=? | # dot that is not decimal point, string concatenation
&& | \|\| | # logic
:: | -> | => | # scope, member, dictionary
\\(?!\n) | # namespace
\+\+ | -- | # increment, decrement
[,;?:()\[\]{}] | # simple delimiters
[-+*\/%&|^]=? | # ordinary math, binary logic, assignment shortcuts
[~$] | # whatever
=& | # reference assignment
[=!]=?=? | <> | # comparison and assignment
<<=? | >>=? | [<>]=? # comparison and shift
/x
end
protected
def scan_tokens encoder, options
if check(RE::PHP_START) || # starts with
(match?(/\s*<\S/) && check(/.{1,1000}#{RE::PHP_START}/om)) || # starts with tag and contains
check(/.{0,1000}#{RE::HTML_INDICATOR}/om) ||
check(/.{1,100}#{RE::PHP_START}/om) # PHP start after max 100 chars
# is HTML with embedded PHP, so start with HTML
states = [:initial]
else
# is just PHP, so start with PHP surrounded by HTML
states = [:initial, :php]
end
label_expected = true
case_expected = false
heredoc_delimiter = nil
delimiter = nil
modifier = nil
until eos?
case states.last
when :initial # HTML
if match = scan(RE::PHP_START)
encoder.text_token match, :inline_delimiter
label_expected = true
states << :php
else
match = scan_until(/(?=#{RE::PHP_START})/o) || scan_rest
@html_scanner.tokenize match unless match.empty?
end
when :php, :php_inline
if match = scan(/\s+/)
encoder.text_token match, :space
elsif match = scan(%r! (?m: \/\* (?: .*? \*\/ | .* ) ) | (?://|\#) .*? (?=#{RE::PHP_END}|$) !xo)
encoder.text_token match, :comment
elsif match = scan(RE::IDENTIFIER)
kind = Words::IDENT_KIND[match]
if kind == :ident && label_expected && check(/:(?!:)/)
kind = :label
label_expected = true
else
label_expected = false
if kind == :ident && match =~ /^[A-Z]/
kind = :constant
elsif kind == :keyword
case match
when 'class'
states << :class_expected
when 'function'
states << :function_expected
when 'case', 'default'
case_expected = true
end
elsif match == 'b' && check(/['"]/) # binary string literal
modifier = match
next
end
end
encoder.text_token match, kind
elsif match = scan(/(?:\d+\.\d*|\d*\.\d+)(?:e[-+]?\d+)?|\d+e[-+]?\d+/i)
label_expected = false
encoder.text_token match, :float
elsif match = scan(/0x[0-9a-fA-F]+/)
label_expected = false
encoder.text_token match, :hex
elsif match = scan(/\d+/)
label_expected = false
encoder.text_token match, :integer
elsif match = scan(/['"`]/)
encoder.begin_group :string
if modifier
encoder.text_token modifier, :modifier
modifier = nil
end
delimiter = match
encoder.text_token match, :delimiter
states.push match == "'" ? :sqstring : :dqstring
elsif match = scan(RE::VARIABLE)
label_expected = false
encoder.text_token match, Words::VARIABLE_KIND[match]
elsif match = scan(/\{/)
encoder.text_token match, :operator
label_expected = true
states.push :php
elsif match = scan(/\}/)
if states.size == 1
encoder.text_token match, :error
else
state = states.pop
if states.last.is_a?(::Array)
delimiter = states.last[1]
states[-1] = states.last[0]
encoder.text_token match, :delimiter
encoder.end_group :inline
else
encoder.text_token match, :operator
encoder.end_group :inline if state == :php_inline
label_expected = true
end
end
elsif match = scan(/@/)
label_expected = false
encoder.text_token match, :exception
elsif match = scan(RE::PHP_END)
encoder.text_token match, :inline_delimiter
while state = states.pop
encoder.end_group :string if [:sqstring, :dqstring].include? state
if state.is_a? Array
encoder.end_group :inline
encoder.end_group :string if [:sqstring, :dqstring].include? state.first
end
end
states << :initial
elsif match = scan(/<<<(?:(#{RE::IDENTIFIER})|"(#{RE::IDENTIFIER})"|'(#{RE::IDENTIFIER})')/o)
encoder.begin_group :string
# warn 'heredoc in heredoc?' if heredoc_delimiter
heredoc_delimiter = Regexp.escape(self[1] || self[2] || self[3])
encoder.text_token match, :delimiter
states.push self[3] ? :sqstring : :dqstring
heredoc_delimiter = /#{heredoc_delimiter}(?=;?$)/
elsif match = scan(/#{RE::OPERATOR}/o)
label_expected = match == ';'
if case_expected
label_expected = true if match == ':'
case_expected = false
end
encoder.text_token match, :operator
else
encoder.text_token getch, :error
end
when :sqstring
if match = scan(heredoc_delimiter ? /[^\\\n]+/ : /[^'\\]+/)
encoder.text_token match, :content
elsif !heredoc_delimiter && match = scan(/'/)
encoder.text_token match, :delimiter
encoder.end_group :string
delimiter = nil
label_expected = false
states.pop
elsif heredoc_delimiter && match = scan(/\n/)
if scan heredoc_delimiter
encoder.text_token "\n", :content
encoder.text_token matched, :delimiter
encoder.end_group :string
heredoc_delimiter = nil
label_expected = false
states.pop
else
encoder.text_token match, :content
end
elsif match = scan(heredoc_delimiter ? /\\\\/ : /\\[\\'\n]/)
encoder.text_token match, :char
elsif match = scan(/\\./m)
encoder.text_token match, :content
elsif match = scan(/\\/)
encoder.text_token match, :error
else
encoder.end_group :string
states.pop
end
when :dqstring
if match = scan(heredoc_delimiter ? /[^${\\\n]+/ : (delimiter == '"' ? /[^"${\\]+/ : /[^`${\\]+/))
encoder.text_token match, :content
elsif !heredoc_delimiter && match = scan(delimiter == '"' ? /"/ : /`/)
encoder.text_token match, :delimiter
encoder.end_group :string
delimiter = nil
label_expected = false
states.pop
elsif heredoc_delimiter && match = scan(/\n/)
if scan heredoc_delimiter
encoder.text_token "\n", :content
encoder.text_token matched, :delimiter
encoder.end_group :string
heredoc_delimiter = nil
label_expected = false
states.pop
else
encoder.text_token match, :content
end
elsif match = scan(/\\(?:x[0-9A-Fa-f]{1,2}|[0-7]{1,3})/)
encoder.text_token match, :char
elsif match = scan(heredoc_delimiter ? /\\[nrtvf\\$]/ : (delimiter == '"' ? /\\[nrtvf\\$"]/ : /\\[nrtvf\\$`]/))
encoder.text_token match, :char
elsif match = scan(/\\./m)
encoder.text_token match, :content
elsif match = scan(/\\/)
encoder.text_token match, :error
elsif match = scan(/#{RE::VARIABLE}/o)
if check(/\[#{RE::IDENTIFIER}\]/o)
encoder.begin_group :inline
encoder.text_token match, :local_variable
encoder.text_token scan(/\[/), :operator
encoder.text_token scan(/#{RE::IDENTIFIER}/o), :ident
encoder.text_token scan(/\]/), :operator
encoder.end_group :inline
elsif check(/\[/)
match << scan(/\[['"]?#{RE::IDENTIFIER}?['"]?\]?/o)
encoder.text_token match, :error
elsif check(/->#{RE::IDENTIFIER}/o)
encoder.begin_group :inline
encoder.text_token match, :local_variable
encoder.text_token scan(/->/), :operator
encoder.text_token scan(/#{RE::IDENTIFIER}/o), :ident
encoder.end_group :inline
elsif check(/->/)
match << scan(/->/)
encoder.text_token match, :error
else
encoder.text_token match, :local_variable
end
elsif match = scan(/\{/)
if check(/\$/)
encoder.begin_group :inline
states[-1] = [states.last, delimiter]
delimiter = nil
states.push :php_inline
encoder.text_token match, :delimiter
else
encoder.text_token match, :content
end
elsif match = scan(/\$\{#{RE::IDENTIFIER}\}/o)
encoder.text_token match, :local_variable
elsif match = scan(/\$/)
encoder.text_token match, :content
else
encoder.end_group :string
states.pop
end
when :class_expected
if match = scan(/\s+/)
encoder.text_token match, :space
elsif match = scan(/#{RE::IDENTIFIER}/o)
encoder.text_token match, :class
states.pop
else
states.pop
end
when :function_expected
if match = scan(/\s+/)
encoder.text_token match, :space
elsif match = scan(/&/)
encoder.text_token match, :operator
elsif match = scan(/#{RE::IDENTIFIER}/o)
encoder.text_token match, :function
states.pop
else
states.pop
end
else
raise_inspect 'Unknown state!', encoder, states
end
end
while state = states.pop
encoder.end_group :string if [:sqstring, :dqstring].include? state
if state.is_a? Array
encoder.end_group :inline
encoder.end_group :string if [:sqstring, :dqstring].include? state.first
end
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/python.rb 0000664 0000000 0000000 00000023606 13664404461 0021037 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# Scanner for Python. Supports Python 3.
#
# Based on pygments' PythonLexer, see
# http://dev.pocoo.org/projects/pygments/browser/pygments/lexers/agile.py.
class Python < Scanner
register_for :python
file_extension 'py'
KEYWORDS = [
'and', 'as', 'assert', 'break', 'class', 'continue', 'def',
'del', 'elif', 'else', 'except', 'finally', 'for',
'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not',
'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield',
'nonlocal', # new in Python 3
] # :nodoc:
OLD_KEYWORDS = [
'exec', 'print', # gone in Python 3
] # :nodoc:
PREDEFINED_METHODS_AND_TYPES = %w[
__import__ abs all any apply basestring bin bool buffer
bytearray bytes callable chr classmethod cmp coerce compile
complex delattr dict dir divmod enumerate eval execfile exit
file filter float frozenset getattr globals hasattr hash hex id
input int intern isinstance issubclass iter len list locals
long map max min next object oct open ord pow property range
raw_input reduce reload repr reversed round set setattr slice
sorted staticmethod str sum super tuple type unichr unicode
vars xrange zip
] # :nodoc:
PREDEFINED_EXCEPTIONS = %w[
ArithmeticError AssertionError AttributeError
BaseException DeprecationWarning EOFError EnvironmentError
Exception FloatingPointError FutureWarning GeneratorExit IOError
ImportError ImportWarning IndentationError IndexError KeyError
KeyboardInterrupt LookupError MemoryError NameError
NotImplemented NotImplementedError OSError OverflowError
OverflowWarning PendingDeprecationWarning ReferenceError
RuntimeError RuntimeWarning StandardError StopIteration
SyntaxError SyntaxWarning SystemError SystemExit TabError
TypeError UnboundLocalError UnicodeDecodeError
UnicodeEncodeError UnicodeError UnicodeTranslateError
UnicodeWarning UserWarning ValueError Warning ZeroDivisionError
] # :nodoc:
PREDEFINED_VARIABLES_AND_CONSTANTS = [
'False', 'True', 'None', # "keywords" since Python 3
'self', 'Ellipsis', 'NotImplemented',
] # :nodoc:
IDENT_KIND = WordList.new(:ident).
add(KEYWORDS, :keyword).
add(OLD_KEYWORDS, :old_keyword).
add(PREDEFINED_METHODS_AND_TYPES, :predefined).
add(PREDEFINED_VARIABLES_AND_CONSTANTS, :predefined_constant).
add(PREDEFINED_EXCEPTIONS, :exception) # :nodoc:
NAME = / [[:alpha:]_] \w* /x # :nodoc:
ESCAPE = / [abfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} | N\{[-\w ]+\} /x # :nodoc:
OPERATOR = /
\.\.\. | # ellipsis
\.(?!\d) | # dot but not decimal point
[,;:()\[\]{}] | # simple delimiters
\/\/=? | \*\*=? | # special math
[-+*\/%&|^]=? | # ordinary math and binary logic
[~`] | # binary complement and inspection
<<=? | >>=? | [<>=]=? | != # comparison and assignment
/x # :nodoc:
STRING_DELIMITER_REGEXP = Hash.new { |h, delimiter|
h[delimiter] = Regexp.union delimiter # :nodoc:
}
STRING_CONTENT_REGEXP = Hash.new { |h, delimiter|
h[delimiter] = / [^\\\n]+? (?= \\ | $ | #{Regexp.escape(delimiter)} ) /x # :nodoc:
}
DEF_NEW_STATE = WordList.new(:initial).
add(%w(def), :def_expected).
add(%w(import from), :include_expected).
add(%w(class), :class_expected) # :nodoc:
DESCRIPTOR = /
#{NAME}
(?: \. #{NAME} )*
| \*
/x # :nodoc:
DOCSTRING_COMING = /
[ \t]* u?r? ("""|''')
/x # :nodoc:
protected
def scan_tokens encoder, options
state = :initial
string_delimiter = nil
string_raw = false
string_type = nil
docstring_coming = match?(/#{DOCSTRING_COMING}/o)
last_token_dot = false
unicode = string.respond_to?(:encoding) && string.encoding.name == 'UTF-8'
from_import_state = []
until eos?
if state == :string
if match = scan(STRING_DELIMITER_REGEXP[string_delimiter])
encoder.text_token match, :delimiter
encoder.end_group string_type
string_type = nil
state = :initial
next
elsif string_delimiter.size == 3 && match = scan(/\n/)
encoder.text_token match, :content
elsif match = scan(STRING_CONTENT_REGEXP[string_delimiter])
encoder.text_token match, :content
elsif !string_raw && match = scan(/ \\ #{ESCAPE} /ox)
encoder.text_token match, :char
elsif match = scan(/ \\ #{UNICODE_ESCAPE} /ox)
encoder.text_token match, :char
elsif match = scan(/ \\ . /x)
encoder.text_token match, :content
elsif match = scan(/ \\ | $ /x)
encoder.end_group string_type
string_type = nil
encoder.text_token match, :error unless match.empty?
state = :initial
else
raise_inspect "else case \" reached; %p not handled." % peek(1), encoder, state
end
elsif match = scan(/ [ \t]+ | \\?\n /x)
encoder.text_token match, :space
if match == "\n"
state = :initial if state == :include_expected
docstring_coming = true if match?(/#{DOCSTRING_COMING}/o)
end
next
elsif match = scan(/ \# [^\n]* /mx)
encoder.text_token match, :comment
next
elsif state == :initial
if match = scan(/#{OPERATOR}/o)
encoder.text_token match, :operator
elsif match = scan(/(u?r?|b)?("""|"|'''|')/i)
modifiers = self[1]
string_delimiter = self[2]
string_type = docstring_coming ? :docstring : (modifiers == 'b' ? :binary : :string)
docstring_coming = false if docstring_coming
encoder.begin_group string_type
string_raw = false
unless modifiers.empty?
string_raw = !!modifiers.index(?r)
encoder.text_token modifiers, :modifier
match = string_delimiter
end
state = :string
encoder.text_token match, :delimiter
# TODO: backticks
elsif match = scan(unicode ? /#{NAME}/uo : /#{NAME}/o)
kind = IDENT_KIND[match]
# TODO: keyword arguments
kind = :ident if last_token_dot
if kind == :old_keyword
kind = check(/\(/) ? :ident : :keyword
elsif kind == :predefined && check(/ *=/)
kind = :ident
elsif kind == :keyword
state = DEF_NEW_STATE[match]
from_import_state << match.to_sym if state == :include_expected
end
encoder.text_token match, kind
elsif match = scan(/@[a-zA-Z0-9_.]+[lL]?/)
encoder.text_token match, :decorator
elsif match = scan(/0[xX][0-9A-Fa-f]+[lL]?/)
encoder.text_token match, :hex
elsif match = scan(/0[bB][01]+[lL]?/)
encoder.text_token match, :binary
elsif match = scan(/(?:\d*\.\d+|\d+\.\d*)(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+/)
if scan(/[jJ]/)
match << matched
encoder.text_token match, :imaginary
else
encoder.text_token match, :float
end
elsif match = scan(/0[oO][0-7]+|0[0-7]+(?![89.eE])[lL]?/)
encoder.text_token match, :octal
elsif match = scan(/\d+([lL])?/)
if self[1] == nil && scan(/[jJ]/)
match << matched
encoder.text_token match, :imaginary
else
encoder.text_token match, :integer
end
else
encoder.text_token getch, :error
end
elsif state == :def_expected
state = :initial
if match = scan(unicode ? /#{NAME}/uo : /#{NAME}/o)
encoder.text_token match, :method
else
next
end
elsif state == :class_expected
state = :initial
if match = scan(unicode ? /#{NAME}/uo : /#{NAME}/o)
encoder.text_token match, :class
else
next
end
elsif state == :include_expected
if match = scan(unicode ? /#{DESCRIPTOR}/uo : /#{DESCRIPTOR}/o)
if match == 'as'
encoder.text_token match, :keyword
from_import_state << :as
elsif from_import_state.first == :from && match == 'import'
encoder.text_token match, :keyword
from_import_state << :import
elsif from_import_state.last == :as
# encoder.text_token match, match[0,1][unicode ? /[[:upper:]]/u : /[[:upper:]]/] ? :class : :method
encoder.text_token match, :ident
from_import_state.pop
elsif IDENT_KIND[match] == :keyword
unscan
match = nil
state = :initial
next
else
encoder.text_token match, :include
end
elsif match = scan(/,/)
from_import_state.pop if from_import_state.last == :as
encoder.text_token match, :operator
else
from_import_state = []
state = :initial
next
end
else
raise_inspect 'Unknown state', encoder, state
end
last_token_dot = match == '.'
end
if state == :string
encoder.end_group string_type
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/raydebug.rb 0000664 0000000 0000000 00000003444 13664404461 0021316 0 ustar 00root root 0000000 0000000 require 'set'
module CodeRay
module Scanners
# = Raydebug Scanner
#
# Highlights the output of the Encoders::Debug encoder.
class Raydebug < Scanner
register_for :raydebug
file_extension 'raydebug'
title 'CodeRay Token Dump'
protected
def setup
super
@known_token_kinds = TokenKinds.keys.map(&:to_s).to_set
end
def scan_tokens encoder, options
opened_tokens = []
until eos?
if match = scan(/\s+/)
encoder.text_token match, :space
elsif match = scan(/ (\w+) \( ( [^\)\\]* ( \\. [^\)\\]* )* ) /x)
kind = self[1]
encoder.text_token kind, :class
encoder.text_token '(', :operator
match = self[2]
unless match.empty?
if @known_token_kinds.include? kind
encoder.text_token match, kind.to_sym
else
encoder.text_token match, :plain
end
end
encoder.text_token match, :operator if match = scan(/\)/)
elsif match = scan(/ (\w+) ([<\[]) /x)
encoder.text_token self[1], :class
if @known_token_kinds.include? self[1]
kind = self[1].to_sym
else
kind = :unknown
end
opened_tokens << kind
encoder.begin_group kind
encoder.text_token self[2], :operator
elsif !opened_tokens.empty? && match = scan(/ [>\]] /x)
encoder.text_token match, :operator
encoder.end_group opened_tokens.pop
else
encoder.text_token getch, :space
end
end
encoder.end_group opened_tokens.pop until opened_tokens.empty?
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/ruby.rb 0000664 0000000 0000000 00000042636 13664404461 0020503 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# This scanner is really complex, since Ruby _is_ a complex language!
#
# It tries to highlight 100% of all common code,
# and 90% of strange codes.
#
# It is optimized for HTML highlighting, and is not very useful for
# parsing or pretty printing.
class Ruby < Scanner
register_for :ruby
file_extension 'rb'
autoload :Patterns, CodeRay.coderay_path('scanners', 'ruby', 'patterns')
autoload :StringState, CodeRay.coderay_path('scanners', 'ruby', 'string_state')
def interpreted_string_state
StringState.new :string, true, '"'
end
protected
def setup
@state = :initial
end
def scan_tokens encoder, options
state, heredocs = options[:state] || @state
heredocs = heredocs.dup if heredocs.is_a?(Array)
if state && state.instance_of?(StringState)
encoder.begin_group state.type
end
last_state = nil
method_call_expected = false
value_expected = true
inline_block_stack = nil
inline_block_curly_depth = 0
if heredocs
state = heredocs.shift
encoder.begin_group state.type
heredocs = nil if heredocs.empty?
end
# def_object_stack = nil
# def_object_paren_depth = 0
patterns = Patterns # avoid constant lookup
unicode = string.respond_to?(:encoding) && string.encoding.name == 'UTF-8'
until eos?
if state.instance_of? ::Symbol
if match = scan(/[ \t\f\v]+/)
encoder.text_token match, :space
elsif match = scan(/\n/)
if heredocs
unscan # heredoc scanning needs \n at start
state = heredocs.shift
encoder.begin_group state.type
heredocs = nil if heredocs.empty?
else
state = :initial if state == :undef_comma_expected
encoder.text_token match, :space
value_expected = true
end
elsif match = scan(bol? ? / \#(!)?.* | #{patterns::RUBYDOC_OR_DATA} /ox : /\#.*/)
encoder.text_token match, self[1] ? :doctype : :comment
elsif match = scan(/\\\n/)
if heredocs
unscan # heredoc scanning needs \n at start
encoder.text_token scan(/\\/), :space
state = heredocs.shift
encoder.begin_group state.type
heredocs = nil if heredocs.empty?
else
encoder.text_token match, :space
end
elsif state == :initial
# IDENTS #
if !method_call_expected &&
match = scan(unicode ? /#{patterns::METHOD_NAME}/uo :
/#{patterns::METHOD_NAME}/o)
kind = patterns::IDENT_KIND[match]
if value_expected != :colon_expected && scan(/:(?!:)/)
value_expected = true
encoder.text_token match, :key
encoder.text_token ':', :operator
else
value_expected = false
if kind == :ident
if match[/\A[A-Z]/] && !(match[/[!?]$/] || match?(/\(/))
kind = :constant
end
elsif kind == :keyword
state = patterns::KEYWORD_NEW_STATE[match]
if patterns::KEYWORDS_EXPECTING_VALUE[match]
value_expected = match == 'when' ? :colon_expected : true
end
end
value_expected = true if !value_expected && check(/#{patterns::VALUE_FOLLOWS}/o)
encoder.text_token match, kind
end
elsif method_call_expected &&
match = scan(unicode ? /#{patterns::METHOD_AFTER_DOT}/uo :
/#{patterns::METHOD_AFTER_DOT}/o)
if method_call_expected == '::' && match[/\A[A-Z]/] && !match?(/\(/)
encoder.text_token match, :constant
else
encoder.text_token match, :ident
end
method_call_expected = false
value_expected = check(/#{patterns::VALUE_FOLLOWS}/o)
# OPERATORS #
elsif !method_call_expected && match = scan(/ (\.(?!\.)|::) | ( \.\.\.? | ==?=? | [,\(\[\{] ) | [\)\]\}] /x)
method_call_expected = self[1]
value_expected = !method_call_expected && !!self[2]
if inline_block_stack
case match
when '{'
inline_block_curly_depth += 1
when '}'
inline_block_curly_depth -= 1
if inline_block_curly_depth == 0 # closing brace of inline block reached
state, inline_block_curly_depth, heredocs = inline_block_stack.pop
inline_block_stack = nil if inline_block_stack.empty?
heredocs = nil if heredocs && heredocs.empty?
encoder.text_token match, :inline_delimiter
encoder.end_group :inline
next
end
end
end
encoder.text_token match, :operator
elsif match = scan(unicode ? /#{patterns::SYMBOL}/uo :
/#{patterns::SYMBOL}/o)
case delim = match[1]
when ?', ?"
encoder.begin_group :symbol
encoder.text_token ':', :symbol
match = delim.chr
encoder.text_token match, :delimiter
state = self.class::StringState.new :symbol, delim == ?", match
else
encoder.text_token match, :symbol
value_expected = false
end
elsif match = scan(/ ' (?:(?>[^'\\]*) ')? | " (?:(?>[^"\\\#]*) ")? /mx)
if match.size == 1
kind = check(self.class::StringState.simple_key_pattern(match)) ? :key : :string
encoder.begin_group kind
encoder.text_token match, :delimiter
state = self.class::StringState.new kind, match == '"', match # important for streaming
else
kind = value_expected == true && scan(/:/) ? :key : :string
encoder.begin_group kind
encoder.text_token match[0,1], :delimiter
encoder.text_token match[1..-2], :content if match.size > 2
encoder.text_token match[-1,1], :delimiter
encoder.end_group kind
encoder.text_token ':', :operator if kind == :key
value_expected = false
end
elsif match = scan(unicode ? /#{patterns::INSTANCE_VARIABLE}/uo :
/#{patterns::INSTANCE_VARIABLE}/o)
value_expected = false
encoder.text_token match, :instance_variable
elsif value_expected && match = scan(/\//)
encoder.begin_group :regexp
encoder.text_token match, :delimiter
state = self.class::StringState.new :regexp, true, '/'
elsif match = scan(value_expected ? /[-+]?#{patterns::NUMERIC}/o : /#{patterns::NUMERIC}/o)
if method_call_expected
encoder.text_token match, :error
method_call_expected = false
else
kind = self[1] ? :float : :integer # TODO: send :hex/:octal/:binary
match << 'r' if match !~ /e/i && scan(/r/)
match << 'i' if scan(/i/)
encoder.text_token match, kind
end
value_expected = false
elsif match = scan(/ [-+!~^\/]=? | [:;] | &\. | [*|&]{1,2}=? | >>? /x)
value_expected = true
encoder.text_token match, :operator
elsif value_expected && match = scan(/#{patterns::HEREDOC_OPEN}/o)
quote = self[3]
delim = self[quote ? 4 : 2]
kind = patterns::QUOTE_TO_TYPE[quote]
encoder.begin_group kind
encoder.text_token match, :delimiter
encoder.end_group kind
heredocs ||= [] # create heredocs if empty
heredocs << self.class::StringState.new(kind, quote != "'", delim,
self[1] ? :indented : :linestart)
value_expected = false
elsif value_expected && match = scan(/#{patterns::FANCY_STRING_START}/o)
kind = patterns::FANCY_STRING_KIND[self[1]]
encoder.begin_group kind
state = self.class::StringState.new kind, patterns::FANCY_STRING_INTERPRETED[self[1]], self[2]
encoder.text_token match, :delimiter
elsif value_expected && match = scan(/#{patterns::CHARACTER}/o)
value_expected = false
encoder.text_token match, :integer
elsif match = scan(/ %=? | <(?:<|=>?)? | \? /x)
value_expected = match == '?' ? :colon_expected : true
encoder.text_token match, :operator
elsif match = scan(/`/)
encoder.begin_group :shell
encoder.text_token match, :delimiter
state = self.class::StringState.new :shell, true, match
elsif match = scan(unicode ? /#{patterns::GLOBAL_VARIABLE}/uo :
/#{patterns::GLOBAL_VARIABLE}/o)
encoder.text_token match, :global_variable
value_expected = false
elsif match = scan(unicode ? /#{patterns::CLASS_VARIABLE}/uo :
/#{patterns::CLASS_VARIABLE}/o)
encoder.text_token match, :class_variable
value_expected = false
elsif match = scan(/\\\z/)
encoder.text_token match, :space
else
if method_call_expected
method_call_expected = false
next
end
unless unicode
# check for unicode
$DEBUG_BEFORE, $DEBUG = $DEBUG, false
begin
if check(/./mu).size > 1
# seems like we should try again with unicode
unicode = true
end
rescue
# bad unicode char; use getch
ensure
$DEBUG = $DEBUG_BEFORE
end
next if unicode
end
encoder.text_token getch, :error
end
if last_state
state = last_state unless state.is_a?(StringState) # otherwise, a simple 'def"' results in unclosed tokens
last_state = nil
end
elsif state == :def_expected
if match = scan(unicode ? /(?>#{patterns::METHOD_NAME_EX})(?!\.|::)/uo :
/(?>#{patterns::METHOD_NAME_EX})(?!\.|::)/o)
encoder.text_token match, :method
state = :initial
else
last_state = :dot_expected
state = :initial
end
elsif state == :dot_expected
if match = scan(/\.|::/)
# invalid definition
state = :def_expected
encoder.text_token match, :operator
else
state = :initial
end
elsif state == :module_expected
if match = scan(/<)
encoder.text_token match, :operator
else
state = :initial
if match = scan(unicode ? / (?:#{patterns::IDENT}::)* #{patterns::IDENT} /oux :
/ (?:#{patterns::IDENT}::)* #{patterns::IDENT} /ox)
encoder.text_token match, :class
end
end
elsif state == :undef_expected
state = :undef_comma_expected
if match = scan(unicode ? /(?>#{patterns::METHOD_NAME_EX})(?!\.|::)/uo :
/(?>#{patterns::METHOD_NAME_EX})(?!\.|::)/o)
encoder.text_token match, :method
elsif match = scan(/#{patterns::SYMBOL}/o)
case delim = match[1]
when ?', ?"
encoder.begin_group :symbol
encoder.text_token ':', :symbol
match = delim.chr
encoder.text_token match, :delimiter
state = self.class::StringState.new :symbol, delim == ?", match
state.next_state = :undef_comma_expected
else
encoder.text_token match, :symbol
end
else
state = :initial
end
elsif state == :undef_comma_expected
if match = scan(/,/)
encoder.text_token match, :operator
state = :undef_expected
else
state = :initial
end
elsif state == :alias_expected
match = scan(unicode ? /(#{patterns::METHOD_NAME_OR_SYMBOL})([ \t]+)(#{patterns::METHOD_NAME_OR_SYMBOL})/uo :
/(#{patterns::METHOD_NAME_OR_SYMBOL})([ \t]+)(#{patterns::METHOD_NAME_OR_SYMBOL})/o)
if match
encoder.text_token self[1], (self[1][0] == ?: ? :symbol : :method)
encoder.text_token self[2], :space
encoder.text_token self[3], (self[3][0] == ?: ? :symbol : :method)
end
state = :initial
else
#:nocov:
raise_inspect 'Unknown state: %p' % [state], encoder
#:nocov:
end
else # StringState
match = scan_until(state.pattern) || scan_rest
unless match.empty?
encoder.text_token match, :content
break if eos?
end
if state.heredoc && self[1] # end of heredoc
match = getch
match << scan_until(/$/) unless eos?
encoder.text_token match, :delimiter unless match.empty?
encoder.end_group state.type
state = state.next_state
next
end
case match = getch
when state.delim
if state.paren_depth
state.paren_depth -= 1
if state.paren_depth > 0
encoder.text_token match, :content
next
end
end
encoder.text_token match, :delimiter
if state.type == :regexp && !eos?
match = scan(/#{patterns::REGEXP_MODIFIERS}/o)
encoder.text_token match, :modifier unless match.empty?
end
encoder.end_group state.type
value_expected = false
state = state.next_state
when '\\'
if state.interpreted
if esc = scan(/#{patterns::ESCAPE}/o)
encoder.text_token match + esc, :char
else
encoder.text_token match, :error
end
else
case esc = getch
when nil
encoder.text_token match, :content
when state.delim, '\\'
encoder.text_token match + esc, :char
else
encoder.text_token match + esc, :content
end
end
when '#'
case peek(1)
when '{'
inline_block_stack ||= []
inline_block_stack << [state, inline_block_curly_depth, heredocs]
value_expected = true
state = :initial
inline_block_curly_depth = 1
encoder.begin_group :inline
encoder.text_token match + getch, :inline_delimiter
when '$', '@'
encoder.text_token match, :escape
last_state = state
state = :initial
else
#:nocov:
raise_inspect 'else-case # reached; #%p not handled' % [peek(1)], encoder
#:nocov:
end
when state.opening_paren
state.paren_depth += 1
encoder.text_token match, :content
else
#:nocov
raise_inspect 'else-case " reached; %p not handled, state = %p' % [match, state], encoder
#:nocov:
end
end
end
# cleaning up
if state.is_a? StringState
encoder.end_group state.type
end
if options[:keep_state]
if state.is_a?(StringState) && state.heredoc
(heredocs ||= []).unshift state
state = :initial
elsif heredocs && heredocs.empty?
heredocs = nil
end
@state = state, heredocs
end
if inline_block_stack
until inline_block_stack.empty?
state, = *inline_block_stack.pop
encoder.end_group :inline
encoder.end_group state.type
end
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/ruby/ 0000775 0000000 0000000 00000000000 13664404461 0020143 5 ustar 00root root 0000000 0000000 coderay-1.1.3/lib/coderay/scanners/ruby/patterns.rb 0000664 0000000 0000000 00000011560 13664404461 0022333 0 ustar 00root root 0000000 0000000 # encoding: utf-8
module CodeRay
module Scanners
module Ruby::Patterns # :nodoc: all
KEYWORDS = %w[
and def end in or unless begin
defined? ensure module redo super until
BEGIN break do next rescue then
when END case else for retry
while alias class elsif if not return
undef yield
]
# See http://murfy.de/ruby-constants.
PREDEFINED_CONSTANTS = %w[
nil true false self
DATA ARGV ARGF ENV
FALSE TRUE NIL
STDERR STDIN STDOUT
TOPLEVEL_BINDING
RUBY_COPYRIGHT RUBY_DESCRIPTION RUBY_ENGINE RUBY_PATCHLEVEL
RUBY_PLATFORM RUBY_RELEASE_DATE RUBY_REVISION RUBY_VERSION
__FILE__ __LINE__ __ENCODING__
]
IDENT_KIND = WordList.new(:ident).
add(KEYWORDS, :keyword).
add(PREDEFINED_CONSTANTS, :predefined_constant)
KEYWORD_NEW_STATE = WordList.new(:initial).
add(%w[ def ], :def_expected).
add(%w[ undef ], :undef_expected).
add(%w[ alias ], :alias_expected).
add(%w[ class module ], :module_expected)
IDENT = 'ä'[/[[:alpha:]]/] == 'ä' ? Regexp.new('[[:alpha:]_[^\0-\177]][[:alnum:]_[^\0-\177]]*') : /[^\W\d]\w*/
METHOD_NAME = / #{IDENT} [?!]? /ox
METHOD_NAME_OPERATOR = /
\*\*? # multiplication and power
| [-+~]@? # plus, minus, tilde with and without at sign
| [\/%&|^`] # division, modulo or format strings, and, or, xor, system
| \[\]=? # array getter and setter
| << | >> # append or shift left, shift right
| <=?>? | >=? # comparison, rocket operator
| ===? | =~ # simple equality, case equality, match
| ![~=@]? # negation with and without at sign, not-equal and not-match
/ox
METHOD_SUFFIX = / (?: [?!] | = (?![~>]|=(?!>)) ) /x
METHOD_NAME_EX = / #{IDENT} #{METHOD_SUFFIX}? | #{METHOD_NAME_OPERATOR} /ox
METHOD_AFTER_DOT = / #{IDENT} [?!]? | #{METHOD_NAME_OPERATOR} /ox
INSTANCE_VARIABLE = / @ #{IDENT} /ox
CLASS_VARIABLE = / @@ #{IDENT} /ox
OBJECT_VARIABLE = / @@? #{IDENT} /ox
GLOBAL_VARIABLE = / \$ (?: #{IDENT} | [1-9]\d* | 0\w* | [~&+`'=\/,;_.<>!@$?*":\\] | -[a-zA-Z_0-9] ) /ox
PREFIX_VARIABLE = / #{GLOBAL_VARIABLE} | #{OBJECT_VARIABLE} /ox
VARIABLE = / @?@? #{IDENT} | #{GLOBAL_VARIABLE} /ox
QUOTE_TO_TYPE = {
'`' => :shell,
'/' => :regexp,
}
QUOTE_TO_TYPE.default = :string
REGEXP_MODIFIERS = /[mousenix]*/
DECIMAL = /\d+(?:_\d+)*/
OCTAL = /0_?[0-7]+(?:_[0-7]+)*/
HEXADECIMAL = /0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*/
BINARY = /0b[01]+(?:_[01]+)*/
EXPONENT = / [eE] [+-]? #{DECIMAL} /ox
FLOAT_SUFFIX = / #{EXPONENT} | \. #{DECIMAL} #{EXPONENT}? /ox
FLOAT_OR_INT = / #{DECIMAL} (?: #{FLOAT_SUFFIX} () )? /ox
NUMERIC = / (?: (?=0) (?: #{OCTAL} | #{HEXADECIMAL} | #{BINARY} ) | #{FLOAT_OR_INT} ) /ox
SYMBOL = /
:
(?:
#{METHOD_NAME_EX}
| #{PREFIX_VARIABLE}
| ['"]
)
/ox
METHOD_NAME_OR_SYMBOL = / #{METHOD_NAME_EX} | #{SYMBOL} /ox
SIMPLE_ESCAPE = /
[abefnrstv]
| [0-7]{1,3}
| x[0-9A-Fa-f]{1,2}
| .
/mx
CONTROL_META_ESCAPE = /
(?: M-|C-|c )
(?: \\ (?: M-|C-|c ) )*
(?: [^\\] | \\ #{SIMPLE_ESCAPE} )?
/mox
ESCAPE = /
#{CONTROL_META_ESCAPE} | #{SIMPLE_ESCAPE}
/mox
CHARACTER = /
\?
(?:
[^\s\\]
| \\ #{ESCAPE}
)
/mox
# NOTE: This is not completely correct, but
# nobody needs heredoc delimiters ending with \n.
HEREDOC_OPEN = /
<< ([-~])? # $1 = float
(?:
( [A-Za-z_0-9]+ ) # $2 = delim
|
( ["'`\/] ) # $3 = quote, type
( [^\n]*? ) \3 # $4 = delim
)
/mx
RUBYDOC = /
=begin (?!\S)
.*?
(?: \Z | ^=end (?!\S) [^\n]* )
/mx
DATA = /
__END__$
.*?
(?: \Z | (?=^\#CODE) )
/mx
RUBYDOC_OR_DATA = / #{RUBYDOC} | #{DATA} /xo
# Checks for a valid value to follow. This enables
# value_expected in method calls without parentheses.
VALUE_FOLLOWS = /
(?>[ \t\f\v]+)
(?:
[%\/][^\s=]
| <<-?\S
| [-+] \d
| #{CHARACTER}
)
/ox
KEYWORDS_EXPECTING_VALUE = WordList.new.add(%w[
and end in or unless begin
defined? ensure redo super until
break do next rescue then
when case else for retry
while elsif if not return
yield
])
FANCY_STRING_START = / % ( [iIqQrswWx] | (?![a-zA-Z0-9]) ) ([^a-zA-Z0-9]) /x
FANCY_STRING_KIND = Hash.new(:string).merge({
'i' => :symbol,
'I' => :symbol,
'r' => :regexp,
's' => :symbol,
'x' => :shell,
})
FANCY_STRING_INTERPRETED = Hash.new(true).merge({
'i' => false,
'q' => false,
's' => false,
'w' => false,
})
end
end
end
coderay-1.1.3/lib/coderay/scanners/ruby/string_state.rb 0000664 0000000 0000000 00000004527 13664404461 0023206 0 ustar 00root root 0000000 0000000 # encoding: utf-8
module CodeRay
module Scanners
class Ruby
class StringState < Struct.new :type, :interpreted, :delim, :heredoc,
:opening_paren, :paren_depth, :pattern, :next_state # :nodoc: all
CLOSING_PAREN = Hash[ *%w[
( )
[ ]
< >
{ }
] ].each { |k,v| k.freeze; v.freeze } # debug, if I try to change it with <<
STRING_PATTERN = Hash.new do |h, k|
delim, interpreted = *k
delim_pattern = Regexp.escape(delim)
if closing_paren = CLOSING_PAREN[delim]
delim_pattern << Regexp.escape(closing_paren)
end
delim_pattern << '\\\\' unless delim == '\\'
# special_escapes =
# case interpreted
# when :regexp_symbols
# '| [|?*+(){}\[\].^$]'
# end
if interpreted && delim != '#'
/ (?= [#{delim_pattern}] | \# [{$@] ) /mx
else
/ (?= [#{delim_pattern}] ) /mx
end.tap do |pattern|
h[k] = pattern if (delim.respond_to?(:ord) ? delim.ord : delim[0]) < 256
end
end
def self.simple_key_pattern delim
if delim == "'"
/ (?> (?: [^\\']+ | \\. )* ) ' : /mx
else
/ (?> (?: [^\\"\#]+ | \\. | \#\$[\\"] | \#\{[^\{\}]+\} | \#(?!\{) )* ) " : /mx
end
end
def initialize kind, interpreted, delim, heredoc = false
if heredoc
pattern = heredoc_pattern delim, interpreted, heredoc == :indented
delim = nil
else
pattern = STRING_PATTERN[ [delim, interpreted] ]
if closing_paren = CLOSING_PAREN[delim]
opening_paren = delim
delim = closing_paren
paren_depth = 1
end
end
super kind, interpreted, delim, heredoc, opening_paren, paren_depth, pattern, :initial
end
def heredoc_pattern delim, interpreted, indented
# delim = delim.dup # workaround for old Ruby
delim_pattern = Regexp.escape(delim)
delim_pattern = / (?:\A|\n) #{ '(?>[ \t]*)' if indented } #{ Regexp.new delim_pattern } $ /x
if interpreted
/ (?= #{delim_pattern}() | \\ | \# [{$@] ) /mx # $1 set == end of heredoc
else
/ (?= #{delim_pattern}() | \\ ) /mx
end
end
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/sass.rb 0000664 0000000 0000000 00000017200 13664404461 0020460 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# A scanner for Sass.
class Sass < CSS
register_for :sass
file_extension 'sass'
protected
def setup
@state = :initial
end
def scan_tokens encoder, options
states = Array(options[:state] || @state).dup
encoder.begin_group :string if states.last == :sqstring || states.last == :dqstring
until eos?
if bol? && (match = scan(/(?>( +)?(\/[\*\/])(.+)?)(?=\n)/))
encoder.text_token self[1], :space if self[1]
encoder.begin_group :comment
encoder.text_token self[2], :delimiter
encoder.text_token self[3], :content if self[3]
if match = scan(/(?:\n+#{self[1]} .*)+/)
encoder.text_token match, :content
end
encoder.end_group :comment
elsif match = scan(/\n|[^\n\S]+\n?/)
encoder.text_token match, :space
if match.index(/\n/)
value_expected = false
states.pop if states.last == :include
end
elsif states.last == :sass_inline && (match = scan(/\}/))
encoder.text_token match, :inline_delimiter
encoder.end_group :inline
states.pop
elsif case states.last
when :initial, :media, :sass_inline
if match = scan(/(?>#{RE::Ident})(?!\()/ox)
encoder.text_token match, value_expected ? :value : (check(/.*:(?![a-z])/) ? :key : :tag)
next
elsif !value_expected && (match = scan(/\*/))
encoder.text_token match, :tag
next
elsif match = scan(RE::Class)
encoder.text_token match, :class
next
elsif match = scan(RE::Id)
encoder.text_token match, :id
next
elsif match = scan(RE::PseudoClass)
encoder.text_token match, :pseudo_class
next
elsif match = scan(RE::AttributeSelector)
# TODO: Improve highlighting inside of attribute selectors.
encoder.text_token match[0,1], :operator
encoder.text_token match[1..-2], :attribute_name if match.size > 2
encoder.text_token match[-1,1], :operator if match[-1] == ?]
next
elsif match = scan(/(\=|@mixin +)#{RE::Ident}/o)
encoder.text_token match, :function
next
elsif match = scan(/@import\b/)
encoder.text_token match, :directive
states << :include
next
elsif match = scan(/@media\b/)
encoder.text_token match, :directive
# states.push :media_before_name
next
end
when :block
if match = scan(/(?>#{RE::Ident})(?!\()/ox)
if value_expected
encoder.text_token match, :value
else
encoder.text_token match, :key
end
next
end
when :sqstring, :dqstring
if match = scan(states.last == :sqstring ? /(?:[^\n\'\#]+|\\\n|#{RE::Escape}|#(?!\{))+/o : /(?:[^\n\"\#]+|\\\n|#{RE::Escape}|#(?!\{))+/o)
encoder.text_token match, :content
elsif match = scan(/['"]/)
encoder.text_token match, :delimiter
encoder.end_group :string
states.pop
elsif match = scan(/#\{/)
encoder.begin_group :inline
encoder.text_token match, :inline_delimiter
states.push :sass_inline
elsif match = scan(/ \\ | $ /x)
encoder.end_group states.last
encoder.text_token match, :error unless match.empty?
states.pop
else
raise_inspect "else case #{states.last} reached; %p not handled." % peek(1), encoder
end
when :include
if match = scan(/[^\s'",]+/)
encoder.text_token match, :include
next
end
else
#:nocov:
raise_inspect 'Unknown state: %p' % [states.last], encoder
#:nocov:
end
elsif match = scan(/\$#{RE::Ident}/o)
encoder.text_token match, :variable
next
elsif match = scan(/&/)
encoder.text_token match, :local_variable
elsif match = scan(/\+#{RE::Ident}/o)
encoder.text_token match, :include
value_expected = true
elsif match = scan(/\/\*(?:.*?\*\/|.*)|\/\/.*/)
encoder.text_token match, :comment
elsif match = scan(/#\{/)
encoder.begin_group :inline
encoder.text_token match, :inline_delimiter
states.push :sass_inline
elsif match = scan(/\{/)
value_expected = false
encoder.text_token match, :operator
states.push :block
elsif match = scan(/\}/)
value_expected = false
encoder.text_token match, :operator
if states.last == :block || states.last == :media
states.pop
end
elsif match = scan(/['"]/)
encoder.begin_group :string
encoder.text_token match, :delimiter
if states.include? :sass_inline
# no nesting, just scan the string until delimiter
content = scan_until(/(?=#{match}|\}|\z)/)
encoder.text_token content, :content unless content.empty?
encoder.text_token match, :delimiter if scan(/#{match}/)
encoder.end_group :string
else
states.push match == "'" ? :sqstring : :dqstring
end
elsif match = scan(/#{RE::Function}/o)
encoder.begin_group :function
start = match[/^[-\w]+\(/]
encoder.text_token start, :delimiter
if match[-1] == ?)
encoder.text_token match[start.size..-2], :content
encoder.text_token ')', :delimiter
else
encoder.text_token match[start.size..-1], :content if start.size < match.size
end
encoder.end_group :function
elsif match = scan(/[a-z][-a-z_]*(?=\()/o)
encoder.text_token match, :predefined
elsif match = scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox)
encoder.text_token match, :float
elsif match = scan(/#{RE::HexColor}/o)
encoder.text_token match, :color
elsif match = scan(/! *(?:important|optional)/)
encoder.text_token match, :important
elsif match = scan(/(?:rgb|hsl)a?\([^()\n]*\)?/)
encoder.text_token match, :color
elsif match = scan(/@else if\b|#{RE::AtKeyword}/o)
encoder.text_token match, :directive
value_expected = true
elsif match = scan(/ == | != | [-+*\/>~:;,.=()] /x)
if match == ':'
value_expected = true
elsif match == ';'
value_expected = false
end
encoder.text_token match, :operator
else
encoder.text_token getch, :error
end
end
states.pop if states.last == :include
if options[:keep_state]
@state = states.dup
end
while state = states.pop
if state == :sass_inline
encoder.end_group :inline
elsif state == :sqstring || state == :dqstring
encoder.end_group :string
end
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/scanner.rb 0000664 0000000 0000000 00000022530 13664404461 0021142 0 ustar 00root root 0000000 0000000 # encoding: utf-8
module CodeRay
module Scanners
# = Scanner
#
# The base class for all Scanners.
#
# It is a subclass of Ruby's great +StringScanner+, which
# makes it easy to access the scanning methods inside.
#
# It is also +Enumerable+, so you can use it like an Array of
# Tokens:
#
# require 'coderay'
#
# c_scanner = CodeRay::Scanners[:c].new "if (*p == '{') nest++;"
#
# for text, kind in c_scanner
# puts text if kind == :operator
# end
#
# # prints: (*==)++;
#
# OK, this is a very simple example :)
# You can also use +map+, +any?+, +find+ and even +sort_by+,
# if you want.
class Scanner < StringScanner
extend Plugin
plugin_host Scanners
# Raised if a Scanner fails while scanning
ScanError = Class.new StandardError
# The default options for all scanner classes.
#
# Define @default_options for subclasses.
DEFAULT_OPTIONS = { }
KINDS_NOT_LOC = [:comment, :doctype, :docstring]
attr_accessor :state
class << self
# Normalizes the given code into a string with UNIX newlines, in the
# scanner's internal encoding, with invalid and undefined charachters
# replaced by placeholders. Always returns a new object.
def normalize code
# original = code
code = code.to_s unless code.is_a? ::String
return code if code.empty?
if code.respond_to? :encoding
code = encode_with_encoding code, self.encoding
else
code = to_unix code
end
# code = code.dup if code.eql? original
code
end
# The typical filename suffix for this scanner's language.
def file_extension extension = lang
@file_extension ||= extension.to_s
end
# The encoding used internally by this scanner.
def encoding name = 'UTF-8'
@encoding ||= defined?(Encoding.find) && Encoding.find(name)
end
# The lang of this Scanner class, which is equal to its Plugin ID.
def lang
@plugin_id
end
protected
def encode_with_encoding code, target_encoding
if code.encoding == target_encoding
if code.valid_encoding?
return to_unix(code)
else
source_encoding = guess_encoding code
end
else
source_encoding = code.encoding
end
# print "encode_with_encoding from #{source_encoding} to #{target_encoding}"
code.encode target_encoding, source_encoding, :universal_newline => true, :undef => :replace, :invalid => :replace
end
def to_unix code
code.index(?\r) ? code.gsub(/\r\n?/, "\n") : code
end
def guess_encoding s
#:nocov:
IO.popen("file -b --mime -", "w+") do |file|
file.write s[0, 1024]
file.close_write
begin
Encoding.find file.gets[/charset=([-\w]+)/, 1]
rescue ArgumentError
Encoding::BINARY
end
end
#:nocov:
end
end
# Create a new Scanner.
#
# * +code+ is the input String and is handled by the superclass
# StringScanner.
# * +options+ is a Hash with Symbols as keys.
# It is merged with the default options of the class (you can
# overwrite default options here.)
#
# Else, a Tokens object is used.
def initialize code = '', options = {}
if self.class == Scanner
raise NotImplementedError, "I am only the basic Scanner class. I can't scan anything. :( Use my subclasses."
end
@options = self.class::DEFAULT_OPTIONS.merge options
super self.class.normalize(code)
@tokens = options[:tokens] || Tokens.new
@tokens.scanner = self if @tokens.respond_to? :scanner=
setup
end
# Sets back the scanner. Subclasses should redefine the reset_instance
# method instead of this one.
def reset
super
reset_instance
end
# Set a new string to be scanned.
def string= code
code = self.class.normalize(code)
super code
reset_instance
end
# the Plugin ID for this scanner
def lang
self.class.lang
end
# the default file extension for this scanner
def file_extension
self.class.file_extension
end
# Scan the code and returns all tokens in a Tokens object.
def tokenize source = nil, options = {}
options = @options.merge(options)
set_tokens_from_options options
set_string_from_source source
begin
scan_tokens @tokens, options
rescue => e
message = "Error in %s#scan_tokens, initial state was: %p" % [self.class, defined?(state) && state]
raise_inspect e.message, @tokens, message, 30, e.backtrace
end
@cached_tokens = @tokens
if source.is_a? Array
@tokens.split_into_parts(*source.map { |part| part.size })
else
@tokens
end
end
# Cache the result of tokenize.
def tokens
@cached_tokens ||= tokenize
end
# Traverse the tokens.
def each &block
tokens.each(&block)
end
include Enumerable
# The current line position of the scanner, starting with 1.
# See also: #column.
#
# Beware, this is implemented inefficiently. It should be used
# for debugging only.
def line pos = self.pos
return 1 if pos <= 0
binary_string[0...pos].count("\n") + 1
end
# The current column position of the scanner, starting with 1.
# See also: #line.
def column pos = self.pos
return 1 if pos <= 0
pos - (binary_string.rindex(?\n, pos - 1) || -1)
end
# The string in binary encoding.
#
# To be used with #pos, which is the index of the byte the scanner
# will scan next.
def binary_string
@binary_string ||=
if string.respond_to?(:bytesize) && string.bytesize != string.size
#:nocov:
string.dup.force_encoding('binary')
#:nocov:
else
string
end
end
protected
# Can be implemented by subclasses to do some initialization
# that has to be done once per instance.
#
# Use reset for initialization that has to be done once per
# scan.
def setup # :doc:
end
def set_string_from_source source
case source
when Array
self.string = self.class.normalize(source.join)
when nil
reset
else
self.string = self.class.normalize(source)
end
end
def set_tokens_from_options options
@tokens = options[:tokens] || @tokens || Tokens.new
@tokens.scanner = self if @tokens.respond_to? :scanner=
end
# This is the central method, and commonly the only one a
# subclass implements.
#
# Subclasses must implement this method; it must return +tokens+
# and must only use Tokens#<< for storing scanned tokens!
def scan_tokens tokens, options # :doc:
raise NotImplementedError, "#{self.class}#scan_tokens not implemented."
end
# Resets the scanner.
def reset_instance
@tokens.clear if @tokens.respond_to?(:clear) && !@options[:keep_tokens]
@cached_tokens = nil
@binary_string = nil if defined? @binary_string
end
SCAN_ERROR_MESSAGE = <<-MESSAGE
***ERROR in %s: %s (after %s tokens)
tokens:
%s
%s
surrounding code:
%p ~~ %p
***ERROR***
MESSAGE
def raise_inspect_arguments message, tokens, state, ambit
return File.basename(caller[0]),
message,
tokens_size(tokens),
tokens_last(tokens, 10).map(&:inspect).join("\n"),
scanner_state_info(state),
binary_string[pos - ambit, ambit],
binary_string[pos, ambit]
end
SCANNER_STATE_INFO = <<-INFO
current line: %d column: %d pos: %d
matched: %p state: %p
bol?: %p, eos?: %p
INFO
def scanner_state_info state
SCANNER_STATE_INFO % [
line, column, pos,
matched, state || 'No state given!',
bol?, eos?,
]
end
# Scanner error with additional status information
def raise_inspect message, tokens, state = self.state, ambit = 30, backtrace = caller
raise ScanError, SCAN_ERROR_MESSAGE % raise_inspect_arguments(message, tokens, state, ambit), backtrace
end
def tokens_size tokens
tokens.size if tokens.respond_to?(:size)
end
def tokens_last tokens, n
tokens.respond_to?(:last) ? tokens.last(n) : []
end
# Shorthand for scan_until(/\z/).
# This method also avoids a JRuby 1.9 mode bug.
def scan_rest
rest = self.rest
terminate
rest
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/sql.rb 0000664 0000000 0000000 00000012514 13664404461 0020311 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# by Josh Goebel
class SQL < Scanner
register_for :sql
KEYWORDS = %w(
all and any as before begin between by case check collate
each else end exists
for foreign from full group having if in inner is join
like not of on or order outer over references
then to union using values when where
left right distinct
)
OBJECTS = %w(
database databases table tables column columns fields index constraint
constraints transaction function procedure row key view trigger
)
COMMANDS = %w(
add alter comment create delete drop grant insert into select update set
show prompt begin commit rollback replace truncate
)
PREDEFINED_TYPES = %w(
char varchar varchar2 enum binary text tinytext mediumtext
longtext blob tinyblob mediumblob longblob timestamp
date time datetime year double decimal float int
integer tinyint mediumint bigint smallint unsigned bit numeric
bool boolean hex bin oct
)
PREDEFINED_FUNCTIONS = %w( sum cast substring abs pi count min max avg now )
DIRECTIVES = %w(
auto_increment unique default charset initially deferred
deferrable cascade immediate read write asc desc after
primary foreign return engine
)
PREDEFINED_CONSTANTS = %w( null true false )
IDENT_KIND = WordList::CaseIgnoring.new(:ident).
add(KEYWORDS, :keyword).
add(OBJECTS, :type).
add(COMMANDS, :class).
add(PREDEFINED_TYPES, :predefined_type).
add(PREDEFINED_CONSTANTS, :predefined_constant).
add(PREDEFINED_FUNCTIONS, :predefined).
add(DIRECTIVES, :directive)
ESCAPE = / [rbfntv\n\\\/'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} | . /mx
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x
STRING_PREFIXES = /[xnb]|_\w+/i
STRING_CONTENT_PATTERN = {
'"' => / (?: [^\\"] | "" )+ /x,
"'" => / (?: [^\\'] | '' )+ /x,
'`' => / (?: [^\\`] | `` )+ /x,
}
def scan_tokens encoder, options
state = :initial
string_type = nil
string_content = ''
name_expected = false
until eos?
if state == :initial
if match = scan(/ \s+ | \\\n /x)
encoder.text_token match, :space
elsif match = scan(/(?:--\s?|#).*/)
encoder.text_token match, :comment
elsif match = scan(%r( /\* (!)? (?: .*? \*/ | .* ) )mx)
encoder.text_token match, self[1] ? :directive : :comment
elsif match = scan(/ [*\/=<>:;,!&^|()\[\]{}~%] | [-+\.](?!\d) /x)
name_expected = true if match == '.' && check(/[A-Za-z_]/)
encoder.text_token match, :operator
elsif match = scan(/(#{STRING_PREFIXES})?([`"'])/o)
prefix = self[1]
string_type = self[2]
encoder.begin_group :string
encoder.text_token prefix, :modifier if prefix
match = string_type
state = :string
encoder.text_token match, :delimiter
elsif match = scan(/ @? [A-Za-z_][A-Za-z_0-9\$]* /x)
encoder.text_token match, name_expected ? :ident : (match[0] == ?@ ? :variable : IDENT_KIND[match])
name_expected = false
elsif match = scan(/0[xX][0-9A-Fa-f]+/)
encoder.text_token match, :hex
elsif match = scan(/0[0-7]+(?![89.eEfF])/)
encoder.text_token match, :octal
elsif match = scan(/[-+]?(?>\d+)(?![.eEfF])/)
encoder.text_token match, :integer
elsif match = scan(/[-+]?(?:\d[fF]|\d*\.\d+(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+)/)
encoder.text_token match, :float
elsif match = scan(/\\N/)
encoder.text_token match, :predefined_constant
else
encoder.text_token getch, :error
end
elsif state == :string
if match = scan(STRING_CONTENT_PATTERN[string_type])
encoder.text_token match, :content
elsif match = scan(/["'`]/)
if string_type == match
if peek(1) == string_type # doubling means escape
encoder.text_token match + getch, :content
else
encoder.text_token match, :delimiter
encoder.end_group :string
state = :initial
string_type = nil
end
else
encoder.text_token match, :content
end
elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
encoder.text_token match, :char
elsif match = scan(/ \\ . /mox)
encoder.text_token match, :content
elsif match = scan(/ \\ | $ /x)
encoder.text_token match, :error unless match.empty?
encoder.end_group :string
state = :initial
else
raise "else case \" reached; %p not handled." % peek(1), encoder
end
else
raise 'else-case reached', encoder
end
end
if state == :string
encoder.end_group state
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/taskpaper.rb 0000664 0000000 0000000 00000002010 13664404461 0021472 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
class Taskpaper < Scanner
register_for :taskpaper
file_extension 'taskpaper'
protected
def scan_tokens encoder, options
until eos?
if match = scan(/\S.*:.*$/) # project
encoder.text_token(match, :namespace)
elsif match = scan(/-.+@done.*/) # completed task
encoder.text_token(match, :done)
elsif match = scan(/-(?:[^@\n]+|@(?!due))*/) # task
encoder.text_token(match, :plain)
elsif match = scan(/@due.*/) # comment
encoder.text_token(match, :important)
elsif match = scan(/.+/) # comment
encoder.text_token(match, :comment)
elsif match = scan(/\s+/) # space
encoder.text_token(match, :space)
else # other
encoder.text_token getch, :error
end
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/text.rb 0000664 0000000 0000000 00000000714 13664404461 0020475 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# Scanner for plain text.
#
# Yields just one token of the kind :plain.
#
# Alias: +plaintext+, +plain+
class Text < Scanner
register_for :text
title 'Plain text'
KINDS_NOT_LOC = [:plain] # :nodoc:
protected
def scan_tokens encoder, options
encoder.text_token string, :plain
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/scanners/xml.rb 0000664 0000000 0000000 00000000330 13664404461 0020303 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
load :html
# Scanner for XML.
#
# Currently this is the same scanner as Scanners::HTML.
class XML < HTML
register_for :xml
file_extension 'xml'
end
end
end
coderay-1.1.3/lib/coderay/scanners/yaml.rb 0000664 0000000 0000000 00000011016 13664404461 0020450 0 ustar 00root root 0000000 0000000 module CodeRay
module Scanners
# Scanner for YAML.
#
# Based on the YAML scanner from Syntax by Jamis Buck.
class YAML < Scanner
register_for :yaml
file_extension 'yml'
KINDS_NOT_LOC = :all
protected
def scan_tokens encoder, options
state = :initial
key_indent = string_indent = 0
until eos?
key_indent = nil if bol?
if match = scan(/ +[\t ]*/)
encoder.text_token match, :space
elsif match = scan(/\n+/)
encoder.text_token match, :space
state = :initial if match.index(?\n)
elsif match = scan(/#.*/)
encoder.text_token match, :comment
elsif bol? and case
when match = scan(/---|\.\.\./)
encoder.begin_group :head
encoder.text_token match, :head
encoder.end_group :head
next
when match = scan(/%.*/)
encoder.text_token match, :doctype
next
end
elsif state == :value and case
when !check(/(?:"[^"]*")(?=: |:$)/) && match = scan(/"/)
encoder.begin_group :string
encoder.text_token match, :delimiter
encoder.text_token match, :content if (match = scan(/ [^"\\]* (?: \\. [^"\\]* )* /mx)) && !match.empty?
encoder.text_token match, :delimiter if match = scan(/"/)
encoder.end_group :string
next
when match = scan(/[|>][-+]?/)
encoder.begin_group :string
encoder.text_token match, :delimiter
string_indent = key_indent || column(pos - match.size) - 1
encoder.text_token matched, :content if scan(/(?:\n+ {#{string_indent + 1}}.*)+/)
encoder.end_group :string
next
when match = scan(/(?![!"*&]).+?(?=$|\s+#)/)
encoder.begin_group :string
encoder.text_token match, :content
string_indent = key_indent || column(pos - match.size) - 1
encoder.text_token matched, :content if scan(/(?:\n+ {#{string_indent + 1}}.*)+/)
encoder.end_group :string
next
end
elsif case
when match = scan(/[-:](?= |$)/)
state = :value if state == :colon && (match == ':' || match == '-')
state = :value if state == :initial && match == '-'
encoder.text_token match, :operator
next
when match = scan(/[,{}\[\]]/)
encoder.text_token match, :operator
next
when state == :initial && match = scan(/[-\w.()\/ ]*\S(?= *:(?: |$))/)
encoder.text_token match, :key
key_indent = column(pos - match.size) - 1
state = :colon
next
when match = scan(/(?:"[^"\n]*"|'[^'\n]*')(?= *:(?: |$))/)
encoder.begin_group :key
encoder.text_token match[0,1], :delimiter
encoder.text_token match[1..-2], :content if match.size > 2
encoder.text_token match[-1,1], :delimiter
encoder.end_group :key
key_indent = column(pos - match.size) - 1
state = :colon
next
when match = scan(/(![\w\/]+)(:([\w:]+))?/)
encoder.text_token self[1], :type
if self[2]
encoder.text_token ':', :operator
encoder.text_token self[3], :class
end
next
when match = scan(/&\S+/)
encoder.text_token match, :variable
next
when match = scan(/\*\w+/)
encoder.text_token match, :global_variable
next
when match = scan(/<)
encoder.text_token match, :class_variable
next
when match = scan(/\d\d:\d\d:\d\d/)
encoder.text_token match, :octal
next
when match = scan(/\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d(\.\d+)? [-+]\d\d:\d\d/)
encoder.text_token match, :octal
next
when match = scan(/:\w+/)
encoder.text_token match, :symbol
next
when match = scan(/[^:\s]+(:(?! |$)[^:\s]*)* .*/)
encoder.text_token match, :error
next
when match = scan(/[^:\s]+(:(?! |$)[^:\s]*)*/)
encoder.text_token match, :error
next
end
else
raise if eos?
encoder.text_token getch, :error
end
end
encoder
end
end
end
end
coderay-1.1.3/lib/coderay/styles.rb 0000664 0000000 0000000 00000000417 13664404461 0017220 0 ustar 00root root 0000000 0000000 module CodeRay
# This module holds the Style class and its subclasses.
#
# See Plugin.
module Styles
extend PluginHost
plugin_path File.dirname(__FILE__), 'styles'
autoload :Style, CodeRay.coderay_path('styles', 'style')
end
end
coderay-1.1.3/lib/coderay/styles/ 0000775 0000000 0000000 00000000000 13664404461 0016671 5 ustar 00root root 0000000 0000000 coderay-1.1.3/lib/coderay/styles/_map.rb 0000664 0000000 0000000 00000000074 13664404461 0020133 0 ustar 00root root 0000000 0000000 module CodeRay
module Styles
default :alpha
end
end
coderay-1.1.3/lib/coderay/styles/alpha.rb 0000664 0000000 0000000 00000011647 13664404461 0020314 0 ustar 00root root 0000000 0000000 module CodeRay
module Styles
# A colorful theme using CSS 3 colors (with alpha channel).
class Alpha < Style
register_for :alpha
code_background = 'hsl(0,0%,95%)'
numbers_background = 'hsl(180,65%,90%)'
border_color = 'silver'
normal_color = 'black'
CSS_MAIN_STYLES = <<-MAIN # :nodoc:
.CodeRay {
background-color: #{code_background};
border: 1px solid #{border_color};
color: #{normal_color};
}
.CodeRay pre {
margin: 0px;
}
span.CodeRay { white-space: pre; border: 0px; padding: 2px; }
table.CodeRay { border-collapse: collapse; width: 100%; padding: 2px; }
table.CodeRay td { padding: 2px 4px; vertical-align: top; }
.CodeRay .line-numbers {
background-color: #{numbers_background};
color: gray;
text-align: right;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.CodeRay .line-numbers a {
background-color: #{numbers_background} !important;
color: gray !important;
text-decoration: none !important;
}
.CodeRay .line-numbers pre {
word-break: normal;
}
.CodeRay .line-numbers a:target { color: blue !important; }
.CodeRay .line-numbers .highlighted { color: red !important; }
.CodeRay .line-numbers .highlighted a { color: red !important; }
.CodeRay span.line-numbers { padding: 0px 4px; }
.CodeRay .line { display: block; float: left; width: 100%; }
.CodeRay .code { width: 100%; }
MAIN
TOKEN_COLORS = <<-'TOKENS'
.debug { color: white !important; background: blue !important; }
.annotation { color:#007 }
.attribute-name { color:#b48 }
.attribute-value { color:#700 }
.binary { color:#549 }
.binary .char { color:#325 }
.binary .delimiter { color:#325 }
.char { color:#D20 }
.char .content { color:#D20 }
.char .delimiter { color:#710 }
.class { color:#B06; font-weight:bold }
.class-variable { color:#369 }
.color { color:#0A0 }
.comment { color:#777 }
.comment .char { color:#444 }
.comment .delimiter { color:#444 }
.constant { color:#036; font-weight:bold }
.decorator { color:#B0B }
.definition { color:#099; font-weight:bold }
.delimiter { color:black }
.directive { color:#088; font-weight:bold }
.docstring { color:#D42; }
.doctype { color:#34b }
.done { text-decoration: line-through; color: gray }
.entity { color:#800; font-weight:bold }
.error { color:#F00; background-color:#FAA }
.escape { color:#666 }
.exception { color:#C00; font-weight:bold }
.float { color:#60E }
.function { color:#06B; font-weight:bold }
.function .delimiter { color:#059 }
.function .content { color:#037 }
.global-variable { color:#d70 }
.hex { color:#02b }
.id { color:#33D; font-weight:bold }
.include { color:#B44; font-weight:bold }
.inline { background-color: hsla(0,0%,0%,0.07); color: black }
.inline-delimiter { font-weight: bold; color: #666 }
.instance-variable { color:#33B }
.integer { color:#00D }
.imaginary { color:#f00 }
.important { color:#D00 }
.key { color: #606 }
.key .char { color: #60f }
.key .delimiter { color: #404 }
.keyword { color:#080; font-weight:bold }
.label { color:#970; font-weight:bold }
.local-variable { color:#950 }
.map .content { color:#808 }
.map .delimiter { color:#40A}
.map { background-color:hsla(200,100%,50%,0.06); }
.namespace { color:#707; font-weight:bold }
.octal { color:#40E }
.operator { }
.predefined { color:#369; font-weight:bold }
.predefined-constant { color:#069 }
.predefined-type { color:#0a8; font-weight:bold }
.preprocessor { color:#579 }
.pseudo-class { color:#00C; font-weight:bold }
.regexp { background-color:hsla(300,100%,50%,0.06); }
.regexp .content { color:#808 }
.regexp .delimiter { color:#404 }
.regexp .modifier { color:#C2C }
.reserved { color:#080; font-weight:bold }
.shell { background-color:hsla(120,100%,50%,0.06); }
.shell .content { color:#2B2 }
.shell .delimiter { color:#161 }
.string { background-color:hsla(0,100%,50%,0.05); }
.string .char { color: #b0b }
.string .content { color: #D20 }
.string .delimiter { color: #710 }
.string .modifier { color: #E40 }
.symbol { color:#A60 }
.symbol .content { color:#A60 }
.symbol .delimiter { color:#740 }
.tag { color:#070; font-weight:bold }
.type { color:#339; font-weight:bold }
.value { color: #088 }
.variable { color:#037 }
.insert { background: hsla(120,100%,50%,0.12) }
.delete { background: hsla(0,100%,50%,0.12) }
.change { color: #bbf; background: #007 }
.head { color: #f8f; background: #505 }
.head .filename { color: white; }
.delete .eyecatcher { background-color: hsla(0,100%,50%,0.2); border: 1px solid hsla(0,100%,45%,0.5); margin: -1px; border-bottom: none; border-top-left-radius: 5px; border-top-right-radius: 5px; }
.insert .eyecatcher { background-color: hsla(120,100%,50%,0.2); border: 1px solid hsla(120,100%,25%,0.5); margin: -1px; border-top: none; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }
.insert .insert { color: #0c0; background:transparent; font-weight:bold }
.delete .delete { color: #c00; background:transparent; font-weight:bold }
.change .change { color: #88f }
.head .head { color: #f4f }
TOKENS
end
end
end
coderay-1.1.3/lib/coderay/styles/style.rb 0000664 0000000 0000000 00000000423 13664404461 0020355 0 ustar 00root root 0000000 0000000 module CodeRay
module Styles
# Base class for styles.
#
# Styles are used by Encoders::HTML to colorize tokens.
class Style
extend Plugin
plugin_host Styles
DEFAULT_OPTIONS = { } # :nodoc:
end
end
end
coderay-1.1.3/lib/coderay/token_kinds.rb 0000664 0000000 0000000 00000012147 13664404461 0020210 0 ustar 00root root 0000000 0000000 module CodeRay
# A Hash of all known token kinds and their associated CSS classes.
TokenKinds = Hash.new(false)
# speedup
TokenKinds.compare_by_identity if TokenKinds.respond_to? :compare_by_identity
TokenKinds.update( # :nodoc:
:debug => 'debug', # highlight for debugging (white on blue background)
:annotation => 'annotation', # Groovy, Java
:attribute_name => 'attribute-name', # HTML, CSS
:attribute_value => 'attribute-value', # HTML
:binary => 'binary', # Python, Ruby
:char => 'char', # most scanners, also inside of strings
:class => 'class', # lots of scanners, for different purposes also in CSS
:class_variable => 'class-variable', # Ruby, YAML
:color => 'color', # CSS
:comment => 'comment', # most scanners
:constant => 'constant', # PHP, Ruby
:content => 'content', # inside of strings, most scanners
:decorator => 'decorator', # Python
:definition => 'definition', # CSS
:delimiter => 'delimiter', # inside strings, comments and other types
:directive => 'directive', # lots of scanners
:doctype => 'doctype', # Goorvy, HTML, Ruby, YAML
:docstring => 'docstring', # Python
:done => 'done', # Taskpaper
:entity => 'entity', # HTML
:error => 'error', # invalid token, most scanners
:escape => 'escape', # Ruby (string inline variables like #$foo, #@bar)
:exception => 'exception', # Java, PHP, Python
:filename => 'filename', # Diff
:float => 'float', # most scanners
:function => 'function', # CSS, JavaScript, PHP
:global_variable => 'global-variable', # Ruby, YAML
:hex => 'hex', # hexadecimal number; lots of scanners
:id => 'id', # CSS
:imaginary => 'imaginary', # Python
:important => 'important', # CSS, Taskpaper
:include => 'include', # C, Groovy, Java, Python, Sass
:inline => 'inline', # nested code, eg. inline string evaluation; lots of scanners
:inline_delimiter => 'inline-delimiter', # used instead of :inline > :delimiter FIXME: Why use inline_delimiter?
:instance_variable => 'instance-variable', # Ruby
:integer => 'integer', # most scanners
:key => 'key', # lots of scanners, used together with :value
:keyword => 'keyword', # reserved word that's actually implemented; most scanners
:label => 'label', # C, PHP
:local_variable => 'local-variable', # local and magic variables; some scanners
:map => 'map', # Lua tables
:modifier => 'modifier', # used inside on strings; lots of scanners
:namespace => 'namespace', # Clojure, Java, Taskpaper
:octal => 'octal', # lots of scanners
:predefined => 'predefined', # predefined function: lots of scanners
:predefined_constant => 'predefined-constant',# lots of scanners
:predefined_type => 'predefined-type', # C, Java, PHP
:preprocessor => 'preprocessor', # C, Delphi, HTML
:pseudo_class => 'pseudo-class', # CSS
:regexp => 'regexp', # Groovy, JavaScript, Ruby
:reserved => 'reserved', # most scanners
:shell => 'shell', # Ruby
:string => 'string', # most scanners
:symbol => 'symbol', # Clojure, Ruby, YAML
:tag => 'tag', # CSS, HTML
:type => 'type', # CSS, Java, SQL, YAML
:value => 'value', # used together with :key; CSS, JSON, YAML
:variable => 'variable', # Sass, SQL, YAML
:change => 'change', # Diff
:delete => 'delete', # Diff
:head => 'head', # Diff, YAML
:insert => 'insert', # Diff
:eyecatcher => 'eyecatcher', # Diff
:ident => false, # almost all scanners
:operator => false, # almost all scanners
:space => false, # almost all scanners
:plain => false # almost all scanners
)
TokenKinds[:method] = TokenKinds[:function]
TokenKinds[:unknown] = TokenKinds[:plain]
end
coderay-1.1.3/lib/coderay/tokens.rb 0000664 0000000 0000000 00000012410 13664404461 0017174 0 ustar 00root root 0000000 0000000 module CodeRay
# The Tokens class represents a list of tokens returned from
# a Scanner. It's actually just an Array with a few helper methods.
#
# A token itself is not a special object, just two elements in an Array:
# * the _token_ _text_ (the original source of the token in a String) or
# a _token_ _action_ (begin_group, end_group, begin_line, end_line)
# * the _token_ _kind_ (a Symbol representing the type of the token)
#
# It looks like this:
#
# ..., '# It looks like this', :comment, ...
# ..., '3.1415926', :float, ...
# ..., '$^', :error, ...
#
# Some scanners also yield sub-tokens, represented by special
# token actions, for example :begin_group and :end_group.
#
# The Ruby scanner, for example, splits "a string" into:
#
# [
# :begin_group, :string,
# '"', :delimiter,
# 'a string', :content,
# '"', :delimiter,
# :end_group, :string
# ]
#
# Tokens can be used to save the output of a Scanners in a simple
# Ruby object that can be send to an Encoder later:
#
# tokens = CodeRay.scan('price = 2.59', :ruby).tokens
# tokens.encode(:html)
# tokens.html
# CodeRay.encoder(:html).encode_tokens(tokens)
#
# Tokens gives you the power to handle pre-scanned code very easily:
# You can serialize it to a JSON string and store it in a database, pass it
# around to encode it more than once, send it to other algorithms...
class Tokens < Array
# Remove Array#filter that is a new alias for Array#select on Ruby 2.6,
# for method_missing called with filter method.
undef_method :filter if instance_methods.include?(:filter)
# The Scanner instance that created the tokens.
attr_accessor :scanner
# Encode the tokens using encoder.
#
# encoder can be
# * a plugin name like :html oder 'statistic'
# * an Encoder object
#
# options are passed to the encoder.
def encode encoder, options = {}
encoder = Encoders[encoder].new options if encoder.respond_to? :to_sym
encoder.encode_tokens self, options
end
# Turn tokens into a string by concatenating them.
def to_s
encode CodeRay::Encoders::Encoder.new
end
# Redirects unknown methods to encoder calls.
#
# For example, if you call +tokens.html+, the HTML encoder
# is used to highlight the tokens.
def method_missing meth, options = {}
encode meth, options
rescue PluginHost::PluginNotFound
super
end
# Split the tokens into parts of the given +sizes+.
#
# The result will be an Array of Tokens objects. The parts have
# the text size specified by the parameter. In addition, each
# part closes all opened tokens. This is useful to insert tokens
# betweem them.
#
# This method is used by @Scanner#tokenize@ when called with an Array
# of source strings. The Diff encoder uses it for inline highlighting.
def split_into_parts *sizes
return Array.new(sizes.size) { Tokens.new } if size == 2 && first == ''
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
# Return the actual number of tokens.
def count
size / 2
end
alias text_token push
def begin_group kind; push :begin_group, kind end
def end_group kind; push :end_group, kind end
def begin_line kind; push :begin_line, kind end
def end_line kind; push :end_line, kind end
alias tokens concat
end
end
coderay-1.1.3/lib/coderay/tokens_proxy.rb 0000664 0000000 0000000 00000002773 13664404461 0020450 0 ustar 00root root 0000000 0000000 module CodeRay
# The result of a scan operation is a TokensProxy, but should act like Tokens.
#
# This proxy makes it possible to use the classic CodeRay.scan.encode API
# while still providing the benefits of direct streaming.
class TokensProxy
attr_accessor :input, :lang, :options, :block
# Create a new TokensProxy with the arguments of CodeRay.scan.
def initialize input, lang, options = {}, block = nil
@input = input
@lang = lang
@options = options
@block = block
end
# Call CodeRay.encode if +encoder+ is a Symbol;
# otherwise, convert the receiver to tokens and call encoder.encode_tokens.
def encode encoder, options = {}
if encoder.respond_to? :to_sym
CodeRay.encode(input, lang, encoder, options)
else
encoder.encode_tokens tokens, options
end
end
# Tries to call encode;
# delegates to tokens otherwise.
def method_missing method, *args, &blk
encode method.to_sym, *args
rescue PluginHost::PluginNotFound
tokens.send(method, *args, &blk)
end
# The (cached) result of the tokenized input; a Tokens instance.
def tokens
@tokens ||= scanner.tokenize(input)
end
# A (cached) scanner instance to use for the scan task.
def scanner
@scanner ||= CodeRay.scanner(lang, options, &block)
end
# Overwrite Struct#each.
def each *args, &blk
tokens.each(*args, &blk)
self
end
end
end
coderay-1.1.3/lib/coderay/version.rb 0000664 0000000 0000000 00000000047 13664404461 0017361 0 ustar 00root root 0000000 0000000 module CodeRay
VERSION = '1.1.3'
end
coderay-1.1.3/rake_tasks/ 0000775 0000000 0000000 00000000000 13664404461 0015301 5 ustar 00root root 0000000 0000000 coderay-1.1.3/rake_tasks/benchmark.rake 0000664 0000000 0000000 00000000152 13664404461 0020075 0 ustar 00root root 0000000 0000000 desc 'Do a benchmark'
task :benchmark do
ruby 'bench/bench.rb ruby html'
end
task :bench => :benchmark
coderay-1.1.3/rake_tasks/code_statistics.rb 0000664 0000000 0000000 00000010410 13664404461 0021006 0 ustar 00root root 0000000 0000000 # From rails (http://rubyonrails.com)
#
# Improved by murphy
class CodeStatistics
TEST_TYPES = /\btest/i
# Create a new Code Statistic.
#
# Rakefile Example:
#
# desc 'Report code statistics (LOC) from the application'
# task :stats => :copy_files do
# require 'rake_helpers/code_statistics'
# CodeStatistics.new(
# ["Main", "lib"],
# ["Tests", "test"],
# ["Demos", "demo"]
# ).to_s
# end
def initialize(*pairs)
@pairs = pairs
@statistics = calculate_statistics
@total = if pairs.empty? then nil else calculate_total end
end
# Print a textual table viewing the stats
#
# Intended for console output.
def print
print_header
@pairs.each { |name, path| print_line name, @statistics[name] }
print_splitter
if @total
print_line 'Total', @total
print_splitter
end
print_code_test_stats
end
private
DEFAULT_FILE_PATTERN = /\.rb$/
def calculate_statistics
@pairs.inject({}) do |stats, (name, path, pattern, is_ruby_code)|
pattern ||= DEFAULT_FILE_PATTERN
path = File.join path, '*.rb'
stats[name] = calculate_directory_statistics path, pattern, is_ruby_code
stats
end
end
def calculate_directory_statistics directory, pattern = DEFAULT_FILE_PATTERN, is_ruby_code = true
is_ruby_code = true if is_ruby_code.nil?
stats = Hash.new 0
Dir[directory].each do |file_name|
p "Scanning #{file_name}..." if $VERBOSE
next unless file_name =~ pattern
lines = codelines = classes = modules = methods = 0
empty_lines = comment_lines = 0
in_comment_block = false
File.readlines(file_name).each do |line|
lines += 1
if line[/^\s*$/]
empty_lines += 1
elsif is_ruby_code
case line
when /^=end\b/
comment_lines += 1
in_comment_block = false
when in_comment_block
comment_lines += 1
when /^\s*class\b/
classes += 1
when /^\s*module\b/
modules += 1
when /^\s*def\b/
methods += 1
when /^\s*#/
comment_lines += 1
when /^=begin\b/
in_comment_block = false
comment_lines += 1
when /^__END__$/
in_comment_block = true
end
end
end
codelines = lines - comment_lines - empty_lines
stats[:lines] += lines
stats[:comments] += comment_lines
stats[:codelines] += codelines
stats[:classes] += classes
stats[:modules] += modules
stats[:methods] += methods
stats[:files] += 1
end
stats
end
def calculate_total
total = Hash.new 0
@statistics.each_value { |pair| pair.each { |k, v| total[k] += v } }
total
end
def calculate_code
code_loc = 0
@statistics.each { |k, v| code_loc += v[:codelines] unless k[TEST_TYPES] }
code_loc
end
def calculate_tests
test_loc = 0
@statistics.each { |k, v| test_loc += v[:codelines] if k[TEST_TYPES] }
test_loc
end
def print_header
print_splitter
puts "| T=Test Name | Files | Lines | LOC | Comments | Classes | Modules | Methods | M/C | LOC/M |"
print_splitter
end
def print_splitter
puts "+---------------------------+-------+-------+-------+----------+---------+---------+---------+-----+-------+"
end
def print_line name, statistics
m_over_c = (statistics[:methods] / (statistics[:classes] + statistics[:modules])) rescue m_over_c = 0
loc_over_m = (statistics[:codelines] / statistics[:methods]) - 2 rescue loc_over_m = 0
if name[TEST_TYPES]
name = "T #{name}"
else
name = " #{name}"
end
line = "| %-25s | %5d | %5d | %5d | %8d | %7d | %7d | %7d | %3d | %5d |" % (
[name, *statistics.values_at(:files, :lines, :codelines, :comments, :classes, :modules, :methods)] +
[m_over_c, loc_over_m] )
puts line
end
def print_code_test_stats
code = calculate_code
tests = calculate_tests
puts " Code LOC = #{code} Test LOC = #{tests} Code:Test Ratio = [1 : #{sprintf("%.2f", tests.to_f / code)}]"
puts ""
end
end
# Run a test script.
if $0 == __FILE__
$VERBOSE = true
CodeStatistics.new(
['This dir', File.dirname(__FILE__)]
).print
end
coderay-1.1.3/rake_tasks/documentation.rake 0000664 0000000 0000000 00000001065 13664404461 0021020 0 ustar 00root root 0000000 0000000 begin
if RUBY_VERSION >= '1.8.7'
gem 'rdoc' if defined? gem
require 'rdoc/task'
else
require 'rake/rdoctask'
end
rescue LoadError
warn 'Please gem install rdoc.'
end
desc 'Generate documentation for CodeRay'
Rake::RDocTask.new :doc do |rd|
rd.main = 'lib/README'
rd.title = 'CodeRay Documentation'
rd.options << '--line-numbers' << '--tab-width' << '2'
rd.main = 'README_INDEX.rdoc'
rd.rdoc_files.add 'README_INDEX.rdoc'
rd.rdoc_files.add Dir['lib']
rd.rdoc_dir = 'doc'
end if defined? Rake::RDocTask
coderay-1.1.3/rake_tasks/generator.rake 0000664 0000000 0000000 00000005466 13664404461 0020146 0 ustar 00root root 0000000 0000000 namespace :generate do
desc 'generates a new scanner NAME=lang [ALT=alternative,plugin,ids] [EXT=file,extensions] [BASE=base lang]'
task :scanner do
raise 'I need a scanner name; use NAME=lang' unless scanner_class_name = ENV['NAME']
raise "Invalid lang: #{scanner_class_name}; use NAME=lang." unless /\A\w+\z/ === scanner_class_name
require 'active_support/all'
lang = scanner_class_name.underscore
class_name = scanner_class_name.camelize
def scanner_file_for_lang lang
File.join(LIB_ROOT, 'coderay', 'scanners', lang + '.rb')
end
scanner_file = scanner_file_for_lang lang
if File.exist? scanner_file
print "#{scanner_file} already exists. Overwrite? [y|N] "
exit unless $stdin.gets.chomp.downcase == 'y'
end
base_lang = ENV.fetch('BASE', 'json')
base_scanner_file = scanner_file_for_lang(base_lang)
puts "Reading base scanner #{base_scanner_file}..."
base_scanner = File.read base_scanner_file
puts "Writing new scanner #{scanner_file}..."
File.open(scanner_file, 'w') do |file|
file.write base_scanner.
sub(/class \w+ < Scanner/, "class #{class_name} < Scanner").
sub('# Scanner for JSON (JavaScript Object Notation).', "# A scanner for #{scanner_class_name}.").
sub(/register_for :\w+/, "register_for :#{lang}").
sub(/file_extension '\S+'/, "file_extension '#{ENV.fetch('EXT', lang).split(',').first}'")
end
test_dir = File.join(ROOT, 'test', 'scanners', lang)
unless File.exist? test_dir
puts "Creating test folder #{test_dir}..."
sh "mkdir #{test_dir}"
end
test_suite_file = File.join(test_dir, 'suite.rb')
unless File.exist? test_suite_file
puts "Creating test suite file #{test_suite_file}..."
base_suite = File.read File.join(test_dir, '..', 'ruby', 'suite.rb')
File.open(test_suite_file, 'w') do |file|
file.write base_suite.sub(/class Ruby/, "class #{class_name}")
end
end
if extensions = ENV['EXT']
file_type_file = File.join(LIB_ROOT, 'coderay', 'helpers', 'filetype.rb')
puts "Not automated. Remember to add your extensions to #{file_type_file}:"
for ext in extensions.split(',')
puts " '#{ext}' => :#{lang},"
end
end
if alternative_ids = ENV['ALT'] && alternative_ids != lang
map_file = File.join(LIB_ROOT, 'coderay', 'scanners', '_map.rb')
puts "Not automated. Remember to add your alternative plugin ids to #{map_file}:"
for id in alternative_ids.split(',')
puts " :#{id} => :#{lang},"
end
end
print 'Add to git? [Y|n] '
answer = $stdin.gets.chomp.downcase
if answer.empty? || answer == 'y'
sh "git add #{scanner_file}"
cd File.join('test', 'scanners') do
sh "git add #{lang}"
end
end
end
end
coderay-1.1.3/rake_tasks/statistic.rake 0000664 0000000 0000000 00000001336 13664404461 0020157 0 ustar 00root root 0000000 0000000 desc 'Report code statistics (LOC) from the application'
task :stats do
require './rake_tasks/code_statistics'
CodeStatistics.new(
['Main', 'lib', /coderay.rb$/],
['CodeRay', 'lib/coderay/'],
[' Scanners', 'lib/coderay/scanners/**'],
[' Encoders', 'lib/coderay/encoders/**'],
[' Helpers', 'lib/coderay/helpers/**'],
[' Styles', 'lib/coderay/styles/**'],
['Executable', 'bin', /coderay$/],
['Executable Tests', 'test/executable/**'],
['Functional Tests', 'test/functional/**'],
['Scanner Tests', 'test/scanners/**', /suite\.rb$/],
['Unit Tests', 'test/unit/**'],
# [' Test Data', 'test/scanners/**', /\.in\./, false],
['Demos', 'sample/**']
).print
end
coderay-1.1.3/rake_tasks/test.rake 0000664 0000000 0000000 00000004467 13664404461 0017137 0 ustar 00root root 0000000 0000000 namespace :test do
desc 'run functional tests'
task :functional do
ruby './test/functional/suite.rb'
ruby './test/functional/for_redcloth.rb' unless (''.chop! rescue true)
end
desc 'run unit tests'
task :units do
ruby './test/unit/suite.rb'
end
scanner_suite = 'test/scanners/suite.rb'
desc 'run all scanner tests'
task :scanners => :update_scanner_suite do
ruby scanner_suite
end
desc 'update scanner test suite from GitHub'
task :update_scanner_suite do
if File.exist? scanner_suite
Dir.chdir File.dirname(scanner_suite) do
if File.directory? '.git'
puts 'Updating scanner test suite...'
sh 'git pull'
elsif File.directory? '.svn'
raise <<-ERROR
Found the deprecated Subversion scanner test suite in ./#{File.dirname(scanner_suite)}.
Please rename or remove it and run again to use the GitHub repository:
mv test/scanners test/scanners-old
ERROR
else
raise 'No scanner test suite found.'
end
end
else
puts 'Downloading scanner test suite...'
sh 'git clone https://github.com/rubychan/coderay-scanner-tests.git test/scanners/'
end unless ENV['SKIP_UPDATE_SCANNER_SUITE']
end
namespace :scanner do
Dir['./test/scanners/*'].each do |scanner|
next unless File.directory? scanner
lang = File.basename(scanner)
desc "run all scanner tests for #{lang}"
task lang => :update_scanner_suite do
ruby "./test/scanners/suite.rb #{lang}"
end
end
end
desc 'clean test output files'
task :clean do
for file in Dir['test/scanners/**/*.actual.*']
rm file
end
for file in Dir['test/scanners/**/*.debug.diff']
rm file
end
for file in Dir['test/scanners/**/*.debug.diff.html']
rm file
end
for file in Dir['test/scanners/**/*.expected.html']
rm file
end
end
desc 'test the CodeRay executable'
task :exe do
if RUBY_VERSION >= '1.8.7'
ruby './test/executable/suite.rb'
else
puts
puts "Can't run executable tests because shoulda-context requires Ruby 1.8.7+."
puts "Skipping."
end
end
end
if RUBY_VERSION >= '1.9'
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
end
task :test => %w(test:functional test:units test:exe spec)
coderay-1.1.3/spec/ 0000775 0000000 0000000 00000000000 13664404461 0014104 5 ustar 00root root 0000000 0000000 coderay-1.1.3/spec/coderay_spec.rb 0000664 0000000 0000000 00000001566 13664404461 0017101 0 ustar 00root root 0000000 0000000 require File.expand_path('../spec_helper', __FILE__)
RSpec.describe CodeRay do
describe '::VERSION' do
it "returns the Gem's version" do
expect(CodeRay::VERSION).to match(/\A\d\.\d\.\d?\z/)
end
end
describe '.coderay_path' do
it 'returns an absolute file path to the given code file' do
base = File.expand_path('../..', __FILE__)
expect(CodeRay.coderay_path('file')).to eq("#{base}/lib/coderay/file")
end
end
describe '.scan' do
let(:code) { 'puts "Hello, World!"' }
let(:tokens) do
[
['puts', :ident],
[' ', :space],
[:begin_group, :string],
['"', :delimiter],
['Hello, World!', :content],
['"', :delimiter],
[:end_group, :string]
].flatten
end
it 'returns tokens' do
expect(CodeRay.scan(code, :ruby).tokens).to eq(tokens)
end
end
end
coderay-1.1.3/spec/spec_helper.rb 0000664 0000000 0000000 00000011617 13664404461 0016730 0 ustar 00root root 0000000 0000000 require 'simplecov'
# This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# The generated `.rspec` file contains `--require spec_helper` which will cause
# this file to always be loaded, without a need to explicitly require it in any
# files.
#
# Given that it is always loaded, you are encouraged to keep this file as
# light-weight as possible. Requiring heavyweight dependencies from this file
# will add to the boot time of your test suite on EVERY test run, even for an
# individual file that may not need all of that loaded. Instead, consider making
# a separate helper file that requires the additional dependencies and performs
# the additional setup, and require it from the spec files that actually need
# it.
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
# rspec-expectations config goes here. You can use an alternate
# assertion/expectation library such as wrong or the stdlib/minitest
# assertions if you prefer.
config.expect_with :rspec do |expectations|
# This option will default to `true` in RSpec 4. It makes the `description`
# and `failure_message` of custom matchers include text for helper methods
# defined using `chain`, e.g.:
# be_bigger_than(2).and_smaller_than(4).description
# # => "be bigger than 2 and smaller than 4"
# ...rather than:
# # => "be bigger than 2"
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end if RUBY_VERSION >= '1.9'
# rspec-mocks config goes here. You can use an alternate test double
# library (such as bogus or mocha) by changing the `mock_with` option here.
config.mock_with :rspec do |mocks|
# Prevents you from mocking or stubbing a method that does not exist on
# a real object. This is generally recommended, and will default to
# `true` in RSpec 4.
mocks.verify_partial_doubles = true
end
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
# have no way to turn it off -- the option exists only for backwards
# compatibility in RSpec 3). It causes shared context metadata to be
# inherited by the metadata hash of host groups and examples, rather than
# triggering implicit auto-inclusion in groups with matching metadata.
config.shared_context_metadata_behavior = :apply_to_host_groups
# The settings below are suggested to provide a good initial experience
# with RSpec, but feel free to customize to your heart's content.
=begin
# This allows you to limit a spec run to individual examples or groups
# you care about by tagging them with `:focus` metadata. When nothing
# is tagged with `:focus`, all examples get run. RSpec also provides
# aliases for `it`, `describe`, and `context` that include `:focus`
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
config.filter_run_when_matching :focus
# Allows RSpec to persist some state between runs in order to support
# the `--only-failures` and `--next-failure` CLI options. We recommend
# you configure your source control system to ignore this file.
config.example_status_persistence_file_path = "spec/examples.txt"
# Limits the available syntax to the non-monkey patched syntax that is
# recommended. For more details, see:
# - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
# - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
config.disable_monkey_patching!
# This setting enables warnings. It's recommended, but in some cases may
# be too noisy due to issues in dependencies.
config.warnings = true
# Many RSpec users commonly either run the entire suite or an individual
# file, and it's useful to allow more verbose output when running an
# individual spec file.
if config.files_to_run.one?
# Use the documentation formatter for detailed output,
# unless a formatter has already been configured
# (e.g. via a command-line flag).
config.default_formatter = "doc"
end
# Print the 10 slowest examples and example groups at the
# end of the spec run, to help surface which specs are running
# particularly slow.
config.profile_examples = 10
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = :random
# Seed global randomization in this process using the `--seed` CLI option.
# Setting this allows you to use `--seed` to deterministically reproduce
# test failures related to randomization by passing the same `--seed` value
# as the one that triggered the failure.
Kernel.srand config.seed
=end
end
$:.unshift File.expand_path('../lib', __FILE__)
require 'coderay'
coderay-1.1.3/test/ 0000775 0000000 0000000 00000000000 13664404461 0014131 5 ustar 00root root 0000000 0000000 coderay-1.1.3/test/executable/ 0000775 0000000 0000000 00000000000 13664404461 0016252 5 ustar 00root root 0000000 0000000 coderay-1.1.3/test/executable/source.py 0000664 0000000 0000000 00000000027 13664404461 0020123 0 ustar 00root root 0000000 0000000 class ClassName(): pass coderay-1.1.3/test/executable/source.rb 0000664 0000000 0000000 00000000024 13664404461 0020073 0 ustar 00root root 0000000 0000000 class ClassName; end coderay-1.1.3/test/executable/source_with_comments.rb 0000664 0000000 0000000 00000000036 13664404461 0023036 0 ustar 00root root 0000000 0000000 # a class
class ClassName
end
coderay-1.1.3/test/executable/suite.rb 0000664 0000000 0000000 00000014601 13664404461 0017732 0 ustar 00root root 0000000 0000000 require 'simplecov' if RUBY_VERSION >= '1.9'
require 'test/unit'
require 'rubygems' unless defined? Gem
require 'shoulda-context'
require 'pathname'
require 'json'
$:.unshift File.expand_path('../../../lib', __FILE__)
require 'coderay'
puts "Running CodeRay #{CodeRay::VERSION} executable tests..."
class TestCodeRayExecutable < Test::Unit::TestCase
ROOT_DIR = Pathname.new(File.dirname(__FILE__)) + '..' + '..'
EXECUTABLE = ROOT_DIR + 'bin' + 'coderay'
RUBY_COMMAND = 'ruby'
EXE_COMMAND =
if RUBY_PLATFORM === 'java' && `ruby --ng -e '' 2> /dev/null` && $?.success?
# use Nailgun
"#{RUBY_COMMAND}--ng -I%s %s"
else
"#{RUBY_COMMAND} -I%s %s"
end % [ROOT_DIR + 'lib', EXECUTABLE]
def coderay args, options = {}
if options[:fake_tty]
command = "#{EXE_COMMAND} #{args} --tty"
else
command = "#{EXE_COMMAND} #{args}"
end
puts command if $DEBUG
if options[:input]
output = IO.popen "#{command} 2>&1", "r+" do |io|
io.write options[:input]
io.close_write
io.read
end
else
output = `#{command} 2>&1`
end
if output[EXECUTABLE.to_s]
raise output
else
output
end
end
context 'a simple call with no arguments' do
should 'work' do
assert_nothing_raised { coderay('') }
end
should 'print version and help' do
assert_match(/CodeRay #{CodeRay::VERSION}/, coderay(''))
assert_match(/usage:/, coderay(''))
end
end
context 'version' do
should 'be printed with -v' do
assert_match(/\ACodeRay #{CodeRay::VERSION}\Z/, coderay('-v'))
end
should 'be printed with --version' do
assert_match(/\ACodeRay #{CodeRay::VERSION}\Z/, coderay('--version'))
end
end
context 'help' do
should 'be printed with -h' do
assert_match(/^usage:/, coderay('-h'))
end
should 'be printed with --help' do
assert_match(/^usage:/, coderay('--help'))
end
should 'be printed with subcommand help' do
assert_match(/^usage:/, coderay('help'))
end
end
context 'commands' do
should 'be printed with subcommand commands' do
assert_match(/^ +help/, coderay('commands'))
assert_match(/^ +version/, coderay('commands'))
end
end
context 'highlighting a file to the terminal' do
source_file = ROOT_DIR + 'test/executable/source.py'
source = File.read source_file
ansi_seq = /\e\[[0-9;]+m/
should 'not throw an error' do
assert_nothing_raised { coderay(source_file, :fake_tty => true) }
end
should 'output its contents to stdout' do
target = coderay(source_file, :fake_tty => true)
assert_equal source, target.chomp.gsub(ansi_seq, '')
end
should 'output ANSI-colored text' do
target = coderay(source_file, :fake_tty => true)
assert_not_equal source, target.chomp
assert_equal 6, target.scan(ansi_seq).size
end
end
context 'highlighting a file into a pipe (source.rb -html > source.rb.html)' do
source_file = ROOT_DIR + 'test/executable/source.rb'
target_file = "#{source_file}.html"
command = "#{source_file} -html > #{target_file}"
source = File.read source_file
pre = %r{(.*?)
}m
tag = /<[^>]*>/
should 'not throw an error' do
assert_nothing_raised { coderay(command) }
end
should 'output its contents to the pipe' do
coderay(command)
target = File.read(target_file)
if target = target[pre, 1]
assert_equal source, target.gsub(tag, '').strip
else
flunk "target code has no tag: #{target}"
end
end
should 'output valid HTML' do
coderay(command)
target = File.read(target_file)
assert_not_equal source, target[pre, 1]
assert_equal 6, target[pre, 1].scan(tag).size
assert_match %r{\A\n\n}, target
end
end
context 'highlighting a file into another file (source.rb source.rb.json)' do
source_file = ROOT_DIR + 'test/executable/source.rb'
target_file = "#{source_file}.json"
command = "#{source_file} #{target_file}"
source = File.read source_file
text = /"text":"([^"]*)"/
should 'not throw an error' do
assert_nothing_raised { coderay(command) }
end
should 'output its contents to the file' do
coderay(command)
target = File.read(target_file)
assert_equal source, target.scan(text).join
end
should 'output JSON' do
coderay(command)
target = File.read(target_file)
assert_not_equal source, target
assert_equal 6, target.scan(text).size
end
end
context 'highlighting a file without explicit input type (source.py)' do
source_file = ROOT_DIR + 'test/executable/source.py'
command = "#{source_file} -html"
source = File.read source_file
pre = %r{(.*?)
}m
tag_class = /]*>/
should 'respect the file extension and highlight the input as Python' do
target = coderay(command)
assert_equal %w(keyword class keyword), target[pre, 1].scan(tag_class).flatten
end
end
context 'highlighting a file with explicit input type (-ruby source.py)' do
source_file = ROOT_DIR + 'test/executable/source.py'
command = "-ruby #{source_file} -html"
source = File.read source_file
pre = %r{(.*?)
}m
tag_class = /]*>/
should 'ignore the file extension and highlight the input as Ruby' do
target = coderay(command)
assert_equal %w(keyword class), target[pre, 1].scan(tag_class).flatten
end
end
context 'highlighting a file with explicit input and output type (-ruby source.py -span)' do
source_file = ROOT_DIR + 'test/executable/source.py'
command = "-ruby #{source_file} -span"
source = File.read source_file
span_tags = /<\/?span[^>]*>/
should 'just respect the output type and include span tags' do
target = coderay(command)
assert_equal source, target.chomp.gsub(span_tags, '')
end
end
context 'the LOC counter' do
source_file = ROOT_DIR + 'test/executable/source_with_comments.rb'
command = "-ruby -loc"
should 'work' do
output = coderay(command, :input => <<-CODE)
# test
=begin
=end
test
CODE
assert_equal "1\n", output
end
end
end
coderay-1.1.3/test/functional/ 0000775 0000000 0000000 00000000000 13664404461 0016273 5 ustar 00root root 0000000 0000000 coderay-1.1.3/test/functional/basic.rb 0000664 0000000 0000000 00000021115 13664404461 0017701 0 ustar 00root root 0000000 0000000 # encoding: utf-8
require 'test/unit'
require File.expand_path('../../lib/assert_warning', __FILE__)
$:.unshift File.expand_path('../../../lib', __FILE__)
require 'coderay'
class BasicTest < Test::Unit::TestCase
def test_version
assert_nothing_raised do
assert_match(/\A\d\.\d\.\d?\z/, CodeRay::VERSION)
end
end
def with_empty_load_path
old_load_path = $:.dup
$:.clear
yield
ensure
$:.replace old_load_path
end
def test_autoload
with_empty_load_path do
assert_nothing_raised do
CodeRay::Scanners::Java::BuiltinTypes
end
end
end
RUBY_TEST_CODE = 'puts "Hello, World!"'
RUBY_TEST_TOKENS = [
['puts', :ident],
[' ', :space],
[:begin_group, :string],
['"', :delimiter],
['Hello, World!', :content],
['"', :delimiter],
[:end_group, :string]
].flatten
def test_simple_scan
assert_nothing_raised do
assert_equal RUBY_TEST_TOKENS, CodeRay.scan(RUBY_TEST_CODE, :ruby).tokens
end
end
RUBY_TEST_HTML = 'puts "' +
'Hello, World!"'
def test_simple_highlight
assert_nothing_raised do
assert_equal RUBY_TEST_HTML, CodeRay.scan(RUBY_TEST_CODE, :ruby).html
end
end
def test_scan_file
CodeRay.scan_file __FILE__
end
def test_encode
assert_equal 1, CodeRay.encode('test', :python, :count)
end
def test_encode_tokens
assert_equal 1, CodeRay.encode_tokens(CodeRay::Tokens['test', :string], :count)
end
def test_encode_file
assert_equal File.read(__FILE__), CodeRay.encode_file(__FILE__, :text)
end
def test_highlight
assert_match 'test
', CodeRay.highlight('test', :python)
end
def test_highlight_file
assert_match "require 'test/unit'\n", CodeRay.highlight_file(__FILE__)
end
def test_duo
assert_equal(RUBY_TEST_CODE,
CodeRay::Duo[:plain, :text].highlight(RUBY_TEST_CODE))
assert_equal(RUBY_TEST_CODE,
CodeRay::Duo[:plain => :text].highlight(RUBY_TEST_CODE))
end
def test_duo_stream
assert_equal(RUBY_TEST_CODE,
CodeRay::Duo[:plain, :text].highlight(RUBY_TEST_CODE, :stream => true))
end
def test_comment_filter
assert_equal <<-EXPECTED, CodeRay.scan(<<-INPUT, :ruby).comment_filter.text
#!/usr/bin/env ruby
code
more code
EXPECTED
#!/usr/bin/env ruby
=begin
A multi-line comment.
=end
code
# A single-line comment.
more code # and another comment, in-line.
INPUT
end
def test_lines_of_code
assert_equal 2, CodeRay.scan(<<-INPUT, :ruby).lines_of_code
#!/usr/bin/env ruby
=begin
A multi-line comment.
=end
code
# A single-line comment.
more code # and another comment, in-line.
INPUT
rHTML = <<-RHTML
puts "Hello, world!"
DIV
# output as standalone HTML page (using CSS classes)
page = CodeRay.scan('puts "Hello, world!"', :ruby).page
assert_match <<-PAGE, page
1
2
3
5.times do
puts 'Hello, world!'
end
PAGE
# keep scanned tokens for later use
tokens = CodeRay.scan('{ "just": "an", "example": 42 }', :json)
assert_kind_of CodeRay::TokensProxy, tokens
assert_equal ["{", :operator, " ", :space, :begin_group, :key,
"\"", :delimiter, "just", :content, "\"", :delimiter,
:end_group, :key, ":", :operator, " ", :space,
:begin_group, :string, "\"", :delimiter, "an", :content,
"\"", :delimiter, :end_group, :string, ",", :operator,
" ", :space, :begin_group, :key, "\"", :delimiter,
"example", :content, "\"", :delimiter, :end_group, :key,
":", :operator, " ", :space, "42", :integer,
" ", :space, "}", :operator], tokens.tokens
# produce a token statistic
assert_equal <<-STATISTIC, tokens.statistic
Code Statistics
Tokens 26
Non-Whitespace 15
Bytes Total 31
Token Types (7):
type count ratio size (average)
-------------------------------------------------------------
TOTAL 26 100.00 % 1.2
delimiter 6 23.08 % 1.0
operator 5 19.23 % 1.0
space 5 19.23 % 1.0
key 4 15.38 % 0.0
:begin_group 3 11.54 % 0.0
:end_group 3 11.54 % 0.0
content 3 11.54 % 4.3
string 2 7.69 % 0.0
integer 1 3.85 % 2.0
STATISTIC
# count the tokens
assert_equal 26, tokens.count
# produce a HTML div, but with CSS classes
div = tokens.div(:css => :class)
assert_equal <<-DIV, div
1
puts "Hello, world!"{ "just": "an", "example": 42 }puts "Hello, world!"puts "Hello, World!"puts \"Hello, World!\"
BLOCKCODE
RedCloth.new('bc. puts "Hello, World!"').to_html
end
def test_for_redcloth_style
require 'coderay/for_redcloth'
assert_equal <<-BLOCKCODE.chomp,
puts \"Hello, World!\"
BLOCKCODE
RedCloth.new('bc{color: red}. puts "Hello, World!"').to_html
end
def test_for_redcloth_escapes
require 'coderay/for_redcloth'
assert_equal 'puts \"Hello, World!\"&
[project]_dff.skjd
BLOCKCODE
end
end if defined? RedCloth coderay-1.1.3/test/functional/suite.rb 0000664 0000000 0000000 00000000721 13664404461 0017751 0 ustar 00root root 0000000 0000000 require 'simplecov' if RUBY_VERSION >= '1.9'
require 'test/unit'
$VERBOSE = $CODERAY_DEBUG = true
$:.unshift File.expand_path('../../../lib', __FILE__)
require 'coderay'
mydir = File.dirname(__FILE__)
suite = Dir[File.join(mydir, '*.rb')].
map { |tc| File.basename(tc).sub(/\.rb$/, '') } - %w'suite for_redcloth'
puts "Running basic CodeRay #{CodeRay::VERSION} tests: #{suite.join(', ')}"
for test_case in suite
load File.join(mydir, test_case + '.rb')
end
coderay-1.1.3/test/lib/ 0000775 0000000 0000000 00000000000 13664404461 0014677 5 ustar 00root root 0000000 0000000 coderay-1.1.3/test/lib/README 0000664 0000000 0000000 00000000144 13664404461 0015556 0 ustar 00root root 0000000 0000000 Contents:
- test/unit: We need the old Test::Unit for the scanner test suite to work with Ruby 1.9.
coderay-1.1.3/test/lib/assert_warning.rb 0000664 0000000 0000000 00000000461 13664404461 0020253 0 ustar 00root root 0000000 0000000 class Test::Unit::TestCase
def assert_warning expected_warning
require 'stringio'
oldstderr = $stderr
$stderr = StringIO.new
yield
$stderr.rewind
given_warning = $stderr.read.chomp
assert_equal expected_warning, given_warning
ensure
$stderr = oldstderr
end
end
coderay-1.1.3/test/lib/test/ 0000775 0000000 0000000 00000000000 13664404461 0015656 5 ustar 00root root 0000000 0000000 coderay-1.1.3/test/lib/test/unit.rb 0000664 0000000 0000000 00000025513 13664404461 0017170 0 ustar 00root root 0000000 0000000 require 'test/unit/testcase'
require 'test/unit/autorunner'
module Test # :nodoc:
#
# = Test::Unit - Ruby Unit Testing Framework
#
# == Introduction
#
# Unit testing is making waves all over the place, largely due to the
# fact that it is a core practice of XP. While XP is great, unit testing
# has been around for a long time and has always been a good idea. One
# of the keys to good unit testing, though, is not just writing tests,
# but having tests. What's the difference? Well, if you just _write_ a
# test and throw it away, you have no guarantee that something won't
# change later which breaks your code. If, on the other hand, you _have_
# tests (obviously you have to write them first), and run them as often
# as possible, you slowly build up a wall of things that cannot break
# without you immediately knowing about it. This is when unit testing
# hits its peak usefulness.
#
# Enter Test::Unit, a framework for unit testing in Ruby, helping you to
# design, debug and evaluate your code by making it easy to write and
# have tests for it.
#
#
# == Notes
#
# Test::Unit has grown out of and superceded Lapidary.
#
#
# == Feedback
#
# I like (and do my best to practice) XP, so I value early releases,
# user feedback, and clean, simple, expressive code. There is always
# room for improvement in everything I do, and Test::Unit is no
# exception. Please, let me know what you think of Test::Unit as it
# stands, and what you'd like to see expanded/changed/improved/etc. If
# you find a bug, let me know ASAP; one good way to let me know what the
# bug is is to submit a new test that catches it :-) Also, I'd love to
# hear about any successes you have with Test::Unit, and any
# documentation you might add will be greatly appreciated. My contact
# info is below.
#
#
# == Contact Information
#
# A lot of discussion happens about Ruby in general on the ruby-talk
# mailing list (http://www.ruby-lang.org/en/ml.html), and you can ask
# any questions you might have there. I monitor the list, as do many
# other helpful Rubyists, and you're sure to get a quick answer. Of
# course, you're also welcome to email me (Nathaniel Talbott) directly
# at mailto:testunit@talbott.ws, and I'll do my best to help you out.
#
#
# == Credits
#
# I'd like to thank...
#
# Matz, for a great language!
#
# Masaki Suketa, for his work on RubyUnit, which filled a vital need in
# the Ruby world for a very long time. I'm also grateful for his help in
# polishing Test::Unit and getting the RubyUnit compatibility layer
# right. His graciousness in allowing Test::Unit to supercede RubyUnit
# continues to be a challenge to me to be more willing to defer my own
# rights.
#
# Ken McKinlay, for his interest and work on unit testing, and for his
# willingness to dialog about it. He was also a great help in pointing
# out some of the holes in the RubyUnit compatibility layer.
#
# Dave Thomas, for the original idea that led to the extremely simple
# "require 'test/unit'", plus his code to improve it even more by
# allowing the selection of tests from the command-line. Also, without
# RDoc, the documentation for Test::Unit would stink a lot more than it
# does now.
#
# Everyone who's helped out with bug reports, feature ideas,
# encouragement to continue, etc. It's a real privilege to be a part of
# the Ruby community.
#
# The guys at RoleModel Software, for putting up with me repeating, "But
# this would be so much easier in Ruby!" whenever we're coding in Java.
#
# My Creator, for giving me life, and giving it more abundantly.
#
#
# == License
#
# Test::Unit is copyright (c) 2000-2003 Nathaniel Talbott. It is free
# software, and is distributed under the Ruby license. See the COPYING
# file in the standard Ruby distribution for details.
#
#
# == Warranty
#
# This software is provided "as is" and without any express or
# implied warranties, including, without limitation, the implied
# warranties of merchantibility and fitness for a particular
# purpose.
#
#
# == Author
#
# Nathaniel Talbott.
# Copyright (c) 2000-2003, Nathaniel Talbott
#
# ----
#
# = Usage
#
# The general idea behind unit testing is that you write a _test_
# _method_ that makes certain _assertions_ about your code, working
# against a _test_ _fixture_. A bunch of these _test_ _methods_ are
# bundled up into a _test_ _suite_ and can be run any time the
# developer wants. The results of a run are gathered in a _test_
# _result_ and displayed to the user through some UI. So, lets break
# this down and see how Test::Unit provides each of these necessary
# pieces.
#
#
# == Assertions
#
# These are the heart of the framework. Think of an assertion as a
# statement of expected outcome, i.e. "I assert that x should be equal
# to y". If, when the assertion is executed, it turns out to be
# correct, nothing happens, and life is good. If, on the other hand,
# your assertion turns out to be false, an error is propagated with
# pertinent information so that you can go back and make your
# assertion succeed, and, once again, life is good. For an explanation
# of the current assertions, see Test::Unit::Assertions.
#
#
# == Test Method & Test Fixture
#
# Obviously, these assertions have to be called within a context that
# knows about them and can do something meaningful with their
# pass/fail value. Also, it's handy to collect a bunch of related
# tests, each test represented by a method, into a common test class
# that knows how to run them. The tests will be in a separate class
# from the code they're testing for a couple of reasons. First of all,
# it allows your code to stay uncluttered with test code, making it
# easier to maintain. Second, it allows the tests to be stripped out
# for deployment, since they're really there for you, the developer,
# and your users don't need them. Third, and most importantly, it
# allows you to set up a common test fixture for your tests to run
# against.
#
# What's a test fixture? Well, tests do not live in a vacuum; rather,
# they're run against the code they are testing. Often, a collection
# of tests will run against a common set of data, also called a
# fixture. If they're all bundled into the same test class, they can
# all share the setting up and tearing down of that data, eliminating
# unnecessary duplication and making it much easier to add related
# tests.
#
# Test::Unit::TestCase wraps up a collection of test methods together
# and allows you to easily set up and tear down the same test fixture
# for each test. This is done by overriding #setup and/or #teardown,
# which will be called before and after each test method that is
# run. The TestCase also knows how to collect the results of your
# assertions into a Test::Unit::TestResult, which can then be reported
# back to you... but I'm getting ahead of myself. To write a test,
# follow these steps:
#
# * Make sure Test::Unit is in your library path.
# * require 'test/unit' in your test script.
# * Create a class that subclasses Test::Unit::TestCase.
# * Add a method that begins with "test" to your class.
# * Make assertions in your test method.
# * Optionally define #setup and/or #teardown to set up and/or tear
# down your common test fixture.
# * You can now run your test as you would any other Ruby
# script... try it and see!
#
# A really simple test might look like this (#setup and #teardown are
# commented out to indicate that they are completely optional):
#
# require 'test/unit'
#
# class TC_MyTest < Test::Unit::TestCase
# # def setup
# # end
#
# # def teardown
# # end
#
# def test_fail
# assert(false, 'Assertion was false.')
# end
# end
#
#
# == Test Runners
#
# So, now you have this great test class, but you still need a way to
# run it and view any failures that occur during the run. This is
# where Test::Unit::UI::Console::TestRunner (and others, such as
# Test::Unit::UI::GTK::TestRunner) comes into play. The console test
# runner is automatically invoked for you if you require 'test/unit'
# and simply run the file. To use another runner, or to manually
# invoke a runner, simply call its run class method and pass in an
# object that responds to the suite message with a
# Test::Unit::TestSuite. This can be as simple as passing in your
# TestCase class (which has a class suite method). It might look
# something like this:
#
# require 'test/unit/ui/console/testrunner'
# Test::Unit::UI::Console::TestRunner.run(TC_MyTest)
#
#
# == Test Suite
#
# As more and more unit tests accumulate for a given project, it
# becomes a real drag running them one at a time, and it also
# introduces the potential to overlook a failing test because you
# forget to run it. Suddenly it becomes very handy that the
# TestRunners can take any object that returns a Test::Unit::TestSuite
# in response to a suite method. The TestSuite can, in turn, contain
# other TestSuites or individual tests (typically created by a
# TestCase). In other words, you can easily wrap up a group of
# TestCases and TestSuites like this:
#
# require 'test/unit/testsuite'
# require 'tc_myfirsttests'
# require 'tc_moretestsbyme'
# require 'ts_anothersetoftests'
#
# class TS_MyTests
# def self.suite
# suite = Test::Unit::TestSuite.new
# suite << TC_MyFirstTests.suite
# suite << TC_MoreTestsByMe.suite
# suite << TS_AnotherSetOfTests.suite
# return suite
# end
# end
# Test::Unit::UI::Console::TestRunner.run(TS_MyTests)
#
# Now, this is a bit cumbersome, so Test::Unit does a little bit more
# for you, by wrapping these up automatically when you require
# 'test/unit'. What does this mean? It means you could write the above
# test case like this instead:
#
# require 'test/unit'
# require 'tc_myfirsttests'
# require 'tc_moretestsbyme'
# require 'ts_anothersetoftests'
#
# Test::Unit is smart enough to find all the test cases existing in
# the ObjectSpace and wrap them up into a suite for you. It then runs
# the dynamic suite using the console TestRunner.
#
#
# == Questions?
#
# I'd really like to get feedback from all levels of Ruby
# practitioners about typos, grammatical errors, unclear statements,
# missing points, etc., in this document (or any other).
#
module Unit
# If set to false Test::Unit will not automatically run at exit.
def self.run=(flag)
@run = flag
end
# Automatically run tests at exit?
def self.run?
@run ||= false
end
end
end
at_exit do
unless $! || Test::Unit.run?
exit Test::Unit::AutoRunner.run
end
end
coderay-1.1.3/test/lib/test/unit/ 0000775 0000000 0000000 00000000000 13664404461 0016635 5 ustar 00root root 0000000 0000000 coderay-1.1.3/test/lib/test/unit/assertionfailederror.rb 0000664 0000000 0000000 00000000451 13664404461 0023410 0 ustar 00root root 0000000 0000000 #--
#
# Author:: Nathaniel Talbott.
# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.
module Test
module Unit
# Thrown by Test::Unit::Assertions when an assertion fails.
class AssertionFailedError < StandardError
end
end
end
coderay-1.1.3/test/lib/test/unit/assertions.rb 0000664 0000000 0000000 00000043463 13664404461 0021366 0 ustar 00root root 0000000 0000000 # Author:: Nathaniel Talbott.
# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.
require 'test/unit/assertionfailederror'
require 'test/unit/util/backtracefilter'
module Test
module Unit
##
# Test::Unit::Assertions contains the standard Test::Unit assertions.
# Assertions is included in Test::Unit::TestCase.
#
# To include it in your own code and use its functionality, you simply
# need to rescue Test::Unit::AssertionFailedError. Additionally you may
# override add_assertion to get notified whenever an assertion is made.
#
# Notes:
# * The message to each assertion, if given, will be propagated with the
# failure.
# * It is easy to add your own assertions based on assert_block().
#
# = Example Custom Assertion
#
# def deny(boolean, message = nil)
# message = build_message message, '> is not false or nil.', boolean
# assert_block message do
# not boolean
# end
# end
module Assertions
##
# The assertion upon which all other assertions are based. Passes if the
# block yields true.
#
# Example:
# assert_block "Couldn't do the thing" do
# do_the_thing
# end
public
def assert_block(message="assert_block failed.") # :yields:
_wrap_assertion do
if (! yield)
raise AssertionFailedError.new(message.to_s)
end
end
end
##
# Asserts that +boolean+ is not false or nil.
#
# Example:
# assert [1, 2].include?(5)
public
def assert(boolean, message=nil)
_wrap_assertion do
assert_block("assert should not be called with a block.") { !block_given? }
assert_block(build_message(message, "> is not true.", boolean)) { boolean }
end
end
##
# Passes if +expected+ == +actual.
#
# Note that the ordering of arguments is important, since a helpful
# error message is generated when this one fails that tells you the
# values of expected and actual.
#
# Example:
# assert_equal 'MY STRING', 'my string'.upcase
public
def assert_equal(expected, actual, message=nil)
full_message = build_message(message, <[project]_dff.skjd