Class: CodeRay::Scanners::Ruby

Inherits:
Scanner
  • Object
show all
Includes:
CodeRay::Streamable
Defined in:
lib/coderay/scanners/ruby.rb,
lib/coderay/scanners/ruby/patterns.rb

Overview

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.

For now, I think it’s better than the scanners in VIM or Syntax, or any highlighter I was able to find, except Caleb’s RubyLexer.

I hope it’s also better than the rdoc/irb lexer.

Defined Under Namespace

Classes: StringState

Constant Summary collapse

DEFAULT_OPTIONS =
{
	:parse_regexps => true,
}
RESERVED_WORDS =
%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
]
DEF_KEYWORDS =
%w[ def ]
UNDEF_KEYWORDS =
%w[ undef ]
MODULE_KEYWORDS =
%w[class module]
DEF_NEW_STATE =
WordList.new(:initial).
add(DEF_KEYWORDS, :def_expected).
add(UNDEF_KEYWORDS, :undef_expected).
add(MODULE_KEYWORDS, :module_expected)
IDENTS_ALLOWING_REGEXP =
%w[
	and or not while until unless if then elsif when sub sub! gsub gsub! scan slice slice! split
]
REGEXP_ALLOWED =
WordList.new(false).
add(IDENTS_ALLOWING_REGEXP, :set)
PREDEFINED_CONSTANTS =
%w[
	nil true false self
	DATA ARGV ARGF __FILE__ __LINE__
]
IDENT_KIND =
WordList.new(:ident).
add(RESERVED_WORDS, :reserved).
add(PREDEFINED_CONSTANTS, :pre_constant)
IDENT =
/[a-z_][\w_]*/i
METHOD_NAME =
/ #{IDENT} [?!]? /ox
METHOD_NAME_OPERATOR =
/
	\*\*?           # multiplication and power
	| [-+]@?        # plus, minus
	| [\/%&|^`~]    # division, modulo or format strings, &and, |or, ^xor, `system`, tilde
	| \[\]=?        # array getter and setter
	| << | >>       # append or shift left, shift right
	| <=?>? | >=?   # comparison, rocket operator
	| ===?          # simple equality and case equality
/ox
METHOD_NAME_EX =
/ #{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,
}
REGEXP_MODIFIERS =
/[mixounse]*/
REGEXP_SYMBOLS =
/[|?*+?(){}\[\].^$]/
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
ESCAPE =

TODO investigste M, \c and C escape sequences (?: M-C-|C-M-|M-\c|cM-|c|C-|M-)? (?: \ (?: [0-7]3 | x2 | . ) ) assert_equal(225, ?M-a) assert_equal(129, ?M-C-a)

/
		[abefnrstv]
	| M-\\C-|C-\\M-|M-\\c|c\\M-|c|C-|M-
	|	[0-7]{1,3}
	| x[0-9A-Fa-f]{1,2}
	| .
/mx
CHARACTER =
/
	\?
	(?:
		[^\s\\]
	| \\ #{ESCAPE}
	)
/mx
HEREDOC_OPEN =

NOTE: This is not completely correct, but nobody needs heredoc delimiters ending with \n.

/
	<< (-)?              # $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
RDOC_DATA_START =
/ ^=begin (?!\S) | ^__END__$ /x
FANCY_START =
/ % ( [qQwWxsr] | (?![\w\s=]) ) (.) /mox
FancyStringType =
{
	'q' => [:string, false],
	'Q' => [:string, true],
	'r' => [:regexp, true],
	's' => [:symbol, false],
	'x' => [:shell, true],
	'w' => [:string, :word],
	'W' => [:string, :word],
}

Constants inherited from Scanner

Scanner::ScanError

Method Summary

Methods inherited from Scanner

#each, #initialize, #line, streamable?, #tokenize

Methods included from Plugin

#helper, #included, #plugin_host, #plugin_id, #register_for

Constructor Details

This class inherits a constructor from CodeRay::Scanners::Scanner