Class: ANSI::Diff
- Inherits:
-
Object
- Object
- ANSI::Diff
- Defined in:
- lib/ansi/diff.rb
Overview
Diff can produced a colorized difference of two string or objects.
Constant Summary collapse
- COLORS =
Rotation of colors for diff output.
[:red, :yellow, :magenta]
Instance Method Summary collapse
- #common(x, y) ⇒ Object private
- #compare(x, y) ⇒ Object private
-
#convert(object) ⇒ Object
private
Ensure the object of comparison is a string.
- #diff1 ⇒ Object
- #diff2 ⇒ Object
-
#diff_string(string1, string2) ⇒ Object
private
Take two plain strings and produce colorized versions of each highlighting their differences.
-
#initialize(object1, object2, options = {}) ⇒ Diff
constructor
A new instance of Diff.
- #lcs(s1, s2) ⇒ Object private
- #lcs_size(s1, s2) ⇒ Object private
- #to_s ⇒ Object
Constructor Details
#initialize(object1, object2, options = {}) ⇒ Diff
Returns a new instance of Diff.
9 10 11 12 13 14 |
# File 'lib/ansi/diff.rb', line 9 def initialize(object1, object2, ={}) @object1 = convert(object1) @object2 = convert(object2) @diff1, @diff2 = diff_string(@object1, @object2) end |
Instance Method Details
#common(x, y) ⇒ Object (private)
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 |
# File 'lib/ansi/diff.rb', line 74 def common(x,y) c = lcs(x, y) i = x.index(c) j = y.index(c) ix = i + c.size jx = j + c.size if i == 0 l = y[0...j] elsif j == 0 l = x[0...i] else l = common(x[0...i], y[0...j]) end if ix == x.size - 1 r = y[jx..-1] elsif jx = y.size - 1 r = x[ix..-1] else r = common(x[ix..-1], y[jx..-1]) end [l, c, r].flatten.reject{ |s| s.empty? } end |
#compare(x, y) ⇒ Object (private)
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/ansi/diff.rb', line 56 def compare(x, y) c = common(x, y) a = x.dup b = y.dup oi = 0 oj = 0 c.each_with_index do |m, q| i = a.index(m, oi) j = b.index(m, oj) a[i,m.size] = ANSI.ansi(m, COLORS[q%3]) if i b[j,m.size] = ANSI.ansi(m, COLORS[q%3]) if j oi = i + m.size if i oj = j + m.size if j end return a, b end |
#convert(object) ⇒ Object (private)
Ensure the object of comparison is a string. If object
is not an instance of String then it wll be converted to one by calling either #to_str, if the object responds to it, or #inspect.
42 43 44 45 46 47 48 49 50 |
# File 'lib/ansi/diff.rb', line 42 def convert(object) if String === object object elsif object.respond_to?(:to_str) object.to_str else object.inspect end end |
#diff1 ⇒ Object
17 18 19 |
# File 'lib/ansi/diff.rb', line 17 def diff1 @diff1 end |
#diff2 ⇒ Object
22 23 24 |
# File 'lib/ansi/diff.rb', line 22 def diff2 @diff2 end |
#diff_string(string1, string2) ⇒ Object (private)
Take two plain strings and produce colorized versions of each highlighting their differences.
35 36 37 |
# File 'lib/ansi/diff.rb', line 35 def diff_string(string1, string2) compare(string1, string2) end |
#lcs(s1, s2) ⇒ Object (private)
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/ansi/diff.rb', line 120 def lcs(s1, s2) res="" num=Array.new(s1.size){Array.new(s2.size)} len,ans=0 lastsub=0 s1.scan(/./).each_with_index do |l1,i | s2.scan(/./).each_with_index do |l2,j | unless l1==l2 num[i][j]=0 else (i==0 || j==0)? num[i][j]=1 : num[i][j]=1 + num[i-1][j-1] if num[i][j] > len len = ans = num[i][j] thissub = i thissub -= num[i-1][j-1] unless num[i-1][j-1].nil? if lastsub==thissub res+=s1[i,1] else lastsub=thissub res=s1[lastsub, (i+1)-lastsub] end end end end end res end |
#lcs_size(s1, s2) ⇒ Object (private)
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/ansi/diff.rb', line 103 def lcs_size(s1, s2) num=Array.new(s1.size){Array.new(s2.size)} len,ans=0 s1.scan(/./).each_with_index do |l1,i | s2.scan(/./).each_with_index do |l2,j | unless l1==l2 num[i][j]=0 else (i==0 || j==0)? num[i][j]=1 : num[i][j]=1 + num[i-1][j-1] len = ans = num[i][j] if num[i][j] > len end end end ans end |
#to_s ⇒ Object
27 28 29 |
# File 'lib/ansi/diff.rb', line 27 def to_s "#{@diff1}\n#{@diff2}" end |