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