Class: Diff

Inherits:
Object
  • Object
show all
Defined in:
lib/diff.rb

Constant Summary

VERSION =
0.3

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(diffs_or_a, b = nil, isstring = nil) ⇒ Diff



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/diff.rb', line 109

def initialize(diffs_or_a, b = nil, isstring = nil)
  if b.nil?
    @diffs = diffs_or_a
    @isstring = isstring
  else
    @diffs = []
    @curdiffs = []
    makediff(diffs_or_a, b)
    @difftype = diffs_or_a.class
  end
end

Instance Attribute Details

#diffsObject (readonly)

Returns the value of attribute diffs



107
108
109
# File 'lib/diff.rb', line 107

def diffs
  @diffs
end

#difftypeObject (readonly)

Returns the value of attribute difftype



107
108
109
# File 'lib/diff.rb', line 107

def difftype
  @difftype
end

Class Method Details

.lcs(a, b) ⇒ Object



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
# File 'lib/diff.rb', line 5

def Diff.lcs(a, b)
  astart = 0
  bstart = 0
  afinish = a.length-1
  bfinish = b.length-1
  mvector = []
  
  # First we prune off any common elements at the beginning
  while (astart <= afinish && bstart <= afinish && a[astart] == b[bstart])
    mvector[astart] = bstart
    astart += 1
    bstart += 1
  end
  
  # now the end
  while (astart <= afinish && bstart <= bfinish && a[afinish] == b[bfinish])
    mvector[afinish] = bfinish
    afinish -= 1
    bfinish -= 1
  end

  bmatches = b.reverse_hash(bstart..bfinish)
  thresh = []
  links = []
  
  (astart..afinish).each { |aindex|
    aelem = a[aindex]
    next unless bmatches.has_key? aelem
    k = nil
    bmatches[aelem].reverse.each { |bindex|
	if k && (thresh[k] > bindex) && (thresh[k-1] < bindex)
 thresh[k] = bindex
	else
 k = thresh.replacenextlarger(bindex, k)
	end
	links[k] = [ (k==0) ? nil : links[k-1], aindex, bindex ] if k
    }
  }

  if !thresh.empty?
    link = links[thresh.length-1]
    while link
	mvector[link[1]] = link[2]
	link = link[0]
    end
  end

  return mvector
end

Instance Method Details

#compactObject



134
135
136
# File 'lib/diff.rb', line 134

def compact
  return Diff.new(compactdiffs)
end

#compact!Object



138
139
140
# File 'lib/diff.rb', line 138

def compact!
  @diffs = compactdiffs
end

#compactdiffsObject



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/diff.rb', line 84

def compactdiffs
  diffs = []
  @diffs.each { |df|
    i = 0
    curdiff = []
    while i < df.length
	whot = df[i][0]
	s = @isstring ? df[i][2].chr : [df[i][2]]
	p = df[i][1]
	last = df[i][1]
	i += 1
	while df[i] && df[i][0] == whot && df[i][1] == last+1
 s << df[i][2]
 last  = df[i][1]
 i += 1
	end
	curdiff.push [whot, p, s]
    end
    diffs.push curdiff
  }
  return diffs
end

#discarda(i, elem) ⇒ Object



126
127
128
# File 'lib/diff.rb', line 126

def discarda(i, elem)
  @curdiffs.push ['-', i, elem]
end

#discardb(i, elem) ⇒ Object



130
131
132
# File 'lib/diff.rb', line 130

def discardb(i, elem)
  @curdiffs.push ['+', i, elem]
end

#inspectObject



142
143
144
# File 'lib/diff.rb', line 142

def inspect
  @diffs.inspect
end

#makediff(a, b) ⇒ Object



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
# File 'lib/diff.rb', line 55

def makediff(a, b)
  mvector = Diff.lcs(a, b)
  ai = bi = 0
  while ai < mvector.length
    bline = mvector[ai]
    if bline
	while bi < bline
 discardb(bi, b[bi])
 bi += 1
	end
	match(ai, bi)
	bi += 1
    else
	discarda(ai, a[ai])
    end
    ai += 1
  end
  while ai < a.length
    discarda(ai, a[ai])
    ai += 1
  end
  while bi < b.length
    discardb(bi, b[bi])
    bi += 1
  end
  match(ai, bi)
  1
end

#match(ai, bi) ⇒ Object



121
122
123
124
# File 'lib/diff.rb', line 121

def match(ai, bi)
  @diffs.push @curdiffs unless @curdiffs.empty?
  @curdiffs = []
end