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