Chris@0: module CodeRay Chris@0: module Scanners Chris@0: Chris@0: class Diff < Scanner Chris@0: Chris@0: register_for :diff Chris@0: title 'diff output' Chris@0: Chris@0: def scan_tokens tokens, options Chris@0: Chris@0: line_kind = nil Chris@0: state = :initial Chris@0: Chris@0: until eos? Chris@0: kind = match = nil Chris@0: Chris@0: if match = scan(/\n/) Chris@0: if line_kind Chris@0: tokens << [:end_line, line_kind] Chris@0: line_kind = nil Chris@0: end Chris@0: tokens << [match, :space] Chris@0: next Chris@0: end Chris@0: Chris@0: case state Chris@0: Chris@0: when :initial Chris@0: if match = scan(/--- |\+\+\+ |=+|_+/) Chris@0: tokens << [:begin_line, line_kind = :head] Chris@0: tokens << [match, :head] Chris@0: next unless match = scan(/.+/) Chris@0: kind = :plain Chris@0: elsif match = scan(/Index: |Property changes on: /) Chris@0: tokens << [:begin_line, line_kind = :head] Chris@0: tokens << [match, :head] Chris@0: next unless match = scan(/.+/) Chris@0: kind = :plain Chris@0: elsif match = scan(/Added: /) Chris@0: tokens << [:begin_line, line_kind = :head] Chris@0: tokens << [match, :head] Chris@0: next unless match = scan(/.+/) Chris@0: kind = :plain Chris@0: state = :added Chris@0: elsif match = scan(/\\ /) Chris@0: tokens << [:begin_line, line_kind = :change] Chris@0: tokens << [match, :change] Chris@0: next unless match = scan(/.+/) Chris@0: kind = :plain Chris@0: elsif scan(/(@@)((?>[^@\n]*))(@@)/) Chris@0: tokens << [:begin_line, line_kind = :change] Chris@0: tokens << [self[1], :change] Chris@0: tokens << [self[2], :plain] Chris@0: tokens << [self[3], :change] Chris@0: next unless match = scan(/.+/) Chris@0: kind = :plain Chris@0: elsif match = scan(/\+/) Chris@0: tokens << [:begin_line, line_kind = :insert] Chris@0: tokens << [match, :insert] Chris@0: next unless match = scan(/.+/) Chris@0: kind = :plain Chris@0: elsif match = scan(/-/) Chris@0: tokens << [:begin_line, line_kind = :delete] Chris@0: tokens << [match, :delete] Chris@0: next unless match = scan(/.+/) Chris@0: kind = :plain Chris@0: elsif scan(/ .*/) Chris@0: kind = :comment Chris@0: elsif scan(/.+/) Chris@0: tokens << [:begin_line, line_kind = :head] Chris@0: kind = :plain Chris@0: else Chris@0: raise_inspect 'else case rached' Chris@0: end Chris@0: Chris@0: when :added Chris@0: if match = scan(/ \+/) Chris@0: tokens << [:begin_line, line_kind = :insert] Chris@0: tokens << [match, :insert] Chris@0: next unless match = scan(/.+/) Chris@0: kind = :plain Chris@0: else Chris@0: state = :initial Chris@0: next Chris@0: end Chris@0: end Chris@0: Chris@0: match ||= matched Chris@0: if $CODERAY_DEBUG and not kind Chris@0: raise_inspect 'Error token %p in line %d' % Chris@0: [[match, kind], line], tokens Chris@0: end Chris@0: raise_inspect 'Empty token', tokens unless match Chris@0: Chris@0: tokens << [match, kind] Chris@0: end Chris@0: Chris@0: tokens << [:end_line, line_kind] if line_kind Chris@0: tokens Chris@0: end Chris@0: Chris@0: end Chris@0: Chris@0: end Chris@0: end