summaryrefslogtreecommitdiff
path: root/lib/coderay
diff options
context:
space:
mode:
Diffstat (limited to 'lib/coderay')
-rw-r--r--lib/coderay/encoder.rb6
-rw-r--r--lib/coderay/encoders/debug.rb8
-rw-r--r--lib/coderay/encoders/html.rb27
-rw-r--r--lib/coderay/encoders/html/numerization.rb4
-rw-r--r--lib/coderay/encoders/html/output.rb4
-rw-r--r--lib/coderay/scanners/diff.rb104
-rw-r--r--lib/coderay/styles/cycnus.rb10
-rw-r--r--lib/coderay/styles/murphy.rb10
-rwxr-xr-xlib/coderay/token_classes.rb5
-rw-r--r--lib/coderay/tokens.rb24
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