[DRE-commits] [ruby-rouge] 01/03: Imported Upstream version 2.0.1

Youhei SASAKI uwabami-guest at moszumanska.debian.org
Tue Jun 21 12:54:38 UTC 2016


This is an automated email from the git hooks/post-receive script.

uwabami-guest pushed a commit to annotated tag debian/2.0.1-1
in repository ruby-rouge.

commit 24467873b189e1e731d8ced39075f3e50970f764
Author: Youhei SASAKI <uwabami at gfd-dennou.org>
Date:   Tue Jun 21 21:41:06 2016 +0900

    Imported Upstream version 2.0.1
---
 lib/rouge.rb                          |  13 +++
 lib/rouge/cli.rb                      |  29 +++--
 lib/rouge/demos/cfscript              |  18 +++
 lib/rouge/demos/kotlin                |   3 +
 lib/rouge/demos/pascal                |  14 +++
 lib/rouge/formatter.rb                |  25 ++++
 lib/rouge/formatters/html.rb          |  99 ++--------------
 lib/rouge/formatters/html_inline.rb   |  22 ++++
 lib/rouge/formatters/html_legacy.rb   |  44 ++++++++
 lib/rouge/formatters/html_linewise.rb |  27 +++++
 lib/rouge/formatters/html_pygments.rb |  16 +++
 lib/rouge/formatters/html_table.rb    |  61 ++++++++++
 lib/rouge/formatters/html_wrapper.rb  |  11 --
 lib/rouge/formatters/terminal256.rb   |  12 +-
 lib/rouge/guesser.rb                  |  46 ++++++++
 lib/rouge/guessers/filename.rb        |  25 ++++
 lib/rouge/guessers/glob_mapping.rb    |  46 ++++++++
 lib/rouge/guessers/mimetype.rb        |  14 +++
 lib/rouge/guessers/modeline.rb        |  42 +++++++
 lib/rouge/guessers/source.rb          |  39 +++++++
 lib/rouge/lexer.rb                    |  96 ++--------------
 lib/rouge/lexers/cfscript.rb          | 153 +++++++++++++++++++++++++
 lib/rouge/lexers/d.rb                 |   2 +-
 lib/rouge/lexers/groovy.rb            |  12 +-
 lib/rouge/lexers/http.rb              |   6 +-
 lib/rouge/lexers/javascript.rb        |  17 ++-
 lib/rouge/lexers/kotlin.rb            |  84 ++++++++++++++
 lib/rouge/lexers/pascal.rb            |  66 +++++++++++
 lib/rouge/lexers/praat.rb             | 207 ++++++++++++++++++----------------
 lib/rouge/plugins/redcarpet.rb        |   2 +-
 lib/rouge/theme.rb                    |  10 +-
 lib/rouge/themes/gruvbox.rb           | 167 +++++++++++++++++++++++++++
 lib/rouge/version.rb                  |   2 +-
 33 files changed, 1113 insertions(+), 317 deletions(-)

diff --git a/lib/rouge.rb b/lib/rouge.rb
index 9cfd8d7..d1e9b9f 100644
--- a/lib/rouge.rb
+++ b/lib/rouge.rb
@@ -36,6 +36,13 @@ load load_dir.join('rouge/util.rb')
 load load_dir.join('rouge/text_analyzer.rb')
 load load_dir.join('rouge/token.rb')
 
+load load_dir.join('rouge/guesser.rb')
+load load_dir.join('rouge/guessers/glob_mapping.rb')
+load load_dir.join('rouge/guessers/modeline.rb')
+load load_dir.join('rouge/guessers/filename.rb')
+load load_dir.join('rouge/guessers/mimetype.rb')
+load load_dir.join('rouge/guessers/source.rb')
+
 load load_dir.join('rouge/lexer.rb')
 load load_dir.join('rouge/regex_lexer.rb')
 load load_dir.join('rouge/template_lexer.rb')
@@ -47,6 +54,11 @@ end
 
 load load_dir.join('rouge/formatter.rb')
 load load_dir.join('rouge/formatters/html.rb')
+load load_dir.join('rouge/formatters/html_table.rb')
+load load_dir.join('rouge/formatters/html_pygments.rb')
+load load_dir.join('rouge/formatters/html_legacy.rb')
+load load_dir.join('rouge/formatters/html_linewise.rb')
+load load_dir.join('rouge/formatters/html_inline.rb')
 load load_dir.join('rouge/formatters/terminal256.rb')
 load load_dir.join('rouge/formatters/null.rb')
 
@@ -58,3 +70,4 @@ load load_dir.join('rouge/themes/github.rb')
 load load_dir.join('rouge/themes/monokai.rb')
 load load_dir.join('rouge/themes/molokai.rb')
 load load_dir.join('rouge/themes/monokai_sublime.rb')
+load load_dir.join('rouge/themes/gruvbox.rb')
diff --git a/lib/rouge/cli.rb b/lib/rouge/cli.rb
index a319a6b..3e80190 100644
--- a/lib/rouge/cli.rb
+++ b/lib/rouge/cli.rb
@@ -13,9 +13,9 @@ module Rouge
     def file
       case input
       when '-'
-        $stdin
+        IO.new($stdin.fileno, 'r:utf-8')
       when String
-        File.new(input)
+        File.new(input, 'r:utf-8')
       when ->(i){ i.respond_to? :read }
         input
       end
@@ -23,7 +23,7 @@ module Rouge
 
     def read
       @read ||= begin
-        File.read(file, encoding: 'utf-8') 
+        file.read
       rescue => e
         $stderr.puts "unable to open #{input}: #{e.message}"
         exit 1
@@ -181,6 +181,8 @@ module Rouge
       def self.parse(argv)
         opts = {
           :formatter => 'terminal256',
+          :theme => 'thankful_eyes',
+          :css_class => 'codehilite',
           :input_file => '-',
           :lexer_opts => {},
           :formatter_opts => {},
@@ -195,12 +197,14 @@ module Rouge
             opts[:mimetype] = argv.shift
           when '--lexer', '-l'
             opts[:lexer] = argv.shift
-          when '--formatter', '-f'
+          when '--formatter-preset', '-f'
             opts[:formatter] = argv.shift
+          when '--theme', '-t'
+            opts[:theme] = argv.shift
+          when '--css-class', '-c'
+            opts[:css_class] = argv.shift
           when '--lexer-opts', '-L'
             opts[:lexer_opts] = parse_cgi(argv.shift)
-          when '--formatter-opts', '-F'
-            opts[:formatter_opts] = parse_cgi(argv.shift)
           when /^--/
             error! "unknown option #{arg.inspect}"
           else
@@ -246,10 +250,17 @@ module Rouge
 
         @lexer_opts = opts[:lexer_opts]
 
-        formatter_class = Formatter.find(opts[:formatter]) \
-          or error! "unknown formatter #{opts[:formatter]}"
+        theme = Theme.find(opts[:theme]).new or error! "unknown theme #{opts[:theme]}"
 
-        @formatter = formatter_class.new(opts[:formatter_opts])
+        @formatter = case opts[:formatter]
+        when 'terminal256' then Formatters::Terminal256.new(theme)
+        when 'html' then Formatters::HTML.new
+        when 'html-pygments' then Formatters::HTMLPygments.new(Formatters::HTML.new, opts[:css_class])
+        when 'html-inline' then Formatters::HTMLInline.new(theme)
+        when 'html-table' then Formatters::HTMLTable.new(Formatters::HTML.new)
+        else
+          error! "unknown formatter preset #{opts[:formatter]}"
+        end
       end
 
       def run
diff --git a/lib/rouge/demos/cfscript b/lib/rouge/demos/cfscript
new file mode 100644
index 0000000..9006416
--- /dev/null
+++ b/lib/rouge/demos/cfscript
@@ -0,0 +1,18 @@
+component accessors="true" {
+
+  property type="string" name="firstName" default="";
+  property string username;
+
+  function init(){
+    return this;
+  }
+
+  public any function submitOrder( required product, coupon="", boolean results=true ){
+
+    var foo = function( required string baz, x=true, y=false ){
+      return "bar!";
+    };
+
+    return foo;
+  }
+}
\ No newline at end of file
diff --git a/lib/rouge/demos/kotlin b/lib/rouge/demos/kotlin
new file mode 100644
index 0000000..a27b0db
--- /dev/null
+++ b/lib/rouge/demos/kotlin
@@ -0,0 +1,3 @@
+fun main(args: Array<String>) {
+    println("Hello, world!")
+}
diff --git a/lib/rouge/demos/pascal b/lib/rouge/demos/pascal
new file mode 100644
index 0000000..16be537
--- /dev/null
+++ b/lib/rouge/demos/pascal
@@ -0,0 +1,14 @@
+program FizzBuzz(output);
+var
+  i: Integer;
+begin
+  for i := 1 to 100 do
+    if i mod 15 = 0 then
+      WriteLn('FizzBuzz')
+    else if i mod 3 = 0 then
+      WriteLn('Fizz')
+    else if i mod 5 = 0 then
+      WriteLn('Buzz')
+    else
+      WriteLn(i)
+end.
diff --git a/lib/rouge/formatter.rb b/lib/rouge/formatter.rb
index 646ae8d..f089f02 100644
--- a/lib/rouge/formatter.rb
+++ b/lib/rouge/formatter.rb
@@ -25,6 +25,10 @@ module Rouge
       new(opts).format(tokens, &b)
     end
 
+    def initialize(opts={})
+      # pass
+    end
+
     # Format a token stream.
     def format(tokens, &b)
       return stream(tokens, &b) if block_given?
@@ -46,5 +50,26 @@ module Rouge
     def stream(tokens, &b)
       raise 'abstract'
     end
+
+  protected
+    def token_lines(tokens, &b)
+      return enum_for(:token_lines, tokens) unless block_given?
+
+      out = []
+      tokens.each do |tok, val|
+        val.scan /\n|[^\n]+/ do |s|
+          if s == "\n"
+            yield out
+            out = []
+          else
+            out << [tok, s]
+          end
+        end
+      end
+
+      # for inputs not ending in a newline
+      yield out if out.any?
+    end
+
   end
 end
diff --git a/lib/rouge/formatters/html.rb b/lib/rouge/formatters/html.rb
index cdc8a2d..88a66ac 100644
--- a/lib/rouge/formatters/html.rb
+++ b/lib/rouge/formatters/html.rb
@@ -9,109 +9,32 @@ module Rouge
     class HTML < Formatter
       tag 'html'
 
-      # @option opts [String] :css_class ('highlight')
-      # @option opts [true/false] :line_numbers (false)
-      # @option opts [Rouge::CSSTheme] :inline_theme (nil)
-      # @option opts [true/false] :wrap (true)
-      #
-      # Initialize with options.
-      #
-      # If `:inline_theme` is given, then instead of rendering the
-      # tokens as <span> tags with CSS classes, the styles according to
-      # the given theme will be inlined in "style" attributes.  This is
-      # useful for formats in which stylesheets are not available.
-      #
-      # Content will be wrapped in a tag (`div` if tableized, `pre` if
-      # not) with the given `:css_class` unless `:wrap` is set to `false`.
-      def initialize(opts={})
-        @css_class = opts.fetch(:css_class, 'highlight')
-        @css_class = " class=#{@css_class.inspect}" if @css_class
-
-        @line_numbers = opts.fetch(:line_numbers, false)
-        @start_line = opts.fetch(:start_line, 1)
-        @inline_theme = opts.fetch(:inline_theme, nil)
-        @inline_theme = Theme.find(@inline_theme).new if @inline_theme.is_a? String
-
-        @wrap = opts.fetch(:wrap, true)
-      end
-
       # @yield the html output.
       def stream(tokens, &b)
-        if @line_numbers
-          stream_tableized(tokens, &b)
-        else
-          stream_untableized(tokens, &b)
-        end
+        tokens.each { |tok, val| yield span(tok, val) }
       end
 
-    private
-      def stream_untableized(tokens, &b)
-        yield "<pre#@css_class><code>" if @wrap
-        tokens.each{ |tok, val| span(tok, val, &b) }
-        yield "</code></pre>\n" if @wrap
+      def span(tok, val)
+        safe_span(tok, val.gsub(/[&<>]/, TABLE_FOR_ESCAPE_HTML))
       end
 
-      def stream_tableized(tokens)
-        num_lines = 0
-        last_val = ''
-        formatted = ''
-
-        tokens.each do |tok, val|
-          last_val = val
-          num_lines += val.scan(/\n/).size
-          span(tok, val) { |str| formatted << str }
-        end
+      def safe_span(tok, safe_val)
+        if tok == Token::Tokens::Text
+          safe_val
+        else
+          shortname = tok.shortname \
+            or raise "unknown token: #{tok.inspect} for #{safe_val.inspect}"
 
-        # add an extra line for non-newline-terminated strings
-        if last_val[-1] != "\n"
-          num_lines += 1
-          span(Token::Tokens::Text::Whitespace, "\n") { |str| formatted << str }
+          "<span class=\"#{shortname}\">#{safe_val}</span>"
         end
-
-        # generate a string of newline-separated line numbers for the gutter>
-        numbers = %<<pre class="lineno">#{(@start_line..num_lines+ at start_line-1)
-          .to_a.join("\n")}</pre>>
-
-        yield "<div#@css_class>" if @wrap
-        yield '<table style="border-spacing: 0"><tbody><tr>'
-
-        # the "gl" class applies the style for Generic.Lineno
-        yield '<td class="gutter gl" style="text-align: right">'
-        yield numbers
-        yield '</td>'
-
-        yield '<td class="code">'
-        yield '<pre>'
-        yield formatted
-        yield '</pre>'
-        yield '</td>'
-
-        yield "</tr></tbody></table>\n"
-        yield "</div>\n" if @wrap
       end
 
+    private
       TABLE_FOR_ESCAPE_HTML = {
         '&' => '&',
         '<' => '<',
         '>' => '>',
       }
-
-      def span(tok, val)
-        val = val.gsub(/[&<>]/, TABLE_FOR_ESCAPE_HTML)
-        shortname = tok.shortname or raise "unknown token: #{tok.inspect} for #{val.inspect}"
-
-        if shortname.empty?
-          yield val
-        else
-          if @inline_theme
-            rules = @inline_theme.style_for(tok).rendered_rules
-
-            yield "<span style=\"#{rules.to_a.join(';')}\">#{val}</span>"
-          else
-            yield "<span class=\"#{shortname}\">#{val}</span>"
-          end
-        end
-      end
     end
   end
 end
diff --git a/lib/rouge/formatters/html_inline.rb b/lib/rouge/formatters/html_inline.rb
new file mode 100644
index 0000000..a6a0a2f
--- /dev/null
+++ b/lib/rouge/formatters/html_inline.rb
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*- #
+
+module Rouge
+  module Formatters
+    class HTMLInline < HTML
+      tag 'html_inline'
+
+      def initialize(theme)
+        @theme = theme
+      end
+
+      def safe_span(tok, safe_val)
+        return safe_val if tok == Token::Tokens::Text
+
+        rules = @theme.style_for(tok).rendered_rules
+
+        "<span style=\"#{rules.to_a.join(';')}\">#{safe_val}</span>"
+      end
+    end
+  end
+end
+
diff --git a/lib/rouge/formatters/html_legacy.rb b/lib/rouge/formatters/html_legacy.rb
new file mode 100644
index 0000000..813cefb
--- /dev/null
+++ b/lib/rouge/formatters/html_legacy.rb
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*- #
+
+# stdlib
+require 'cgi'
+
+module Rouge
+  module Formatters
+    # Transforms a token stream into HTML output.
+    class HTMLLegacy < Formatter
+      tag 'html_legacy'
+
+      # @option opts [String] :css_class ('highlight')
+      # @option opts [true/false] :line_numbers (false)
+      # @option opts [Rouge::CSSTheme] :inline_theme (nil)
+      # @option opts [true/false] :wrap (true)
+      #
+      # Initialize with options.
+      #
+      # If `:inline_theme` is given, then instead of rendering the
+      # tokens as <span> tags with CSS classes, the styles according to
+      # the given theme will be inlined in "style" attributes.  This is
+      # useful for formats in which stylesheets are not available.
+      #
+      # Content will be wrapped in a tag (`div` if tableized, `pre` if
+      # not) with the given `:css_class` unless `:wrap` is set to `false`.
+      def initialize(opts={})
+        @formatter = opts[:inline_theme] ? HTMLInline.new(opts[:inline_theme])
+                   : HTML.new
+
+
+        @formatter = HTMLTable.new(@formatter, opts) if opts[:line_numbers]
+
+        if opts.fetch(:wrap, true)
+          @formatter = HTMLPygments.new(@formatter, opts.fetch(:css_class, 'codehilite'))
+        end
+      end
+
+      # @yield the html output.
+      def stream(tokens, &b)
+        @formatter.stream(tokens, &b)
+      end
+    end
+  end
+end
diff --git a/lib/rouge/formatters/html_linewise.rb b/lib/rouge/formatters/html_linewise.rb
new file mode 100644
index 0000000..55c8e72
--- /dev/null
+++ b/lib/rouge/formatters/html_linewise.rb
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*- #
+
+module Rouge
+  module Formatters
+    class HTMLLinewise < Formatter
+      def initialize(formatter, opts={})
+        @formatter = formatter
+        @class_format = opts.fetch(:class, 'line-%i')
+      end
+
+      def stream(tokens, &b)
+        token_lines(tokens) do |line|
+          yield "<div class=#{next_line_class}>"
+          line.each do |tok, val|
+            yield @formatter.span(tok, val)
+          end
+          yield '</div>'
+        end
+      end
+
+      def next_line_class
+        @lineno ||= 0
+        sprintf(@class_format, @lineno += 1).inspect
+      end
+    end
+  end
+end
diff --git a/lib/rouge/formatters/html_pygments.rb b/lib/rouge/formatters/html_pygments.rb
new file mode 100644
index 0000000..38c88c7
--- /dev/null
+++ b/lib/rouge/formatters/html_pygments.rb
@@ -0,0 +1,16 @@
+module Rouge
+  module Formatters
+    class HTMLPygments < Formatter
+      def initialize(inner, css_class='codehilite')
+        @inner = inner
+        @css_class = css_class
+      end
+
+      def stream(tokens, &b)
+        yield %<<pre class="#@css_class"><code>>
+        @inner.stream(tokens, &b)
+        yield "</code></pre>"
+      end
+    end
+  end
+end
diff --git a/lib/rouge/formatters/html_table.rb b/lib/rouge/formatters/html_table.rb
new file mode 100644
index 0000000..c440e34
--- /dev/null
+++ b/lib/rouge/formatters/html_table.rb
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*- #
+
+module Rouge
+  module Formatters
+    class HTMLTable < Formatter
+      tag 'html_table'
+
+      def initialize(inner, opts={})
+        @inner = inner
+        @start_line = opts.fetch(:start_line, 1)
+        @line_format = opts.fetch(:line_format, '%i')
+        @table_class = opts.fetch(:table_class, 'rouge-table')
+        @gutter_class = opts.fetch(:gutter_class, 'rouge-gutter')
+        @code_class = opts.fetch(:code_class, 'rouge-code')
+      end
+
+      def style(scope)
+        yield "#{scope} .rouge-table { border-spacing: 0 }"
+        yield "#{scope} .rouge-gutter { text-align: right }"
+      end
+
+      def stream(tokens, &b)
+        num_lines = 0
+        last_val = ''
+        formatted = ''
+
+        tokens.each do |tok, val|
+          last_val = val
+          num_lines += val.scan(/\n/).size
+          formatted << @inner.span(tok, val)
+        end
+
+        # add an extra line for non-newline-terminated strings
+        if last_val[-1] != "\n"
+          num_lines += 1
+          @inner.span(Token::Tokens::Text::Whitespace, "\n") { |str| formatted << str }
+        end
+
+        # generate a string of newline-separated line numbers for the gutter>
+        formatted_line_numbers = (@start_line..num_lines+ at start_line-1).map do |i|
+          sprintf("#{@line_format}", i) << "\n"
+        end.join('')
+
+        numbers = %<<pre class="lineno">#{formatted_line_numbers}</pre>>
+
+        yield %<<table class="#@table_class"><tbody><tr>>
+
+        # the "gl" class applies the style for Generic.Lineno
+        yield %<<td class="#@gutter_class gl">>
+        yield numbers
+        yield '</td>'
+
+        yield %<<td class="#@code_class"><pre>>
+        yield formatted
+        yield '</pre></td>'
+
+        yield "</tr></tbody></table>\n"
+      end
+    end
+  end
+end
diff --git a/lib/rouge/formatters/html_wrapper.rb b/lib/rouge/formatters/html_wrapper.rb
deleted file mode 100644
index d842099..0000000
--- a/lib/rouge/formatters/html_wrapper.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module Rouge
-  module Formatters
-    class HTMLWrapper
-      def initialize(open, formatter, close)
-        @open = open
-        @formatter = formatter
-        @close = close
-      end
-    end
-  end
-end
diff --git a/lib/rouge/formatters/terminal256.rb b/lib/rouge/formatters/terminal256.rb
index 165120d..b89d524 100644
--- a/lib/rouge/formatters/terminal256.rb
+++ b/lib/rouge/formatters/terminal256.rb
@@ -4,17 +4,13 @@ module Rouge
   module Formatters
     # A formatter for 256-color terminals
     class Terminal256 < Formatter
-      tag 'terminal256'
-
       # @private
       attr_reader :theme
 
-
-      # @option opts :theme
-      #   (default is thankful_eyes) the theme to render with.
-      def initialize(opts={})
-        @theme = opts[:theme] || 'thankful_eyes'
-        @theme = Theme.find(@theme) if @theme.is_a? String
+      # @argument theme
+      #   the theme to render with.
+      def initialize(theme=nil)
+        @theme = theme || Themes::ThankfulEyes
       end
 
       def stream(tokens, &b)
diff --git a/lib/rouge/guesser.rb b/lib/rouge/guesser.rb
new file mode 100644
index 0000000..a857a22
--- /dev/null
+++ b/lib/rouge/guesser.rb
@@ -0,0 +1,46 @@
+module Rouge
+  class Guesser
+    def self.guess(guessers, lexers)
+      original_size = lexers.size
+
+      guessers.each do |g|
+        new_lexers = case g
+        when Guesser then g.filter(lexers)
+        when proc { |x| x.respond_to? :call } then g.call(lexers)
+        else raise "bad guesser: #{g}"
+        end
+
+        lexers = new_lexers && new_lexers.any? ? new_lexers : lexers
+      end
+
+      # if we haven't filtered the input at *all*,
+      # then we have no idea what language it is,
+      # so we bail and return [].
+      lexers.size < original_size ? lexers : []
+    end
+
+    def collect_best(lexers, opts={}, &scorer)
+      best = []
+      best_score = opts[:threshold]
+
+      lexers.each do |lexer|
+        score = scorer.call(lexer)
+
+        next if score.nil?
+
+        if best_score.nil? || score > best_score
+          best_score = score
+          best = [lexer]
+        elsif score == best_score
+          best << lexer
+        end
+      end
+
+      best
+    end
+
+    def filter(lexers)
+      raise 'abstract'
+    end
+  end
+end
diff --git a/lib/rouge/guessers/filename.rb b/lib/rouge/guessers/filename.rb
new file mode 100644
index 0000000..f26bc04
--- /dev/null
+++ b/lib/rouge/guessers/filename.rb
@@ -0,0 +1,25 @@
+module Rouge
+  module Guessers
+    class Filename < Guesser
+      attr_reader :fname
+      def initialize(filename)
+        @filename = filename
+      end
+
+      # returns a list of lexers that match the given filename with
+      # equal specificity (i.e. number of wildcards in the pattern).
+      # This helps disambiguate between, e.g. the Nginx lexer, which
+      # matches `nginx.conf`, and the Conf lexer, which matches `*.conf`.
+      # In this case, nginx will win because the pattern has no wildcards,
+      # while `*.conf` has one.
+      def filter(lexers)
+        mapping = {}
+        lexers.each do |lexer|
+          mapping[lexer.name] = lexer.filenames || []
+        end
+
+        GlobMapping.new(mapping, @filename).filter(lexers)
+      end
+    end
+  end
+end
diff --git a/lib/rouge/guessers/glob_mapping.rb b/lib/rouge/guessers/glob_mapping.rb
new file mode 100644
index 0000000..431fa5d
--- /dev/null
+++ b/lib/rouge/guessers/glob_mapping.rb
@@ -0,0 +1,46 @@
+module Rouge
+  module Guessers
+    # This class allows for custom behavior
+    # with glob -> lexer name mappings
+    class GlobMapping < Guesser
+      def self.by_pairs(mapping, filename)
+        glob_map = {}
+        mapping.each do |(glob, lexer_name)|
+          lexer = Lexer.find(lexer_name)
+
+          # ignore unknown lexers
+          next unless lexer
+
+          glob_map[lexer.name] ||= []
+          glob_map[lexer.name] << glob
+        end
+
+        new(glob_map, filename)
+      end
+
+      attr_reader :glob_map, :filename
+      def initialize(glob_map, filename)
+        @glob_map = glob_map
+        @filename = filename
+      end
+
+      def filter(lexers)
+        basename = File.basename(filename)
+
+        collect_best(lexers) do |lexer|
+          score = (@glob_map[lexer.name] || []).map do |pattern|
+            if test_pattern(pattern, basename)
+              # specificity is better the fewer wildcards there are
+              -pattern.scan(/[*?\[]/).size
+            end
+          end.compact.min
+        end
+      end
+
+      private
+      def test_pattern(pattern, path)
+        File.fnmatch?(pattern, path, File::FNM_DOTMATCH | File::FNM_CASEFOLD)
+      end
+    end
+  end
+end
diff --git a/lib/rouge/guessers/mimetype.rb b/lib/rouge/guessers/mimetype.rb
new file mode 100644
index 0000000..c5ef017
--- /dev/null
+++ b/lib/rouge/guessers/mimetype.rb
@@ -0,0 +1,14 @@
+module Rouge
+  module Guessers
+    class Mimetype < Guesser
+      attr_reader :mimetype
+      def initialize(mimetype)
+        @mimetype = mimetype
+      end
+
+      def filter(lexers)
+        lexers.select { |lexer| lexer.mimetypes.include? @mimetype }
+      end
+    end
+  end
+end
diff --git a/lib/rouge/guessers/modeline.rb b/lib/rouge/guessers/modeline.rb
new file mode 100644
index 0000000..ac08b5f
--- /dev/null
+++ b/lib/rouge/guessers/modeline.rb
@@ -0,0 +1,42 @@
+module Rouge
+  module Guessers
+    class Modeline < Guesser
+      # [jneen] regexen stolen from linguist
+      EMACS_MODELINE = /-\*-\s*(?:(?!mode)[\w-]+\s*:\s*(?:[\w+-]+)\s*;?\s*)*(?:mode\s*:)?\s*([\w+-]+)\s*(?:;\s*(?!mode)[\w-]+\s*:\s*[\w+-]+\s*)*;?\s*-\*-/i
+
+      # First form vim modeline
+      # [text]{white}{vi:|vim:|ex:}[white]{options}
+      # ex: 'vim: syntax=ruby'
+      VIM_MODELINE_1 = /(?:vim|vi|ex):\s*(?:ft|filetype|syntax)=(\w+)\s?/i
+
+      # Second form vim modeline (compatible with some versions of Vi)
+      # [text]{white}{vi:|vim:|Vim:|ex:}[white]se[t] {options}:[text]
+      # ex: 'vim set syntax=ruby:'
+      VIM_MODELINE_2 = /(?:vim|vi|Vim|ex):\s*se(?:t)?.*\s(?:ft|filetype|syntax)=(\w+)\s?.*:/i
+
+      MODELINES = [EMACS_MODELINE, VIM_MODELINE_1, VIM_MODELINE_2]
+
+      def initialize(source, opts={})
+        @source = source
+        @lines = opts[:lines] || 5
+      end
+
+      def filter(lexers)
+        # don't bother reading the stream if we've already decided
+        return lexers if lexers.size == 1
+
+        source_text = @source
+        source_text = source_text.read if source_text.respond_to? :read
+
+        lines = source_text.split(/\r?\n/)
+
+        search_space = (lines.first(@lines) + lines.last(@lines)).join("\n")
+
+        matches = MODELINES.map { |re| re.match(search_space) }.compact
+        match_set = Set.new(matches.map { |m| m[1] })
+
+        lexers.select { |l| (Set.new([l.tag] + l.aliases) & match_set).any? }
+      end
+    end
+  end
+end
diff --git a/lib/rouge/guessers/source.rb b/lib/rouge/guessers/source.rb
new file mode 100644
index 0000000..5ee3c08
--- /dev/null
+++ b/lib/rouge/guessers/source.rb
@@ -0,0 +1,39 @@
+module Rouge
+  module Guessers
+    class Source < Guesser
+      attr_reader :source
+      def initialize(source)
+        @source = source
+      end
+
+      def filter(lexers)
+        # don't bother reading the input if
+        # we've already filtered to 1
+        return lexers if lexers.size == 1
+
+        # If we're filtering against *all* lexers, we only use confident return
+        # values from analyze_text.  But if we've filtered down already, we can trust
+        # the analysis more.
+        threshold = lexers.size < 10 ? 0 : 0.5
+
+        source_text = case @source
+        when String
+          @source
+        when ->(s){ s.respond_to? :read }
+          @source.read
+        else
+          raise 'invalid source'
+        end
+
+        Lexer.assert_utf8!(source_text)
+
+        source_text = TextAnalyzer.new(source_text)
+
+        collect_best(lexers, threshold: threshold) do |lexer|
+          next unless lexer.methods(false).include? :analyze_text
+          lexer.analyze_text(source_text)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rouge/lexer.rb b/lib/rouge/lexer.rb
index 6f0ad41..e213b95 100644
--- a/lib/rouge/lexer.rb
+++ b/lib/rouge/lexer.rb
@@ -109,26 +109,17 @@ module Rouge
       # to use.
       def guesses(info={})
         mimetype, filename, source = info.values_at(:mimetype, :filename, :source)
-        lexers = registry.values.uniq
-        total_size = lexers.size
-
-        lexers = filter_by_mimetype(lexers, mimetype) if mimetype
-        return lexers if lexers.size == 1
-
-        lexers = filter_by_filename(lexers, filename) if filename
-        return lexers if lexers.size == 1
-
-        if source
-          # If we're filtering against *all* lexers, we only use confident return
-          # values from analyze_text.  But if we've filtered down already, we can trust
-          # the analysis more.
-          source_threshold = lexers.size < total_size ? 0 : 0.5
-          return [best_by_source(lexers, source, source_threshold)].compact
-        elsif lexers.size < total_size
-          return lexers
-        else
-          return []
-        end
+        custom_globs = info[:custom_globs]
+
+        guessers = (info[:guessers] || []).dup
+
+        guessers << Guessers::Mimetype.new(mimetype) if mimetype
+        guessers << Guessers::GlobMapping.by_pairs(custom_globs, filename) if custom_globs && filename
+        guessers << Guessers::Filename.new(filename) if filename
+        guessers << Guessers::Modeline.new(source) if source
+        guessers << Guessers::Source.new(source) if source
+
+        Guesser.guess(guessers, Lexer.all)
       end
 
       class AmbiguousGuess < StandardError
@@ -175,71 +166,6 @@ module Rouge
       end
 
     private
-      def filter_by_mimetype(lexers, mt)
-        filtered = lexers.select { |lexer| lexer.mimetypes.include? mt }
-        filtered.any? ? filtered : lexers
-      end
-
-      # returns a list of lexers that match the given filename with
-      # equal specificity (i.e. number of wildcards in the pattern).
-      # This helps disambiguate between, e.g. the Nginx lexer, which
-      # matches `nginx.conf`, and the Conf lexer, which matches `*.conf`.
-      # In this case, nginx will win because the pattern has no wildcards,
-      # while `*.conf` has one.
-      def filter_by_filename(lexers, fname)
-        fname = File.basename(fname)
-
-        out = []
-        best_seen = nil
-        lexers.each do |lexer|
-          score = lexer.filenames.map do |pattern|
-            if File.fnmatch?(pattern, fname, File::FNM_DOTMATCH)
-              # specificity is better the fewer wildcards there are
-              pattern.scan(/[*?\[]/).size
-            end
-          end.compact.min
-
-          next unless score
-
-          if best_seen.nil? || score < best_seen
-            best_seen = score
-            out = [lexer]
-          elsif score == best_seen
-            out << lexer
-          end
-        end
-
-        out.any? ? out : lexers
-      end
-
-      def best_by_source(lexers, source, threshold=0)
-        source = case source
-        when String
-          source
-        when ->(s){ s.respond_to? :read }
-          source.read
-        else
-          raise 'invalid source'
-        end
-
-        assert_utf8!(source)
-
-        source = TextAnalyzer.new(source)
-
-        best_result = threshold
-        best_match = nil
-        lexers.each do |lexer|
-          result = lexer.analyze_text(source) || 0
-          return lexer if result == 1
-
-          if result > best_result
-            best_match = lexer
-            best_result = result
-          end
-        end
-
-        best_match
-      end
 
     protected
       # @private
diff --git a/lib/rouge/lexers/cfscript.rb b/lib/rouge/lexers/cfscript.rb
new file mode 100644
index 0000000..d3f65a0
--- /dev/null
+++ b/lib/rouge/lexers/cfscript.rb
@@ -0,0 +1,153 @@
+# -*- coding: utf-8 -*- #
+
+module Rouge
+  module Lexers
+
+    class Cfscript < RegexLexer
+      title "CFScript"
+      desc 'CFScript, the CFML scripting language'
+      tag 'cfscript'
+      aliases 'cfc'
+      filenames '*.cfc'
+
+      def self.keywords
+        @keywords ||= %w(
+          if else var xml default break switch do try catch throw in continue for return while required
+        )
+      end
+
+      def self.declarations
+        @declarations ||= %w(
+          component property function remote public package private
+        )
+      end
+
+      def self.types
+        @types ||= %w(
+          any array binary boolean component date guid numeric query string struct uuid void xml
+        )
+      end
+
+      constants = %w(application session client cookie super this variables arguments cgi)
+
+
+      operators = %w(\+\+ -- && \|\| <= >= < > == != mod eq lt gt lte gte not is and or xor eqv imp equal contains \? )
+      dotted_id = /[$a-zA-Z_][a-zA-Z0-9_.]*/
+
+      state :root do
+        mixin :comments_and_whitespace
+        rule /(?:#{operators.join('|')}|does not contain|greater than(?: or equal to)?|less than(?: or equal to)?)\b/i, Operator, :expr_start
+        rule %r([-<>+*%&|\^/!=]=?), Operator, :expr_start
+
+        rule /[(\[,]/, Punctuation, :expr_start
+        rule /;/, Punctuation, :statement
+        rule /[)\].]/, Punctuation
+
+        rule /[?]/ do
+          token Punctuation
+          push :ternary
+          push :expr_start
+        end
+
+        rule /[{}]/, Punctuation, :statement
+
+        rule /(?:#{constants.join('|')})\b/, Name::Constant
+        rule /(?:true|false|null)\b/, Keyword::Constant
+        rule /import\b/, Keyword::Namespace, :import
+        rule /(#{dotted_id})(\s*)(:)(\s*)/ do
+          groups Name, Text, Punctuation, Text
+          push :expr_start
+        end
+
+        rule /([A-Za-z_$][\w.]*)(\s*)(\()/ do |m|
+          if self.class.keywords.include? m[1]
+            token Keyword, m[1]
+            token Text, m[2]
+            token Punctuation, m[3]
+          else
+            token Name::Function, m[1]
+            token Text, m[2]
+            token Punctuation, m[3]
+          end
+        end
+
+        rule dotted_id do |m|
+          if self.class.declarations.include? m[0]
+            token Keyword::Declaration
+            push :expr_start
+          elsif self.class.keywords.include? m[0]
+            token Keyword
+            push :expr_start
+          elsif self.class.types.include? m[0]
+            token Keyword::Type
+            push :expr_start
+          else
+            token Name::Other
+          end
+        end
+
+        rule /[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?/, Num::Float
+        rule /0x[0-9a-fA-F]+/, Num::Hex
+        rule /[0-9]+/, Num::Integer
+        rule /"(\\\\|\\"|[^"])*"/, Str::Double
+        rule /'(\\\\|\\'|[^'])*'/, Str::Single
+
+      end
+
+      # same as java, broken out
+      state :comments_and_whitespace do
+        rule /\s+/, Text
+        rule %r(//.*?$), Comment::Single
+        rule %r(/\*.*?\*/)m, Comment::Multiline
+      end
+
+      state :expr_start do
+        mixin :comments_and_whitespace
+
+        rule /[{]/, Punctuation, :object
+
+        rule //, Text, :pop!
+      end
+
+      state :statement do
+
+        rule /[{}]/, Punctuation
+
+        mixin :expr_start
+      end
+
+      # object literals
+      state :object do
+        mixin :comments_and_whitespace
+        rule /[}]/ do
+          token Punctuation
+          push :expr_start
+        end
+
+        rule /(#{dotted_id})(\s*)(:)/ do
+          groups Name::Other, Text, Punctuation
+          push :expr_start
+        end
+
+        rule /:/, Punctuation
+        mixin :root
+      end
+
+      # ternary expressions, where <dotted_id>: is not a label!
+      state :ternary do
+        rule /:/ do
+          token Punctuation
+          goto :expr_start
+        end
+
+        mixin :root
+      end
+
+      state :import do
+        rule /\s+/m, Text
+        rule /[a-z0-9_.]+\*?/i, Name::Namespace, :pop!
+      end
+
+    end
+  end
+end
diff --git a/lib/rouge/lexers/d.rb b/lib/rouge/lexers/d.rb
index 8d80bba..a985e1d 100644
--- a/lib/rouge/lexers/d.rb
+++ b/lib/rouge/lexers/d.rb
@@ -9,7 +9,7 @@ module Rouge
       mimetypes 'application/x-dsrc', 'text/x-dsrc'
 
       title "D"
-      desc 'The D programming language(dlag.org)'
+      desc 'The D programming language(dlang.org)'
 
       keywords = %w(
         abstract alias align asm assert auto body
diff --git a/lib/rouge/lexers/groovy.rb b/lib/rouge/lexers/groovy.rb
index 3b82c1c..130b641 100644
--- a/lib/rouge/lexers/groovy.rb
+++ b/lib/rouge/lexers/groovy.rb
@@ -57,10 +57,14 @@ module Rouge
         rule /package\b/, Keyword::Namespace, :import
         rule /import\b/, Keyword::Namespace, :import
 
-        rule /"(\\\\|\\"|[^"])*"/, Str::Double
-        rule /'(\\\\|\\'|[^'])*'/, Str::Single
-        rule %r(\$/((?!/\$).)*/\$), Str
-        rule %r(/(\\\\|\\"|[^/])*/), Str
+        # TODO: highlight backslash escapes
+        rule /""".*?"""/m, Str::Double
+        rule /'''.*?'''/m, Str::Single
+
+        rule /"(\\.|\\\n|.)*?"/, Str::Double
+        rule /'(\\.|\\\n|.)*?'/, Str::Single
+        rule %r(\$/(\$.|.)*?/\$)m, Str
+        rule %r(/(\\.|\\\n|.)*?/), Str
         rule /'\\.'|'[^\\]'|'\\u[0-9a-f]{4}'/, Str::Char
         rule /(\.)([a-zA-Z_][a-zA-Z0-9_]*)/ do
           groups Operator, Name::Attribute
diff --git a/lib/rouge/lexers/http.rb b/lib/rouge/lexers/http.rb
index 95be336..4ea1021 100644
--- a/lib/rouge/lexers/http.rb
+++ b/lib/rouge/lexers/http.rb
@@ -7,8 +7,8 @@ module Rouge
       title "HTTP"
       desc 'http requests and responses'
 
-      def self.methods
-        @methods ||= %w(GET POST PUT DELETE HEAD OPTIONS TRACE PATCH)
+      def self.http_methods
+        @http_methods ||= %w(GET POST PUT DELETE HEAD OPTIONS TRACE PATCH)
       end
 
       def content_lexer
@@ -24,7 +24,7 @@ module Rouge
       state :root do
         # request
         rule %r(
-          (#{HTTP.methods.join('|')})([ ]+) # method
+          (#{HTTP.http_methods.join('|')})([ ]+) # method
           ([^ ]+)([ ]+)                     # path
           (HTTPS?)(/)(1[.][01])(\r?\n|$)  # http version
         )ox do
diff --git a/lib/rouge/lexers/javascript.rb b/lib/rouge/lexers/javascript.rb
index 7deed95..923a95c 100644
--- a/lib/rouge/lexers/javascript.rb
+++ b/lib/rouge/lexers/javascript.rb
@@ -2,6 +2,12 @@
 
 module Rouge
   module Lexers
+    # IMPORTANT NOTICE:
+    #
+    # Please do not copy this lexer and open a pull request
+    # for a new language. It will not get merged, you will
+    # be unhappy, and kittens will cry.
+    #
     class Javascript < RegexLexer
       title "JavaScript"
       desc "JavaScript, the browser scripting language"
@@ -33,7 +39,10 @@ module Rouge
           goto :regex
         end
 
-        rule /[{]/, Punctuation, :object
+        rule /[{]/ do
+          token Punctuation
+          goto :object
+        end
 
         rule //, Text, :pop!
       end
@@ -177,6 +186,12 @@ module Rouge
       # object literals
       state :object do
         mixin :comments_and_whitespace
+
+        rule /[{]/ do
+          token Punctuation
+          push
+        end
+
         rule /[}]/ do
           token Punctuation
           goto :statement
diff --git a/lib/rouge/lexers/kotlin.rb b/lib/rouge/lexers/kotlin.rb
new file mode 100644
index 0000000..5ce4542
--- /dev/null
+++ b/lib/rouge/lexers/kotlin.rb
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*- #
+
+module Rouge
+  module Lexers
+    class Kotlin < RegexLexer
+      title "Kotlin"
+      desc "Kotlin <http://kotlinlang.org>"
+
+      tag 'kotlin'
+      filenames '*.kt'
+      mimetypes 'text/x-kotlin'
+
+      keywords = %w(
+        abstract annotation as break by catch class companion const
+        constructor continue crossinline do dynamic else enum
+        external false final finally for fun get if import in infix
+        inline inner interface internal is lateinit noinline null
+        object open operator out override package private protected
+        public reified return sealed set super tailrec this throw
+        true try typealias typeof val var vararg when where while
+        yield
+      )
+
+      name = %r'@?[_\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Nl}][\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Nl}\p{Nd}\p{Pc}\p{Cf}\p{Mn}\p{Mc}]*'
+
+      id = %r'(#{name}|`#{name}`)'
+
+      state :root do
+        rule %r'^\s*\[.*?\]', Name::Attribute
+        rule %r'[^\S\n]+', Text
+        rule %r'\\\n', Text # line continuation
+        rule %r'//.*?\n', Comment::Single
+        rule %r'/[*].*?[*]/'m, Comment::Multiline
+        rule %r'\n', Text
+        rule %r'::|!!|\?[:.]', Operator
+        rule %r"(\.\.)", Operator
+        rule %r'[~!%^&*()+=|\[\]:;,.<>/?-]', Punctuation
+        rule %r'[{}]', Punctuation
+        rule %r'@"(""|[^"])*"'m, Str
+        rule %r'""".*?"""'m, Str
+        rule %r'"(\\\\|\\"|[^"\n])*["\n]'m, Str
+        rule %r"'\\.'|'[^\\]'", Str::Char
+        rule %r"[0-9](\.[0-9]+)?([eE][+-][0-9]+)?[flFL]?|0[xX][0-9a-fA-F]+[Ll]?", Num
+        rule %r'(class)(\s+)(object)' do
+          groups Keyword, Text, Keyword
+        end
+        rule %r'(class|data\s+class|interface|object)(\s+)' do
+          groups Keyword::Declaration, Text
+          push :class
+        end
+        rule %r'(package|import)(\s+)' do
+          groups Keyword, Text
+          push :package
+        end
+        rule %r'(val|var)(\s+)' do
+          groups Keyword::Declaration, Text
+          push :property
+        end
+        rule %r'(fun)(\s+)' do
+          groups Keyword, Text
+          push :function
+        end
+        rule /(?:#{keywords.join('|')})\b/, Keyword
+        rule id, Name
+      end
+
+      state :package do
+        rule /\S+/, Name::Namespace, :pop!
+      end
+
+      state :class do
+        rule id, Name::Class, :pop!
+      end
+
+      state :property do
+        rule id, Name::Property, :pop!
+      end
+
+      state :function do
+        rule id, Name::Function, :pop!
+      end
+    end
+  end
+end
diff --git a/lib/rouge/lexers/pascal.rb b/lib/rouge/lexers/pascal.rb
new file mode 100644
index 0000000..98f06cd
--- /dev/null
+++ b/lib/rouge/lexers/pascal.rb
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*- #
+
+module Rouge
+  module Lexers
+    class Pascal < RegexLexer
+      tag 'pascal'
+      title "Pascal"
+      desc 'a procedural programming language commonly used as a teaching language.'
+      filenames '*.pas'
+
+      mimetypes 'text/x-pascal'
+
+      id = /@?[_a-z]\w*/i
+
+      keywords = %w(
+        absolute abstract all and and_then array as asm assembler attribute
+        begin bindable case class const constructor delay destructor div do
+        downto else end except exit export exports external far file finalization
+        finally for forward function goto if implementation import in inc index
+        inherited initialization inline interface interrupt is label library
+        message mod module near nil not object of on only operator or or_else
+        otherwise out overload override packed pascal pow private procedure program
+        property protected public published qualified raise read record register
+        repeat resident resourcestring restricted safecall segment set shl shr
+        stdcall stored string then threadvar to try type unit until uses value var
+        view virtual while with write writeln xor
+      )
+
+      keywords_type = %w(
+        ansichar ansistring bool boolean byte bytebool cardinal char comp currency
+        double dword extended int64 integer iunknown longbool longint longword pansichar
+        pansistring pbool pboolean pbyte pbytearray pcardinal pchar pcomp pcurrency
+        pdate pdatetime pdouble pdword pextended phandle pint64 pinteger plongint plongword
+        pointer ppointer pshortint pshortstring psingle psmallint pstring pvariant pwidechar
+        pwidestring pword pwordarray pwordbool real real48 shortint shortstring single
+        smallint string tclass tdate tdatetime textfile thandle tobject ttime variant
+        widechar widestring word wordbool
+      )
+
+      state :whitespace do
+        # Spaces
+        rule /\s+/m, Text
+        # // Comments
+        rule %r((//).*$\n?), Comment::Single
+        # -- Comments
+        rule %r((--).*$\n?), Comment::Single
+        # (* Comments *)
+        rule %r(\(\*.*?\*\))m, Comment::Multiline
+        # { Comments }
+        rule %r(\{.*?\})m, Comment::Multiline
+      end
+
+      state :root do
+        mixin :whitespace
+
+        rule %r{((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?}, Num
+        rule %r{[~!@#\$%\^&\*\(\)\+`\-={}\[\]:;<>\?,\.\/\|\\]}, Punctuation
+        rule %r{'([^']|'')*'}, Str
+        rule /(true|false|nil)\b/i, Name::Builtin
+        rule /\b(#{keywords.join('|')})\b/i, Keyword
+        rule /\b(#{keywords_type.join('|')})\b/i, Keyword::Type
+        rule id, Name
+      end
+    end
+  end
+end
diff --git a/lib/rouge/lexers/praat.rb b/lib/rouge/lexers/praat.rb
index 82b25f3..089340c 100644
--- a/lib/rouge/lexers/praat.rb
+++ b/lib/rouge/lexers/praat.rb
@@ -16,7 +16,7 @@ module Rouge
 
       keywords = %w(
         if then else elsif elif endif fi for from to endfor endproc while
-        endwhile repeat until select plus minus demo assert stopwatch 
+        endwhile repeat until select plus minus demo assert stopwatch
         nocheck nowarn noprogress editor endeditor clearinfo
       )
 
@@ -39,7 +39,7 @@ module Rouge
         endSendPraat endsWith erb erbToHertz erf erfc exitScript exp
         extractNumber fileReadable fisherP fisherQ floor gaussP gaussQ
         hertzToBark hertzToErb hertzToMel hertzToSemitones imax imin
-        incompleteBeta incompleteGammaP index index_regex invBinomialP
+        incompleteBeta incompleteGammaP index index_regex integer invBinomialP
         invBinomialQ invChiSquareQ invFisherQ invGaussQ invSigmoid invStudentQ
         length ln lnBeta lnGamma log10 log2 max melToHertz min minusObject
         natural number numberOfColumns numberOfRows numberOfSelected
@@ -47,10 +47,10 @@ module Rouge
         phonToDifferenceLimens plusObject positive randomBinomial randomGauss
         randomInteger randomPoisson randomUniform real readFile removeObject
         rindex rindex_regex round runScript runSystem runSystem_nocheck
-        selectObject selected semitonesToHertz sentencetext sigmoid sin sinc
-        sincpi sinh soundPressureToPhon sqrt startsWith studentP studentQ tan
-        tanh variableExists word writeFile writeFileLine writeInfo
-        writeInfoLine
+        selectObject selected semitonesToHertz sentence sentencetext sigmoid
+        sin sinc sincpi sinh soundPressureToPhon sqrt startsWith studentP
+        studentQ tan tanh text variableExists word writeFile writeFileLine
+        writeInfo writeInfoLine
       )
 
       functions_array = %w(
@@ -62,29 +62,31 @@ module Rouge
         BarkFilter BarkSpectrogram CCA Categories Cepstrogram Cepstrum
         Cepstrumc ChebyshevSeries ClassificationTable Cochleagram Collection
         ComplexSpectrogram Configuration Confusion ContingencyTable Corpus
-        Correlation Covariance CrossCorrelationTable CrossCorrelationTables DTW
-        DataModeler Diagonalizer Discriminant Dissimilarity Distance
-        Distributions DurationTier EEG ERP ERPTier EditCostsTable
-        EditDistanceTable Eigen Excitation Excitations ExperimentMFC FFNet
-        FeatureWeights FileInMemory FilesInMemory Formant FormantFilter
-        FormantGrid FormantModeler FormantPoint FormantTier GaussianMixture HMM
-        HMM_Observation HMM_ObservationSequence HMM_State HMM_StateSequence
-        Harmonicity ISpline Index Intensity IntensityTier IntervalTier KNN
-        KlattGrid KlattTable LFCC LPC Label LegendreSeries LinearRegression
-        LogisticRegression LongSound Ltas MFCC MSpline ManPages Manipulation
-        Matrix MelFilter MelSpectrogram MixingMatrix Movie Network OTGrammar
-        OTHistory OTMulti PCA PairDistribution ParamCurve Pattern Permutation
-        Photo Pitch PitchModeler PitchTier PointProcess Polygon Polynomial
-        PowerCepstrogram PowerCepstrum Procrustes RealPoint RealTier ResultsMFC
-        Roots SPINET SSCP SVD Salience ScalarProduct Similarity SimpleString
-        SortedSetOfString Sound Speaker Spectrogram Spectrum SpectrumTier
-        SpeechSynthesizer SpellingChecker Strings StringsIndex Table
-        TableOfReal TextGrid TextInterval TextPoint TextTier Tier Transition
-        VocalTract VocalTractTier Weight WordList
+        Correlation Covariance CrossCorrelationTable CrossCorrelationTableList
+        CrossCorrelationTables DTW DataModeler Diagonalizer Discriminant
+        Dissimilarity Distance Distributions DurationTier EEG ERP ERPTier
+        EditCostsTable EditDistanceTable Eigen Excitation Excitations
+        ExperimentMFC FFNet FeatureWeights FileInMemory FilesInMemory Formant
+        FormantFilter FormantGrid FormantModeler FormantPoint FormantTier
+        GaussianMixture HMM HMM_Observation HMM_ObservationSequence HMM_State
+        HMM_StateSequence HMMObservation HMMObservationSequence HMMState
+        HMMStateSequence Harmonicity ISpline Index Intensity IntensityTier
+        IntervalTier KNN KlattGrid KlattTable LFCC LPC Label LegendreSeries
+        LinearRegression LogisticRegression LongSound Ltas MFCC MSpline ManPages
+        Manipulation Matrix MelFilter MelSpectrogram MixingMatrix Movie Network
+        OTGrammar OTHistory OTMulti PCA PairDistribution ParamCurve Pattern
+        Permutation Photo Pitch PitchModeler PitchTier PointProcess Polygon
+        Polynomial PowerCepstrogram PowerCepstrum Procrustes RealPoint RealTier
+        ResultsMFC Roots SPINET SSCP SVD Salience ScalarProduct Similarity
+        SimpleString SortedSetOfString Sound Speaker Spectrogram Spectrum
+        SpectrumTier SpeechSynthesizer SpellingChecker Strings StringsIndex
+        Table TableOfReal TextGrid TextInterval TextPoint TextTier Tier
+        Transition VocalTract VocalTractTier Weight WordList
       )
 
       variables_numeric = %w(
-        macintosh windows unix praatVersion pi e undefined
+        all average e left macintosh mono pi praatVersion right stereo
+        undefined unix windows
       )
 
       variables_string = %w(
@@ -93,6 +95,10 @@ module Rouge
         defaultDirectory
       )
 
+      object_attributes = %w(
+        ncol nrow xmin ymin xmax ymax nx ny dx dy
+      )
+
       state :root do
         rule /(\s+)(#.*?$)/ do
           groups Text, Comment::Single
@@ -107,6 +113,7 @@ module Rouge
 
         mixin :function_call
 
+        rule /\b(?:select all)\b/, Keyword
         rule /\b(?:#{keywords.join('|')})\b/, Keyword
 
         rule /(\bform\b)(\s+)([^\n]+)/ do
@@ -132,51 +139,25 @@ module Rouge
 
         rule /\b(?=[A-Z])/, Text, :command
         rule /(\.{3}|[)(,\$])/, Punctuation
-        rule /./, Generic::Error
       end
 
       state :command do
         rule /( ?[\w()-]+ ?)/, Keyword
-        rule /'(?=.*')/,  Literal::String::Interpol, :string_interpolated
-        rule /\.{3}/,     Keyword, :old_arguments
-        rule /:/,         Keyword, :comma_list
-        rule /[\s\n]/,    Text, :pop!
-      end
+        mixin :string_interpolated
 
-      state :function_call do
-        rule /\b(#{functions_string.join('|')})\$(?=\s*[:(])/, Name::Function, :function
-        rule /\b(#{functions_array.join('|')})#(?=\s*[:(])/,   Name::Function, :function
-        rule /\b(#{functions_numeric.join('|')})(?=\s*[:(])/,  Name::Function, :function
-      end
-
-      state :old_arguments do
-        rule /\n/ do
-          token Text
+        rule /\.{3}/ do
+          token Keyword
           pop!
-          pop! unless state? :root
+          push :old_arguments
         end
 
-        mixin :function_call
-        mixin :operator
-        mixin :number
-
-        rule /"/, Literal::String, :string
-        rule /[^\n]/, Text
-      end
-
-      state :function do
-        rule /\s+/, Text
-
         rule /:/ do
-          token Punctuation
-          push :comma_list
-        end
-
-        rule /\s*\(/ do
-          token Punctuation
+          token Keyword
           pop!
           push :comma_list
         end
+
+        rule /[\s\n]/,    Text, :pop!
       end
 
       state :procedure_call do
@@ -184,10 +165,14 @@ module Rouge
 
         rule /([\w.]+)(:|\s*\()/ do
           groups Name::Function, Punctuation
-          push :comma_list
+          pop!
         end
 
-        rule /([\w.]+)/, Name::Function, :old_arguments
+        rule /([\w.]+)/ do
+          token Name::Function
+          pop!
+          push :old_arguments
+        end
       end
 
       state :procedure_definition do
@@ -204,16 +189,28 @@ module Rouge
         end
       end
 
+      state :function_call do
+        rule /\b(#{functions_string.join('|')})\$(?=\s*[:(])/, Name::Function, :function
+        rule /\b(#{functions_array.join('|')})#(?=\s*[:(])/,   Name::Function, :function
+        rule /\b(#{functions_numeric.join('|')})(?=\s*[:(])/,  Name::Function, :function
+      end
+
+      state :function do
+        rule /\s+/, Text
+
+        rule /(?::|\s*\()/ do
+          token Text
+          pop!
+          push :comma_list
+        end
+      end
+
       state :comma_list do
         rule /(\s*\n\s*)(\.{3})/ do
           groups Text, Punctuation
         end
 
-        rule /\s*(\)|\]|\n)/ do
-          token Punctuation
-          pop!
-          pop! unless state? :root
-        end
+        rule /\s*[\])\n]/, Text, :pop!
 
         rule /\s+/, Text
         rule /"/,   Literal::String, :string
@@ -224,9 +221,21 @@ module Rouge
         mixin :operator
         mixin :number
 
+        rule /[()]/, Text
         rule /,/, Punctuation
       end
 
+      state :old_arguments do
+        rule /\n/, Text, :pop!
+
+        mixin :variable_name
+        mixin :operator
+        mixin :number
+
+        rule /"/, Literal::String, :string
+        rule /[^\n]/, Text
+      end
+
       state :number do
         rule /\n/, Text, :pop!
         rule /\b\d+(\.\d*)?([eE][-+]?\d+)?%?/, Literal::Number
@@ -237,43 +246,45 @@ module Rouge
         mixin :number
 
         rule /\b(?:#{variables_string.join('|')})\$/,  Name::Builtin
-        rule /\b(?:#{variables_numeric.join('|')})\b/, Name::Builtin
+        rule /\b(?:#{variables_numeric.join('|')})(?!\$)\b/, Name::Builtin
 
-        rule /\b(Object|#{objects.join('|')})_\w+/, Name::Builtin, :object_attributes
-
-        rule /\b((?:Object|#{objects.join('|')})_)(')/ do
-          groups Name::Builtin, Literal::String::Interpol
-          push :object_attributes
-          push :string_interpolated
+        rule /\b(Object|#{objects.join('|')})_/ do
+          token Name::Builtin
+          push :object_reference
         end
 
         rule /\.?[a-z][a-zA-Z0-9_.]*(\$|#)?/, Text
-        rule /[\[\]]/, Punctuation
-        rule /'(?=.*')/, Literal::String::Interpol, :string_interpolated
+        rule /[\[\]]/, Text, :comma_list
+        mixin :string_interpolated
       end
 
-      state :object_attributes do
-        rule /\.?(n(col|row)|[xy]min|[xy]max|[nd][xy])\b/, Name::Builtin, :pop!
-        rule /(\.?(?:col|row)\$)(\[)/ do
-          groups Name::Builtin, Punctuation
-          push :variable_name
-        end
-        rule /(\$?)(\[)/ do
-          groups Name::Builtin, Punctuation
-          push :comma_list
-        end
+      state :object_reference do
+        mixin :string_interpolated
+        rule /([a-z][a-zA-Z0-9_]*|\d+)/, Name::Builtin
+
+        rule /\.(#{object_attributes.join('|')})\b/, Name::Builtin, :pop!
+
+        rule /\$/, Name::Builtin
+        rule /\[/, Text, :pop!
+      end
+
+      state :operator do
+        # This rule incorrectly matches === or +++++, which are not operators
+        rule /([+\/*<>=!-]=?|[&*|][&*|]?|\^|<>)/,       Operator
+        rule /(?<![\w.])(and|or|not|div|mod)(?![\w.])/, Operator::Word
       end
 
       state :string_interpolated do
-        rule /\.?[_a-z][a-zA-Z0-9_.]*(?:[\$#]?(?:\[[a-zA-Z0-9,]+\])?|:[0-9]+)?/, Literal::String::Interpol
-        rule /'/, Literal::String::Interpol, :pop!
+        rule /'[\._a-z][^\[\]'":]*(\[([\d,]+|"[\w\d,]+")\])?(:[0-9]+)?'/, Literal::String::Interpol
       end
 
       state :string_unquoted do
         rule /\n\s*\.{3}/, Punctuation
         rule /\n/,         Text, :pop!
         rule /\s/,         Text
-        rule /'(?=.*')/,   Literal::String::Interpol, :string_interpolated
+
+        mixin :string_interpolated
+
         rule /'/,          Literal::String
         rule /[^'\n]+/,    Literal::String
       end
@@ -281,12 +292,18 @@ module Rouge
       state :string do
         rule /\n\s*\.{3}/, Punctuation
         rule /"/,          Literal::String,           :pop!
-        rule /'(?=.*')/,   Literal::String::Interpol, :string_interpolated
+
+        mixin :string_interpolated
+
         rule /'/,          Literal::String
         rule /[^'"\n]+/,   Literal::String
       end
 
       state :old_form do
+        rule /(\s+)(#.*?$)/ do
+          groups Text, Comment::Single
+        end
+
         rule /\s+/, Text
 
         rule /(optionmenu|choice)([ \t]+\S+:[ \t]+)/ do
@@ -296,11 +313,6 @@ module Rouge
 
         rule /(option|button)([ \t]+)/ do
           groups Keyword, Text
-          push :number
-        end
-
-        rule /(option|button)([ \t]+)/ do
-          groups Keyword, Text
           push :string_unquoted
         end
 
@@ -310,7 +322,7 @@ module Rouge
         end
 
         rule /(word)([ \t]+\S+[ \t]*)(\S+)?([ \t]+.*)?/ do
-          groups Keyword, Text, Literal::String, Generic::Error
+          groups Keyword, Text, Literal::String, Text
         end
 
         rule /(boolean)(\s+\S+\s*)(0|1|"?(?:yes|no)"?)/ do
@@ -330,11 +342,6 @@ module Rouge
         rule /\bendform\b/, Keyword, :pop!
       end
 
-      state :operator do
-        # This rule incorrectly matches === or +++++, which are not operators
-        rule /([+\/*<>=!-]=?|[&*|][&*|]?|\^|<>)/, Operator
-        rule /\b(and|or|not|div|mod)\b/,          Operator::Word
-      end
     end
   end
 end
diff --git a/lib/rouge/plugins/redcarpet.rb b/lib/rouge/plugins/redcarpet.rb
index f27511b..4ae513b 100644
--- a/lib/rouge/plugins/redcarpet.rb
+++ b/lib/rouge/plugins/redcarpet.rb
@@ -23,7 +23,7 @@ module Rouge
 
       # override this method for custom formatting behavior
       def rouge_formatter(lexer)
-        Formatters::HTML.new(:css_class => "highlight #{lexer.tag}")
+        Formatters::HTMLLegacy.new(:css_class => "highlight #{lexer.tag}")
       end
     end
   end
diff --git a/lib/rouge/theme.rb b/lib/rouge/theme.rb
index e35f689..d6d2ddf 100644
--- a/lib/rouge/theme.rb
+++ b/lib/rouge/theme.rb
@@ -63,6 +63,8 @@ module Rouge
       end
     end
 
+    def palette(*a) self.class.palette(*a) end
+
     @styles = {}
     def self.styles
       @styles ||= InheritableHash.new(superclass.styles)
@@ -76,8 +78,6 @@ module Rouge
       def style(*tokens)
         style = tokens.last.is_a?(Hash) ? tokens.pop : {}
 
-        style = Style.new(self, style)
-
         tokens.each do |tok|
           styles[tok] = style
         end
@@ -85,7 +85,7 @@ module Rouge
 
       def get_own_style(token)
         token.token_chain.reverse_each do |anc|
-          return styles[anc] if styles[anc]
+          return Style.new(self, styles[anc]) if styles[anc]
         end
 
         nil
@@ -96,7 +96,7 @@ module Rouge
       end
 
       def base_style
-        styles[Token::Tokens::Text]
+        get_own_style(Token::Tokens::Text)
       end
 
       def name(n=nil)
@@ -150,7 +150,7 @@ module Rouge
       yield "#{@scope} table pre { margin: 0; }"
 
       styles.each do |tok, style|
-        style.render(css_selector(tok), &b)
+        Style.new(self, style).render(css_selector(tok), &b)
       end
     end
 
diff --git a/lib/rouge/themes/gruvbox.rb b/lib/rouge/themes/gruvbox.rb
new file mode 100644
index 0000000..330803d
--- /dev/null
+++ b/lib/rouge/themes/gruvbox.rb
@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*- #
+
+# TODO how are we going to handle soft/hard contrast?
+
+module Rouge
+  module Themes
+    # Based on https://github.com/morhetz/gruvbox, with help from
+    # https://github.com/daveyarwood/gruvbox-pygments
+    class Gruvbox < CSSTheme
+      name 'gruvbox'
+
+      # global Gruvbox colours {{{
+      C_dark0_hard = '#1d2021'
+      C_dark0 ='#282828'
+      C_dark0_soft = '#32302f'
+      C_dark1 = '#3c3836'
+      C_dark2 = '#504945'
+      C_dark3 = '#665c54'
+      C_dark4 = '#7c6f64'
+      C_dark4_256 = '#7c6f64'
+
+      C_gray_245 = '#928374'
+      C_gray_244 = '#928374'
+
+      C_light0_hard = '#f9f5d7'
+      C_light0 = '#fbf1c7'
+      C_light0_soft = '#f2e5bc'
+      C_light1 = '#ebdbb2'
+      C_light2 = '#d5c4a1'
+      C_light3 = '#bdae93'
+      C_light4 = '#a89984'
+      C_light4_256 = '#a89984'
+
+      C_bright_red = '#fb4934'
+      C_bright_green = '#b8bb26'
+      C_bright_yellow = '#fabd2f'
+      C_bright_blue = '#83a598'
+      C_bright_purple = '#d3869b'
+      C_bright_aqua = '#8ec07c'
+      C_bright_orange = '#fe8019'
+
+      C_neutral_red = '#cc241d'
+      C_neutral_green = '#98971a'
+      C_neutral_yellow = '#d79921'
+      C_neutral_blue = '#458588'
+      C_neutral_purple = '#b16286'
+      C_neutral_aqua = '#689d6a'
+      C_neutral_orange = '#d65d0e'
+
+      C_faded_red = '#9d0006'
+      C_faded_green = '#79740e'
+      C_faded_yellow = '#b57614'
+      C_faded_blue = '#076678'
+      C_faded_purple = '#8f3f71'
+      C_faded_aqua = '#427b58'
+      C_faded_orange = '#af3a03'
+      # }}}
+
+      extend HasModes
+
+      def self.light!
+        mode :dark # indicate that there is a dark variant
+        mode! :light
+      end
+
+      def self.dark!
+        mode :light # indicate that there is a light variant
+        mode! :dark
+      end
+
+      def self.make_dark!
+        palette bg0: C_dark0
+        palette bg1: C_dark1
+        palette bg2: C_dark2
+        palette bg3: C_dark3
+        palette bg4: C_dark4
+
+        palette gray: C_gray_245
+
+        palette fg0: C_light0
+        palette fg1: C_light1
+        palette fg2: C_light2
+        palette fg3: C_light3
+        palette fg4: C_light4
+
+        palette fg4_256: C_light4_256
+
+        palette red: C_bright_red
+        palette green: C_bright_green
+        palette yellow: C_bright_yellow
+        palette blue: C_bright_blue
+        palette purple: C_bright_purple
+        palette aqua: C_bright_aqua
+        palette orange: C_bright_orange
+
+      end
+
+      def self.make_light!
+        palette bg0: C_light0
+        palette bg1: C_light1
+        palette bg2: C_light2
+        palette bg3: C_light3
+        palette bg4: C_light4
+
+        palette gray: C_gray_244
+
+        palette fg0: C_dark0
+        palette fg1: C_dark1
+        palette fg2: C_dark2
+        palette fg3: C_dark3
+        palette fg4: C_dark4
+
+        palette fg4_256: C_dark4_256
+
+        palette red: C_faded_red
+        palette green: C_faded_green
+        palette yellow: C_faded_yellow
+        palette blue: C_faded_blue
+        palette purple: C_faded_purple
+        palette aqua: C_faded_aqua
+        palette orange: C_faded_orange
+      end
+
+      dark!
+      mode :light
+
+      style Text, :fg => :fg0, :bg => :bg0
+      style Error, :fg => :red, :bg => :bg0, :bold => true
+      style Comment, :fg => :gray, :italic => true
+
+      style Comment::Preproc, :fg => :aqua
+
+      style Name::Tag, :fg => :red
+
+      style Operator,
+            Punctuation, :fg => :fg0
+
+      style Generic::Inserted, :fg => :green, :bg => :bg0
+      style Generic::Deleted, :fg => :red, :bg => :bg0
+      style Generic::Heading, :fg => :green, :bold => true
+
+      style Keyword, :fg => :red
+      style Keyword::Constant, :fg => :purple
+      style Keyword::Type, :fg => :yellow
+
+      style Keyword::Declaration, :fg => :orange
+
+      style Literal::String,
+            Literal::String::Interpol,
+            Literal::String::Regex, :fg => :green, :italic => true
+
+      style Literal::String::Escape, :fg => :orange
+
+      style Name::Namespace,
+            Name::Class, :fg => :aqua
+
+      style Name::Constant, :fg => :purple
+
+      style Name::Attribute, :fg => :green
+
+      style Literal::Number, :fg => :purple
+
+      style Literal::String::Symbol, :fg => :blue
+
+    end
+  end
+end
diff --git a/lib/rouge/version.rb b/lib/rouge/version.rb
index fb9c97c..053b168 100644
--- a/lib/rouge/version.rb
+++ b/lib/rouge/version.rb
@@ -2,6 +2,6 @@
 
 module Rouge
   def self.version
-    "1.11.0"
+    "2.0.1"
   end
 end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-rouge.git



More information about the Pkg-ruby-extras-commits mailing list