Class: ANSI::Diff
- Inherits:
-
Object
- Object
- ANSI::Diff
- Defined in:
- lib/ansi/diff.rb
Overview
Diff produces colorized differences of two string or objects.
Constant Summary collapse
- COLORS =
Rotation of colors for diff output.
[:red, :yellow, :magenta]
Class Method Summary collapse
-
.diff(object1, object2, options = {}) ⇒ Object
Highlights the differnce between two strings.
Instance Method Summary collapse
-
#common(x, y) ⇒ Object
private
Oh, I should have documented this will I knew what the hell it was doing ;).
-
#compare(x, y) ⇒ Array<String>
private
Take two plain strings and produce colorized versions of each highlighting their differences.
-
#convert(object) ⇒ Object
private
Ensure the object of comparison is a string.
-
#diff1 ⇒ Object
Returns the first object’s difference string.
-
#diff2 ⇒ Object
Returns the second object’s difference string.
-
#diff_string(string1, string2) ⇒ Array<String>
private
Take two plain strings and produce colorized versions of each highlighting their differences.
-
#initialize(object1, object2, options = {}) ⇒ Diff
constructor
Setup new Diff object.
-
#join(separator = $/) ⇒ String
Returns both first and second difference strings separated by a the given ‘separator`.
-
#lcs(s1, s2) ⇒ Object
private
Least common string.
-
#lcs_size(s1, s2) ⇒ Object
private
Hmm…
-
#to_a ⇒ Array
Returns the first and second difference strings in an array.
-
#to_s ⇒ String
Returns both first and second difference strings separated by a new line character.
Constructor Details
#initialize(object1, object2, options = {}) ⇒ Diff
Setup new Diff object. If the objects given are not Strings and do not have ‘#to_str` defined to coerce them to such, then their `#inspect` methods are used to convert them to strings for comparison.
33 34 35 36 37 38 |
# File 'lib/ansi/diff.rb', line 33 def initialize(object1, object2, ={}) @object1 = convert(object1) @object2 = convert(object2) @diff1, @diff2 = diff_string(@object1, @object2) end |
Class Method Details
Instance Method Details
#common(x, y) ⇒ Object (private)
Oh, I should have documented this will I knew what the hell it was doing ;)
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/ansi/diff.rb', line 139 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) ⇒ Array<String> (private)
Take two plain strings and produce colorized versions of each highlighting their differences.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/ansi/diff.rb', line 120 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.
97 98 99 100 101 102 103 104 105 |
# File 'lib/ansi/diff.rb', line 97 def convert(object) if String === object object elsif object.respond_to?(:to_str) object.to_str else object.inspect end end |
#diff1 ⇒ Object
Returns the first object’s difference string.
41 42 43 |
# File 'lib/ansi/diff.rb', line 41 def diff1 @diff1 end |
#diff2 ⇒ Object
Returns the second object’s difference string.
46 47 48 |
# File 'lib/ansi/diff.rb', line 46 def diff2 @diff2 end |
#diff_string(string1, string2) ⇒ Array<String> (private)
Take two plain strings and produce colorized versions of each highlighting their differences.
90 91 92 |
# File 'lib/ansi/diff.rb', line 90 def diff_string(string1, string2) compare(string1, string2) end |
#join(separator = $/) ⇒ String
Returns both first and second difference strings separated by a the given ‘separator`. The default is `$/`, the record separator.
67 68 69 |
# File 'lib/ansi/diff.rb', line 67 def join(separator=$/) "#{@diff1}#{separator}#{@diff2}" end |
#lcs(s1, s2) ⇒ Object (private)
Least common string.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/ansi/diff.rb', line 168 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)
Hmm… is this even useful?
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/ansi/diff.rb', line 197 def lcs_size(s1, s2) num=Array.new(s1.size){Array.new(s2.size)} len,ans=0,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_a ⇒ Array
Returns the first and second difference strings in an array.
74 75 76 |
# File 'lib/ansi/diff.rb', line 74 def to_a [diff1, diff2] end |
#to_s ⇒ String
Should we use ‘$/` record separator instead?
Returns both first and second difference strings separated by a new line character.
56 57 58 |
# File 'lib/ansi/diff.rb', line 56 def to_s "#{@diff1}\n#{@diff2}" end |