From a3b4ad06b992bd418a1d34bfb271c09fd9bedf11 Mon Sep 17 00:00:00 2001 From: murphy Date: Tue, 21 Mar 2006 14:46:34 +0000 Subject: =?UTF-8?q?CodeRay::Duo=20added=20for=20cool=20caching!=20bench/ca?= =?UTF-8?q?ching.rb=20added=20t=C2=B4for=20demonstrating=20this.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HTML Encoder: creates unwrapped output by default (still problems with that.) Numerizing changed (doesn't try to prevent nesting errors) Speedup: "::String" is faster. --- bench/caching.rb | 39 +++++++++++++++++++++++++++++++ lib/coderay.rb | 9 +++++++ lib/coderay/duo.rb | 23 ++++++++++++++++++ lib/coderay/encoders/html.rb | 13 ++++------- lib/coderay/encoders/html/numerization.rb | 30 ++++++++++++------------ lib/coderay/encoders/html/output.rb | 4 ++-- lib/coderay/scanner.rb | 15 ++++++++++++ 7 files changed, 108 insertions(+), 25 deletions(-) create mode 100644 bench/caching.rb create mode 100644 lib/coderay/duo.rb diff --git a/bench/caching.rb b/bench/caching.rb new file mode 100644 index 0000000..3f39fb9 --- /dev/null +++ b/bench/caching.rb @@ -0,0 +1,39 @@ +require 'coderay' +require 'benchmark' + +N = 10 +$code = 'foo(Foo[:foo, /foo/m]); ' * 500 +Benchmark.bm 15 do |bm| + bm.report 'loading' do + CodeRay::Scanners.load :ruby + CodeRay::Encoders.load :div + end + bm.report 'CodeRay.encode' do N.times do + CodeRay.encode($code, :ruby, :div) + end end + bm.report 'Direct' do N.times do + CodeRay::Encoders::Div.new.encode_tokens( + CodeRay::Scanners::Ruby.new($code).tokenize + ) + end end + bm.report 'Semi-cached' do + encoder = CodeRay::Encoders::Div.new + N.times do + encoder.encode $code, :ruby + end + end + bm.report 'Fully cached' do + scanner = CodeRay::Scanners::Ruby.new('') + encoder = CodeRay::Encoders::Div.new + N.times do + scanner.string = $code + encoder.encode_tokens scanner.tokens + end + end + bm.report 'Duo cached' do + duo = CodeRay::Duo[:ruby, :div] + N.times do + duo.encode $code + end + end +end diff --git a/lib/coderay.rb b/lib/coderay.rb index e1dbcd2..6c84c8b 100644 --- a/lib/coderay.rb +++ b/lib/coderay.rb @@ -138,6 +138,7 @@ module CodeRay require 'coderay/tokens' require 'coderay/scanner' require 'coderay/encoder' + require 'coderay/duo' require 'coderay/style' @@ -271,6 +272,14 @@ module CodeRay Encoders[format].new options end + # Finds the Scanner class for +lang+ and creates an instance, passing + # +options+ to it. + # + # See Scanner.new. + def scanner lang, options = {} + Scanners[lang].new '', options + end + # Extract the options for the scanner from the +options+ hash. # # Returns an empty Hash if :scanner_options is not set. diff --git a/lib/coderay/duo.rb b/lib/coderay/duo.rb new file mode 100644 index 0000000..8187277 --- /dev/null +++ b/lib/coderay/duo.rb @@ -0,0 +1,23 @@ +module CodeRay + + class Duo + + attr_accessor :scanner, :encoder + + def initialize lang, format, options = {} + @scanner = CodeRay.scanner lang, CodeRay.get_scanner_options(options) + @encoder = CodeRay.encoder format, options + end + + class << self + alias [] new + end + + def encode code + @scanner.string = code + @encoder.encode_tokens(scanner.tokenize) + end + + end + +end diff --git a/lib/coderay/encoders/html.rb b/lib/coderay/encoders/html.rb index b75f9e5..11fa84c 100644 --- a/lib/coderay/encoders/html.rb +++ b/lib/coderay/encoders/html.rb @@ -36,7 +36,7 @@ module Encoders # # You can also use Encoders::Div and Encoders::Span. # - # Default: :page + # Default: nil # # === :line_numbers # Include line numbers in :table, :inline, :list or nil (no line numbers) @@ -73,7 +73,7 @@ module Encoders :style => :cycnus, - :wrap => :page, + :wrap => nil, :line_numbers => nil, :line_number_start => 1, @@ -208,17 +208,14 @@ module Encoders @out.extend Output @out.css = @css - @out.numerize! options[:line_numbers], options # if options[:line_numbers] - @out.wrap! options[:wrap] # if options[:wrap] - - #require 'pp' - #pp @css_style, @css_style.size + @out.numerize! options[:line_numbers], options + @out.wrap! options[:wrap] super end def token text, type - if text.is_a? String + if text.is_a? ::String if text =~ /#{HTML_ESCAPE_PATTERN}/o text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] } end diff --git a/lib/coderay/encoders/html/numerization.rb b/lib/coderay/encoders/html/numerization.rb index edce9eb..c5d96f3 100644 --- a/lib/coderay/encoders/html/numerization.rb +++ b/lib/coderay/encoders/html/numerization.rb @@ -1,5 +1,5 @@ module CodeRay - module Encoders +module Encoders class HTML @@ -9,13 +9,13 @@ module CodeRay clone.numerize!(*args) end - NUMERIZABLE_WRAPPINGS = { - :table => [:div, :page], +=begin NUMERIZABLE_WRAPPINGS = { + :table => [:div, :page, nil], :inline => :all, - :list => [:div, :page] + :list => [:div, :page, nil] } NUMERIZABLE_WRAPPINGS.default = :all - +=end def numerize! mode = :table, options = {} return self unless mode @@ -26,16 +26,17 @@ module CodeRay raise ArgumentError, "Invalid value %p for :line_number_start; Integer expected." % start end - allowed_wrappings = NUMERIZABLE_WRAPPINGS[mode] - unless allowed_wrappings == :all or allowed_wrappings.include? options[:wrap] - raise ArgumentError, "Can't numerize, :wrap must be in %p, but is %p" % [NUMERIZABLE_WRAPPINGS, options[:wrap]] - end + #allowed_wrappings = NUMERIZABLE_WRAPPINGS[mode] + #unless allowed_wrappings == :all or allowed_wrappings.include? options[:wrap] + # raise ArgumentError, "Can't numerize, :wrap must be in %p, but is %p" % [NUMERIZABLE_WRAPPINGS, options[:wrap]] + #end bold_every = options[:bold_every] bolding = - if bold_every == :no_bolding or bold_every == 0 + if bold_every == false proc { |line| line.to_s } elsif bold_every.is_a? Integer + raise ArgumentError, ":bolding can't be 0." if bold_every == 0 proc do |line| if line % bold_every == 0 "#{line}" # every bold_every-th number in bold @@ -44,11 +45,11 @@ module CodeRay end end else - raise ArgumentError, "Invalid value %p for :bolding; :no_bolding or Integer expected." % bolding + raise ArgumentError, 'Invalid value %p for :bolding; false or Integer expected.' % bold_every end line_count = count("\n") - line_count += 1 if self[-1] != ?\n + line_count += 1 unless self[-1] == ?\n case mode when :inline @@ -59,7 +60,6 @@ module CodeRay line += 1 "#{ line_number.rjust(max_width) } " end - #wrap! :div when :table # This is really ugly. @@ -97,8 +97,8 @@ module CodeRay @wrapped_in = :div else - raise ArgumentError, "Unknown value %p for mode: expected one of %p" % - [mode, NUMERIZABLE_WRAPPINGS.keys - [:all]] + raise ArgumentError, 'Unknown value %p for mode: expected one of %p' % + [mode, [:table, :list, :inline]] end self diff --git a/lib/coderay/encoders/html/output.rb b/lib/coderay/encoders/html/output.rb index 8096dc8..80ab4f1 100644 --- a/lib/coderay/encoders/html/output.rb +++ b/lib/coderay/encoders/html/output.rb @@ -158,10 +158,10 @@ module CodeRay DIV TABLE = <<-`TABLE` - +
-
<%LINE_NUMBERS%>
<%CONTENT%>
+ TABLE # title="double click to expand" diff --git a/lib/coderay/scanner.rb b/lib/coderay/scanner.rb index 33bcb09..5ff07a0 100644 --- a/lib/coderay/scanner.rb +++ b/lib/coderay/scanner.rb @@ -115,6 +115,16 @@ module CodeRay # More mnemonic accessor name for the input string. alias code string + def reset + super + reset_tokens + end + + def string= str + super + reset_tokens + end + # Scans the code and returns all tokens in a Tokens object. def tokenize options = {} options = @options.merge({}) #options @@ -158,6 +168,11 @@ module CodeRay "#{self.class}#scan_tokens not implemented." end + def reset_tokens + @tokens.clear + @cached_tokens = nil + end + # Scanner error with additional status information def raise_inspect msg, tokens, ambit = 30 raise ScanError, <<-EOE % [ -- cgit v1.2.1