summaryrefslogtreecommitdiff
path: root/lib/coderay/scanners/diff.rb
blob: d52458c383da3e011faf7f5be3c375cb255a5e58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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