/
combined.rb
59 lines (43 loc) · 1.16 KB
/
combined.rb
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
module Diff
class Combined
include Enumerable
Row = Struct.new(:edits) do
def to_s
symbols = edits.map { |edit| SYMBOLS.fetch(edit&.type, " ") }
del = edits.find { |edit| edit&.type == :del }
line = del ? del.a_line : edits.first.b_line
symbols.join("") + line.text
end
end
def initialize(diffs)
@diffs = diffs
end
def each
@offsets = @diffs.map { 0 }
loop do
@diffs.each_with_index do |diff, i|
consume_deletions(diff, i) { |row| yield row }
end
return if complete?
edits = offset_diffs.map { |offset, diff| diff[offset] }
@offsets.map! { |offset| offset + 1 }
yield Row.new(edits)
end
end
private
def complete?
offset_diffs.all? { |offset, diff| offset == diff.size }
end
def offset_diffs
@offsets.zip(@diffs)
end
def consume_deletions(diff, i)
while @offsets[i] < diff.size and diff[@offsets[i]].type == :del
edits = Array.new(@diffs.size)
edits[i] = diff[@offsets[i]]
@offsets[i] += 1
yield Row.new(edits)
end
end
end
end