lib/rouge/lexers/elixir.rb in rouge-2.0.7 vs lib/rouge/lexers/elixir.rb in rouge-2.1.0

- old
+ new

@@ -13,17 +13,10 @@ filenames '*.ex', '*.exs' mimetypes 'text/x-elixir', 'application/x-elixir' - BRACES = [ - ['\{', '\}', 'cb'], - ['\[', '\]', 'sb'], - ['\(', '\)', 'pa'], - ['\<', '\>', 'lt'] - ] - state :root do rule /\s+/m, Text rule /#.*$/, Comment::Single rule %r{\b(case|cond|end|bc|lc|if|unless|try|loop|receive|fn|defmodule| defp?|defprotocol|defimpl|defrecord|defmacrop?|defdelegate| @@ -44,43 +37,24 @@ rule /[a-zA-Z_!][\w_]*[!\?]?/, Name rule %r{::|[%(){};,/\|:\\\[\]]}, Punctuation rule /@[a-zA-Z_]\w*|&\d/, Name::Variable rule %r{\b(0[xX][0-9A-Fa-f]+|\d(_?\d)*(\.(?![^\d\s]) (_?\d)*)?([eE][-+]?\d(_?\d)*)?|0[bB][01]+)\b}x, Num - rule %r{~r\/.*\/}, Str::Regex mixin :strings + mixin :sigil_strings end state :strings do rule /(%[A-Ba-z])?"""(?:.|\n)*?"""/, Str::Doc rule /'''(?:.|\n)*?'''/, Str::Doc rule /"/, Str::Doc, :dqs rule /'.*?'/, Str::Single rule %r{(?<!\w)\?(\\(x\d{1,2}|\h{1,2}(?!\h)\b|0[0-7]{0,2}(?![0-7])\b[^x0MC])|(\\[MC]-)+\w|[^\s\\])}, Str::Other - BRACES.each do |_, _, name| - mixin :"braces_#{name}" - end end - BRACES.each do |lbrace, rbrace, name| - state :"braces_#{name}" do - rule /%[a-z]#{lbrace}/, Str::Double, :"braces_#{name}_intp" - rule /%[A-Z]#{lbrace}/, Str::Double, :"braces_#{name}_no_intp" - end - - state :"braces_#{name}_intp" do - rule /#{rbrace}[a-z]*/, Str::Double, :pop! - mixin :enddoublestr - end - - state :"braces_#{name}_no_intp" do - rule /.*#{rbrace}[a-z]*/, Str::Double, :pop! - end - end - state :dqs do rule /"/, Str::Double, :pop! mixin :enddoublestr end @@ -100,9 +74,60 @@ end state :enddoublestr do mixin :interpoling rule /[^#"]+/, Str::Double + end + + state :sigil_strings do + # ~-sigiled strings + # ~(abc), ~[abc], ~<abc>, ~|abc|, ~r/abc/, etc + # Cribbed and adjusted from Ruby lexer + delimiter_map = { '{' => '}', '[' => ']', '(' => ')', '<' => '>' } + # Match a-z for custom sigils too + sigil_opens = Regexp.union(delimiter_map.keys + %w(| / ' ")) + rule /~([A-Za-z])?(#{sigil_opens})/ do |m| + open = Regexp.escape(m[2]) + close = Regexp.escape(delimiter_map[m[2]] || m[2]) + interp = /[SRCW]/ === m[1] + toktype = Str::Other + + puts " open: #{open.inspect}" if @debug + puts " close: #{close.inspect}" if @debug + + # regexes + if 'Rr'.include? m[1] + toktype = Str::Regex + push :regex_flags + end + + if 'Ww'.include? m[1] + push :list_flags + end + + token toktype + + push do + rule /#{close}/, toktype, :pop! + + if interp + mixin :interpoling + rule /#/, toktype + else + rule /[\\#]/, toktype + end + + rule /[^##{open}#{close}\\]+/m, toktype + end + end + end + + state :regex_flags do + rule /[fgimrsux]*/, Str::Regex, :pop! + end + + state :list_flags do + rule /[csa]?/, Str::Other, :pop! end end end end