From a4bd413ca4e835fd3d1fdc24eebce67cd54231ca Mon Sep 17 00:00:00 2001 From: murphy Date: Tue, 30 Sep 2008 16:42:53 +0000 Subject: New: *Simple Diff Scanner* (closes #22). * Highlights unified diffs, especially like the ones svn diff outputs. * Changes to make highlighting of whole lines were necessary. * I added two example files. More changes: * Added token classes :head, :delete, :insert, and :change along with styles. * Added two new special token types: :begin_line and :end_line. They mark token groups that explicitly span whole lines and should be highlighted as such. * The HTML encoder converts these new tokens to DIVs. May need more work. * The Debug Encoder uses square brackets for line tokens. * Some cleanups. --- lib/coderay/scanners/diff.rb | 104 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 lib/coderay/scanners/diff.rb (limited to 'lib/coderay/scanners/diff.rb') 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 -- cgit v1.2.1