lib/tdiff.rb in tdiff-0.1.0 vs lib/tdiff.rb in tdiff-0.2.0

- old
+ new

@@ -1,133 +1,2 @@ -# -# {TDiff} adds the ability to calculate the differences between two tree-like -# objects. Simply include {TDiff} into the class which represents the tree -# nodes and define the {#tdiff_each_child} and {#tdiff_equal} methods. -# -module TDiff - # - # Default method which will enumerate over every child of a parent node. - # - # @param [Object] node - # The parent node. - # - # @yield [child] - # The given block will be passed each child of the parent node. - # - def tdiff_each_child(node,&block) - node.each(&block) if node.kind_of?(Enumerable) - end - - # - # Default method which compares two nodes. - # - # @param [Object] original_node - # A node from the original tree. - # - # @param [Object] new_node - # A node from the new tree. - # - # @return [Boolean] - # Specifies whether the two nodes are equal. - # - def tdiff_equal(original_node,new_node) - original_node == new_node - end - - # - # Finds the differences between `self` and another tree. - # - # @param [#tdiff_each_child] tree - # The other tree. - # - # @yield [change, node] - # The given block will be passed the added or removed nodes. - # - # @yieldparam [' ', '+', '-'] change - # The state-change of the node. - # - # @yieldparam [Object] node - # A node from one of the two trees. - # - # @return [Enumerator] - # If no block is given, an Enumerator object will be returned. - # - def tdiff(tree,&block) - return enum_for(:tdiff,tree) unless block - - # check if the nodes differ - unless tdiff_equal(self,tree) - yield '-', self - yield '+', tree - return self - end - - c = Hash.new { |hash,key| hash[key] = Hash.new(0) } - x = enum_for(:tdiff_each_child,self) - y = enum_for(:tdiff_each_child,tree) - - x.each_with_index do |xi,i| - y.each_with_index do |yi,j| - c[i][j] = if tdiff_equal(xi,yi) - c[i-1][j-1] + 1 - else - if c[i][j-1] > c[i-1][j] - c[i][j-1] - else - c[i-1][j] - end - end - end - end - - unchanged = [] - changes = [] - - x_backtrack = x.each_with_index.reverse_each - y_backtrack = y.each_with_index.reverse_each - - next_child = lambda { |children| - begin - children.next - rescue StopIteration - # end of iteration, return a -1 index - [nil, -1] - end - } - - xi, i = next_child[x_backtrack] - yi, j = next_child[y_backtrack] - - until (i == -1 && j == -1) - if (i != -1 && j != -1 && tdiff_equal(xi,yi)) - changes.unshift [' ', xi] - unchanged.unshift [xi, yi] - - xi, i = next_child[x_backtrack] - yi, j = next_child[y_backtrack] - else - if (j >= 0 && (i == -1 || c[i][j-1] >= c[i-1][j])) - changes.unshift ['+', yi] - - yi, j = next_child[y_backtrack] - elsif (i >= 0 && (j == -1 || c[i][j-1] < c[i-1][j])) - changes.unshift ['-', xi] - - xi, i = next_child[x_backtrack] - end - end - end - - # explicitly discard the c matrix - c = nil - - # sequentially iterate over the changed nodes - changes.each(&block) - changes = nil - - # recurse down through unchanged nodes - unchanged.each { |x,y| x.tdiff(y,&block) } - unchanged = nil - - return self - end -end +require 'tdiff/tdiff' +require 'tdiff/unordered'