Class: Kronk::Diff
- Inherits:
-
Object
- Object
- Kronk::Diff
- Defined in:
- lib/kronk/diff.rb,
lib/kronk/diff/output.rb,
lib/kronk/diff/ascii_format.rb,
lib/kronk/diff/color_format.rb
Overview
Creates simple diffs as formatted strings or arrays, from two strings or data objects.
Defined Under Namespace
Classes: AsciiFormat, ColorFormat, Output
Instance Attribute Summary collapse
-
#char ⇒ Object
Returns the value of attribute char.
-
#meta ⇒ Object
Returns the value of attribute meta.
-
#output ⇒ Object
Returns the value of attribute output.
-
#str1 ⇒ Object
Returns the value of attribute str1.
-
#str2 ⇒ Object
Returns the value of attribute str2.
Class Method Summary collapse
-
.insert_line_nums(str, formatter = nil) ⇒ Object
Adds line numbers to each lines of a String.
-
.new_from_data(data1, data2, opts = {}) ⇒ Object
Creates a new diff from two data objects.
Instance Method Summary collapse
-
#any? ⇒ Boolean
Returns true if any diff is found.
-
#common_sequences(arr1, arr2, &block) ⇒ Object
Returns all common sequences between to arrays ordered by sequence length (including overlapping ones) according to the following format: [[[len1, ix, iy], [len1, ix, iy]],[[len2, ix, iy]]] # e.g.
-
#count ⇒ Object
Returns the number of diffs found.
-
#create_diff ⇒ Object
Returns a diff array with the following format: str1 = “match1nmatch2nstr1 val” str1 = “match1nin str2nmore str2nmatch2nstr2 val”.
-
#diff_array ⇒ Object
(also: #to_a)
Returns the cached diff array when available, otherwise creates it.
-
#find_common(arr1, arr2) ⇒ Object
Finds non-overlapping common sequences between two arrays and returns them in the order they occur as an array of arrays: find_common arr1, arr2 #=> [[size, arr1_index, arr2_index], [size, arr1_index, arr2_index],…].
-
#formatted ⇒ Object
(also: #to_s)
Returns a formatted output as a String.
-
#initialize(str1, str2, opts = {}) ⇒ Diff
constructor
Create a new Diff instance from two strings.
Constructor Details
#initialize(str1, str2, opts = {}) ⇒ Diff
Create a new Diff instance from two strings. Options supported are those of Kronk::Diff::Output, plus:
- :char
-
String/Regex - The char to split on for comparisons.
42 43 44 45 46 47 48 49 |
# File 'lib/kronk/diff.rb', line 42 def initialize str1, str2, opts={} @str1 = str1 @str2 = str2 @diff_ary = nil @char = opts[:char] || /\r?\n/ @meta = [] @output = Output.new opts end |
Instance Attribute Details
#char ⇒ Object
Returns the value of attribute char.
35 36 37 |
# File 'lib/kronk/diff.rb', line 35 def char @char end |
#meta ⇒ Object
Returns the value of attribute meta.
35 36 37 |
# File 'lib/kronk/diff.rb', line 35 def @meta end |
#output ⇒ Object
Returns the value of attribute output.
35 36 37 |
# File 'lib/kronk/diff.rb', line 35 def output @output end |
#str1 ⇒ Object
Returns the value of attribute str1.
35 36 37 |
# File 'lib/kronk/diff.rb', line 35 def str1 @str1 end |
#str2 ⇒ Object
Returns the value of attribute str2.
35 36 37 |
# File 'lib/kronk/diff.rb', line 35 def str2 @str2 end |
Class Method Details
.insert_line_nums(str, formatter = nil) ⇒ Object
Adds line numbers to each lines of a String.
21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/kronk/diff.rb', line 21 def self.insert_line_nums str, formatter=nil format = Diff::Output.formatter formatter || Kronk.config[:diff_format] out = "" width = str.lines.count.to_s.length str.split("\n").each_with_index do |line, i| out << "#{format.lines(i+1, width)}#{line}\n" end out end |
.new_from_data(data1, data2, opts = {}) ⇒ Object
Creates a new diff from two data objects.
12 13 14 15 |
# File 'lib/kronk/diff.rb', line 12 def self.new_from_data data1, data2, opts={} new DataString.new(data1, opts), DataString.new(data2, opts), opts end |
Instance Method Details
#any? ⇒ Boolean
Returns true if any diff is found.
210 211 212 |
# File 'lib/kronk/diff.rb', line 210 def any? !!diff_array.find{|i| Array === i } end |
#common_sequences(arr1, arr2, &block) ⇒ Object
Returns all common sequences between to arrays ordered by sequence length (including overlapping ones) according to the following format:
[[[len1, ix, iy], [len1, ix, iy]],[[len2, ix, iy]]]
# e.g.
[nil,[[1,2,3],[1,2,5]],nil,[[3,4,5],[3,6,9]]
Output is indexed by sequence size.
160 161 162 163 164 165 166 167 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/kronk/diff.rb', line 160 def common_sequences arr1, arr2, &block sequences = [] arr2_map = {} arr2.each_with_index do |line, j| (arr2_map[line] ||= []) << j end arr1.each_with_index do |line, i| next unless arr2_map[line] arr2_map[line].each do |j| line1 = line line2 = arr2[j] k = i start_j = j while line1 && line1 == line2 && k < arr1.length k += 1 j += 1 line1 = arr1[k] line2 = arr2[j] end len = j - start_j (sequences[len] ||= []) << [len, i, start_j] end end yield_sequences sequences, &block if block_given? sequences end |
#count ⇒ Object
Returns the number of diffs found.
218 219 220 |
# File 'lib/kronk/diff.rb', line 218 def count diff_array.select{|i| Array === i }.length end |
#create_diff ⇒ Object
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 105 106 107 108 109 110 111 112 |
# File 'lib/kronk/diff.rb', line 63 def create_diff diff_ary = [] return @str1.split @char if @str1 == @str2 arr1 = @str1.split @char arr2 = @str2.split @char common_list = find_common arr1, arr2 return [[arr1, arr2]] if common_list.empty? last_i1 = 0 last_i2 = 0 common_list.each do |c| next unless c left = arr1[last_i1...c[1]] right = arr2[last_i2...c[2]] # add diffs unless left.empty? && right.empty? @meta << [] @meta.last[0] = left[0].[0] if left[0].respond_to?(:meta) @meta.last[1] = right[0].[0] if right[0].respond_to?(:meta) diff_ary << [left, right] end # add common arr1[c[1], c[0]].each_with_index do |str1, i| str2 = arr2[c[2]+i] @meta << [] @meta.last[0] = str1.[0] if str1.respond_to?(:meta) @meta.last[1] = str2.[0] if str2.respond_to?(:meta) end diff_ary.concat arr1[c[1], c[0]] last_i1 = c[1] + c[0] last_i2 = c[2] + c[0] end left = arr1[last_i1..-1] right = arr2[last_i2..-1] diff_ary << [left, right] unless left.empty? && right.empty? diff_ary end |
#diff_array ⇒ Object Also known as: to_a
Returns the cached diff array when available, otherwise creates it.
226 227 228 |
# File 'lib/kronk/diff.rb', line 226 def diff_array @diff_ary ||= create_diff end |
#find_common(arr1, arr2) ⇒ Object
Finds non-overlapping common sequences between two arrays and returns them in the order they occur as an array of arrays:
find_common arr1, arr2
#=> [[size, arr1_index, arr2_index], [size, arr1_index, arr2_index],...]
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 147 148 |
# File 'lib/kronk/diff.rb', line 121 def find_common arr1, arr2 used1 = [] used2 = [] common = [] common_sequences(arr1, arr2) do |seq| next if used1[seq[1]] || used2[seq[2]] next if Array(used1[seq[1], seq[0]]).index(true) || Array(used2[seq[2], seq[0]]).index(true) if seq[1] > (used1.length / 2) next if Array(used1[seq[1]+seq[0]..-1]).nitems != Array(used2[seq[2]+seq[0]..-1]).nitems else next if Array(used1[0..seq[1]]).nitems != Array(used2[0..seq[2]]).nitems end used1.fill(true, seq[1], seq[0]) used2.fill(true, seq[2], seq[0]) common[seq[1]] = seq end common end |
#formatted ⇒ Object Also known as: to_s
Returns a formatted output as a String.
200 201 202 |
# File 'lib/kronk/diff.rb', line 200 def formatted ( @output.render diff_array, @meta if any? ).to_s end |