diff options
Diffstat (limited to 'lib/coderay')
-rw-r--r-- | lib/coderay/encoder.rb | 6 | ||||
-rw-r--r-- | lib/coderay/encoders/debug.rb | 8 | ||||
-rw-r--r-- | lib/coderay/encoders/html.rb | 27 | ||||
-rw-r--r-- | lib/coderay/encoders/html/numerization.rb | 4 | ||||
-rw-r--r-- | lib/coderay/encoders/html/output.rb | 4 | ||||
-rw-r--r-- | lib/coderay/scanners/diff.rb | 104 | ||||
-rw-r--r-- | lib/coderay/styles/cycnus.rb | 10 | ||||
-rw-r--r-- | lib/coderay/styles/murphy.rb | 10 | ||||
-rwxr-xr-x | lib/coderay/token_classes.rb | 5 | ||||
-rw-r--r-- | lib/coderay/tokens.rb | 24 |
10 files changed, 188 insertions, 14 deletions
diff --git a/lib/coderay/encoder.rb b/lib/coderay/encoder.rb index ced0f6c..28b387b 100644 --- a/lib/coderay/encoder.rb +++ b/lib/coderay/encoder.rb @@ -133,7 +133,7 @@ module CodeRay # whether +text+ is a String. def token text, kind out = - if text.is_a? ::String # Ruby 1.9: :open.is_a? String + if text.is_a? ::String # Ruby 1.9: watch out, :open.is_a? String is true text_token text, kind elsif text.is_a? ::Symbol block_token text, kind @@ -152,6 +152,10 @@ module CodeRay open_token kind when :close close_token kind + when :begin_line + begin_line kind + when :end_line + end_line kind else raise 'unknown block action: %p' % action end diff --git a/lib/coderay/encoders/debug.rb b/lib/coderay/encoders/debug.rb index 8e1c0f0..a4b0648 100644 --- a/lib/coderay/encoders/debug.rb +++ b/lib/coderay/encoders/debug.rb @@ -35,6 +35,14 @@ module Encoders ">" end + def begin_line kind + "#{kind}[" + end + + def end_line kind + "]" + end + end end diff --git a/lib/coderay/encoders/html.rb b/lib/coderay/encoders/html.rb index 2edcf1d..8d13cf5 100644 --- a/lib/coderay/encoders/html.rb +++ b/lib/coderay/encoders/html.rb @@ -226,13 +226,16 @@ module Encoders text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] } end @opened[0] = type - if style = @css_style[@opened] + if text != "\n" && style = @css_style[@opened] @out << style << text << '</span>' else @out << text end else + case text + + # token groups, eg. strings when :open @opened[0] = type @out << (@css_style[@opened] || '<span>') @@ -248,6 +251,28 @@ module Encoders @out << '</span>' @opened.pop end + + # whole lines to be highlighted, eg. a deleted line in a diff + when :begin_line + @opened[0] = type + if style = @css_style[@opened] + @out << style.sub('<span', '<div') + else + @out << '<div>' + end + @opened << type + when :end_line + if @opened.empty? + # nothing to close + else + if $DEBUG and (@opened.size == 1 or @opened.last != type) + raise 'Malformed token stream: Trying to close a line (%p) \ + that is not open. Open are: %p.' % [type, @opened[1..-1]] + end + @out << '</div>' + @opened.pop + end + when nil raise 'Token with nil as text was given: %p' % [[text, type]] else diff --git a/lib/coderay/encoders/html/numerization.rb b/lib/coderay/encoders/html/numerization.rb index d784bbe..9f1667f 100644 --- a/lib/coderay/encoders/html/numerization.rb +++ b/lib/coderay/encoders/html/numerization.rb @@ -71,6 +71,7 @@ module Encoders line_numbers.gsub!(/\n/) { "<tt>\n</tt>" } line_numbers_table_tpl = TABLE.apply('LINE_NUMBERS', line_numbers) + gsub!(/<\/div>\n/) { '</div>' } gsub!(/\n/) { "<tt>\n</tt>" } wrap_in! line_numbers_table_tpl @wrapped_in = :div @@ -90,8 +91,9 @@ module Encoders end close = '</span>' * opened_tags.size - "<li>#{open}#{line}#{close}</li>" + "<li>#{open}#{line}#{close}</li>\n" end + chomp!("\n") wrap_in! LIST @wrapped_in = :div diff --git a/lib/coderay/encoders/html/output.rb b/lib/coderay/encoders/html/output.rb index e74e55e..8def95e 100644 --- a/lib/coderay/encoders/html/output.rb +++ b/lib/coderay/encoders/html/output.rb @@ -166,7 +166,9 @@ module Encoders # title="double click to expand" LIST = <<-`LIST` -<ol class="CodeRay"><%CONTENT%></ol> +<ol class="CodeRay"> +<%CONTENT%> +</ol> LIST PAGE = <<-`PAGE` diff --git a/lib/coderay/scanners/diff.rb b/lib/coderay/scanners/diff.rb new file mode 100644 index 0000000..d52458c --- /dev/null +++ b/lib/coderay/scanners/diff.rb @@ -0,0 +1,104 @@ +module CodeRay +module Scanners + + class Diff < Scanner + + register_for :diff + + def scan_tokens tokens, options + + line_kind = nil + state = :initial + + until eos? + kind = match = nil + + if match = scan(/\n/) + if line_kind + tokens << [:end_line, line_kind] + line_kind = nil + end + tokens << [match, :space] + next + end + + case state + + when :initial + if match = scan(/--- |\+\+\+ |=+|_+/) + tokens << [:begin_line, line_kind = :head] + tokens << [match, :head] + next unless match = scan(/.+/) + kind = :plain + elsif match = scan(/Index: |Property changes on: /) + tokens << [:begin_line, line_kind = :head] + tokens << [match, :head] + next unless match = scan(/.+/) + kind = :plain + elsif match = scan(/Added: /) + tokens << [:begin_line, line_kind = :head] + tokens << [match, :head] + next unless match = scan(/.+/) + kind = :plain + state = :added + elsif match = scan(/\\ /) + tokens << [:begin_line, line_kind = :change] + tokens << [match, :change] + next unless match = scan(/.+/) + kind = :plain + elsif scan(/(@@)((?>[^@\n]*))(@@)/) + tokens << [:begin_line, line_kind = :change] + tokens << [self[1], :change] + tokens << [self[2], :plain] + tokens << [self[3], :change] + next unless match = scan(/.+/) + kind = :plain + elsif match = scan(/\+/) + tokens << [:begin_line, line_kind = :insert] + tokens << [match, :insert] + next unless match = scan(/.+/) + kind = :plain + elsif match = scan(/-/) + tokens << [:begin_line, line_kind = :delete] + tokens << [match, :delete] + next unless match = scan(/.+/) + kind = :plain + elsif scan(/ .*/) + kind = :comment + elsif scan(/.+/) + tokens << [:begin_line, line_kind = :head] + kind = :plain + else + raise_inspect 'else case rached' + end + + when :added + if match = scan(/ \+/) + tokens << [:begin_line, line_kind = :insert] + tokens << [match, :insert] + next unless match = scan(/.+/) + kind = :plain + else + state = :initial + next + end + end + + match ||= matched + if $DEBUG and not kind + raise_inspect 'Error token %p in line %d' % + [[match, kind], line], tokens + end + raise_inspect 'Empty token', tokens unless match + + tokens << [match, kind] + end + + tokens << [:end_line, line_kind] if line_kind + tokens + end + + end + +end +end diff --git a/lib/coderay/styles/cycnus.rb b/lib/coderay/styles/cycnus.rb index b819d52..521c3c9 100644 --- a/lib/coderay/styles/cycnus.rb +++ b/lib/coderay/styles/cycnus.rb @@ -125,6 +125,16 @@ ol.CodeRay li { white-space: pre } .ty { color:#339; font-weight:bold } .v { color:#036 } .xt { color:#444 } + +.ins { background: #afa; } +.del { background: #faa; } +.chg { color: #aaf; background: #007; } +.head { color: #f8f; background: #505 } + +.ins .ins { color: #080; font-weight:bold } +.del .del { color: #800; font-weight:bold } +.chg .chg { color: #66f; } +.head .head { color: #f4f; } TOKENS end diff --git a/lib/coderay/styles/murphy.rb b/lib/coderay/styles/murphy.rb index 15faadb..211ab6b 100644 --- a/lib/coderay/styles/murphy.rb +++ b/lib/coderay/styles/murphy.rb @@ -114,6 +114,16 @@ ol.CodeRay li { white-space: pre; } .ty { color:#339; font-weight:bold; } .v { color:#036; } .xt { color:#444; } + +.ins { background: #afa; } +.del { background: #faa; } +.chg { color: #aaf; background: #007; } +.head { color: #f8f; background: #505 } + +.ins .ins { color: #080; font-weight:bold } +.del .del { color: #800; font-weight:bold } +.chg .chg { color: #66f; } +.head .head { color: #f4f; } TOKENS end diff --git a/lib/coderay/token_classes.rb b/lib/coderay/token_classes.rb index 77d48aa..d85d1af 100755 --- a/lib/coderay/token_classes.rb +++ b/lib/coderay/token_classes.rb @@ -61,6 +61,11 @@ module CodeRay :variable => 'v', :value => 'vl', :xml_text => 'xt', + + :insert => 'ins', + :delete => 'del', + :change => 'chg', + :head => 'head', :ident => :NO_HIGHLIGHT, # 'id' #:operator => 'op', diff --git a/lib/coderay/tokens.rb b/lib/coderay/tokens.rb index 7d82afb..50d324c 100644 --- a/lib/coderay/tokens.rb +++ b/lib/coderay/tokens.rb @@ -200,25 +200,29 @@ module CodeRay # # TODO: Test this! def fix + tokens = self.class.new # Check token nesting using a stack of kinds. opened = [] - for token, kind in self - if token == :open - opened.push kind - elsif token == :close + for type, kind in self + case type + when :open + opened.push [:close, kind] + when :begin_line + opened.push [:end_line, kind] + when :close, :end_line expected = opened.pop - if kind != expected + if [type, kind] != expected # Unexpected :close; decide what to do based on the kind: - # - token was opened earlier: also close tokens in between - # - token was never opened: delete the :close (skip with next) + # - token was never opened: delete the :close (just skip it) next unless opened.rindex expected - tokens << [:close, kind] until (kind = opened.pop) == expected + # - token was opened earlier: also close tokens in between + tokens << token until (token = opened.pop) == expected end end - tokens << [token, kind] + tokens << [type, kind] end # Close remaining opened tokens - tokens << [:close, kind] while kind = opened.pop + tokens << token while token = opened.pop tokens end |