lib/rouge/lexers/php.rb in rouge-2.0.7 vs lib/rouge/lexers/php.rb in rouge-2.1.0
- old
+ new
@@ -11,20 +11,22 @@
# Support Drupal file extensions, see:
# https://github.com/gitlabhq/gitlabhq/issues/8900
'*.module', '*.inc', '*.profile', '*.install', '*.test'
mimetypes 'text/x-php'
- default_options :parent => 'html'
+ option :start_inline, 'Whether to start with inline php or require <?php ... ?>. (default: best guess)'
+ option :funcnamehighlighting, 'Whether to highlight builtin functions (default: true)'
+ option :disabledmodules, 'Disable certain modules from being highlighted as builtins (default: empty)'
- def initialize(opts={})
+ def initialize(*)
+ super
+
# if truthy, the lexer starts highlighting with php code
# (no <?php required)
- @start_inline = opts.delete(:start_inline)
- @funcnamehighlighting = opts.delete(:funcnamehighlighting) { true }
- @disabledmodules = opts.delete(:disabledmodules) { [] }
-
- super(opts)
+ @start_inline = bool_option(:start_inline) { :guess }
+ @funcnamehighlighting = bool_option(:funcnamehighlighting) { true }
+ @disabledmodules = list_option(:disabledmodules)
end
def self.builtins
load Pathname.new(__FILE__).dirname.join('php/builtins.rb')
self.builtins
@@ -39,16 +41,26 @@
builtins.merge(fns)
end
end
end
- def start_inline?
- !!@start_inline
- end
+ # source: http://php.net/manual/en/language.variables.basics.php
+ # the given regex is invalid utf8, so... we're using the unicode
+ # "Letter" property instead.
+ id = /[\p{L}_][\p{L}\p{N}_]*/
+ nsid = /#{id}(?:\\#{id})*/
start do
- push :php if start_inline?
+ case @start_inline
+ when true
+ push :template
+ push :php
+ when false
+ push :template
+ when :guess
+ # pass
+ end
end
def self.keywords
@keywords ||= Set.new %w(
and E_PARSE old_function E_ERROR or as E_WARNING parent eval
@@ -68,26 +80,34 @@
return 0.3 if /<\?(?!xml)/ =~ text
0
end
state :root do
+ # some extremely rough heuristics to decide whether to start inline or not
+ rule(/\s*(?=<)/m) { delegate parent; push :template }
+ rule(/[^$]+(?=<\?(php|=))/) { delegate parent; push :template }
+
+ rule(//) { push :template; push :php }
+ end
+
+ state :template do
rule /<\?(php|=)?/, Comment::Preproc, :php
rule(/.*?(?=<\?)|.*/m) { delegate parent }
end
state :php do
rule /\?>/, Comment::Preproc, :pop!
# heredocs
- rule /<<<('?)([a-z_]\w*)\1\n.*?\n\2;?\n/im, Str::Heredoc
+ rule /<<<('?)(#{id})\1\n.*?\n\2;?\n/im, Str::Heredoc
rule /\s+/, Text
rule /#.*?\n/, Comment::Single
rule %r(//.*?\n), Comment::Single
# empty comment, otherwise seen as the start of a docstring
rule %r(/\*\*/), Comment::Multiline
rule %r(/\*\*.*?\*/)m, Str::Doc
rule %r(/\*.*?\*/)m, Comment::Multiline
- rule /(->|::)(\s*)([a-zA-Z_][a-zA-Z0-9_]*)/ do
+ rule /(->|::)(\s*)(#{id})/ do
groups Operator, Text, Name::Attribute
end
rule /[~!%^&*+=\|:.<>\/?@-]+/, Operator
rule /[\[\]{}();,]/, Punctuation
@@ -101,20 +121,20 @@
rule /(function)(\s+)(&?)(\s*)/ do
groups Keyword, Text, Operator, Text
push :funcname
end
- rule /(const)(\s+)([a-zA-Z_]\w*)/i do
+ rule /(const)(\s+)(#{id})/i do
groups Keyword, Text, Name::Constant
end
rule /(true|false|null)\b/, Keyword::Constant
- rule /\$\{\$+[a-z_]\w*\}/i, Name::Variable
- rule /\$+[a-z_]\w*/i, Name::Variable
+ rule /\$\{\$+#{id}\}/i, Name::Variable
+ rule /\$+#{id}/i, Name::Variable
# may be intercepted for builtin highlighting
- rule /[\\a-z_][\\\w]*/i do |m|
+ rule /\\?#{nsid}/i do |m|
name = m[0]
if self.class.keywords.include? name
token Keyword
elsif self.builtins.include? name
@@ -134,22 +154,22 @@
rule /"/, Str::Double, :string
end
state :classname do
rule /\s+/, Text
- rule /[a-z_][\\\w]*/i, Name::Class, :pop!
+ rule /#{nsid}/, Name::Class, :pop!
end
state :funcname do
- rule /[a-z_]\w*/i, Name::Function, :pop!
+ rule /#{id}/, Name::Function, :pop!
end
state :string do
rule /"/, Str::Double, :pop!
rule /[^\\{$"]+/, Str::Double
rule /\\([nrt\"$\\]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2})/,
Str::Escape
- rule /\$[a-zA-Z_][a-zA-Z0-9_]*(\[\S+\]|->[a-zA-Z_][a-zA-Z0-9_]*)?/, Name::Variable
+ rule /\$#{id}(\[\S+\]|->#{id})?/, Name::Variable
rule /\{\$\{/, Str::Interpol, :interp_double
rule /\{(?=\$)/, Str::Interpol, :interp_single
rule /(\{)(\S+)(\})/ do
groups Str::Interpol, Name::Variable, Str::Interpol