class Test::Unit::Diff::ReadableDiffer - test-unit: Ruby Standard Library Documentation

# class Test::Unit::Diff::ReadableDiffer

### Public Instance Methods

diff(options={}) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 413
    def diff(options={})
      @result = []
      operations.each do |tag, from_start, from_end, to_start, to_end|
        case tag
        when :replace
          diff_lines(from_start, from_end, to_start, to_end)
        when :delete
          tag_deleted(@from[from_start...from_end])
        when :insert
          tag_inserted(@to[to_start...to_end])
        when :equal
          tag_equal(@from[from_start...from_end])
        else
          raise "unknown tag: #{tag}"
        end
      end
      @result
    end

### Private Instance Methods

_diff_lines(from_start, from_end, to_start, to_end) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 528
    def _diff_lines(from_start, from_end, to_start, to_end)
      if from_start < from_end
        if to_start < to_end
          diff_lines(from_start, from_end, to_start, to_end)
        else
          tag_deleted(@from[from_start...from_end])
        end
      else
        tag_inserted(@to[to_start...to_end])
      end
    end

compute_width(line, start, _end) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 550
    def compute_width(line, start, _end)
      if line.respond_to?(:encoding) and
          Encoding.compatible?(Encoding::UTF_8, line.encoding)
        utf8_line = line[start..._end].encode(Encoding::UTF_8)
        width = 0
        utf8_line.each_codepoint do |unicode_codepoint|
          if UTF8Line.wide_character?(unicode_codepoint)
            width += 2
          else
            width += 1
          end
        end
        width
      elsif line.is_a?(UTF8Line)
        line.compute_width(start, _end)
      else
        _end - start
      end
    end

cut_off_ratio() click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 446
    def cut_off_ratio
      0.75
    end

default_ratio() click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 442
    def default_ratio
      0.74
    end

diff_line(from_line, to_line) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 570
    def diff_line(from_line, to_line)
      from_tags = ""
      to_tags = ""
      from_line, to_line, _operations = line_operations(from_line, to_line)
      _operations.each do |tag, from_start, from_end, to_start, to_end|
        from_width = compute_width(from_line, from_start, from_end)
        to_width = compute_width(to_line, to_start, to_end)
        case tag
        when :replace
          from_tags += "^" * from_width
          to_tags += "^" * to_width
        when :delete
          from_tags += "-" * from_width
        when :insert
          to_tags += "+" * to_width
        when :equal
          from_tags += " " * from_width
          to_tags += " " * to_width
        else
          raise "unknown tag: #{tag}"
        end
      end
      format_diff_point(from_line, to_line, from_tags, to_tags)
    end

diff_lines(from_start, from_end, to_start, to_end) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 500
    def diff_lines(from_start, from_end, to_start, to_end)
      info = find_diff_line_info(from_start, from_end, to_start, to_end)
      best_ratio, from_equal_index, to_equal_index, *info = info
      from_best_index, to_best_index = info
      from_best_index ||= from_start
      to_best_index ||= to_start

      if best_ratio < cut_off_ratio
        if from_equal_index.nil?
          if to_end - to_start < from_end - from_start
            tag_inserted(@to[to_start...to_end])
            tag_deleted(@from[from_start...from_end])
          else
            tag_deleted(@from[from_start...from_end])
            tag_inserted(@to[to_start...to_end])
          end
          return
        end
        from_best_index = from_equal_index
        to_best_index = to_equal_index
        best_ratio = 1.0
      end

      _diff_lines(from_start, from_best_index, to_start, to_best_index)
      diff_line(@from[from_best_index], @to[to_best_index])
      _diff_lines(from_best_index + 1, from_end, to_best_index + 1, to_end)
    end

find_diff_line_info(from_start, from_end, to_start, to_end) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 472
    def find_diff_line_info(from_start, from_end, to_start, to_end)
      best_ratio = default_ratio
      from_equal_index = to_equal_index = nil
      from_best_index = to_best_index = nil

      to_start.upto(to_end - 1) do |to_index|
        from_start.upto(from_end - 1) do |from_index|
          if @from[from_index] == @to[to_index]
            from_equal_index ||= from_index
            to_equal_index ||= to_index
            next
          end

          matcher = SequenceMatcher.new(@from[from_index], @to[to_index],
                                        &method(:space_character?))
          if matcher.ratio > best_ratio
            best_ratio = matcher.ratio
            from_best_index = from_index
            to_best_index = to_index
          end
        end
      end

      [best_ratio,
       from_equal_index, to_equal_index,
       from_best_index,  to_best_index]
    end

format_diff_point(from_line, to_line, from_tags, to_tags) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 595
    def format_diff_point(from_line, to_line, from_tags, to_tags)
      common = [n_leading_characters(from_line, ?\t),
                n_leading_characters(to_line, ?\t)].min
      common = [common,
                n_leading_characters(from_tags[0, common], " "[0])].min
      from_tags = from_tags[common..-1].rstrip
      to_tags = to_tags[common..-1].rstrip

      tag_deleted([from_line])
      unless from_tags.empty?
        tag_difference(["#{"\t" * common}#{from_tags}"])
      end
      tag_inserted([to_line])
      unless to_tags.empty?
        tag_difference(["#{"\t" * common}#{to_tags}"])
      end
    end

line_operations(from_line, to_line) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 540
    def line_operations(from_line, to_line)
      if !from_line.respond_to?(:force_encoding) and $KCODE == "UTF8"
        from_line = UTF8Line.new(from_line)
        to_line = UTF8Line.new(to_line)
      end
      matcher = SequenceMatcher.new(from_line, to_line,
                                    &method(:space_character?))
      [from_line, to_line, matcher.operations]
    end

n_leading_characters(string, character) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 613
    def n_leading_characters(string, character)
      n = 0
      while string[n] == character
        n += 1
      end
      n
    end

operations() click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 433
    def operations
      @operations ||= nil
      if @operations.nil?
        matcher = SequenceMatcher.new(@from, @to)
        @operations = matcher.operations
      end
      @operations
    end

space_character?(character) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 621
    def space_character?(character)
      [" "[0], "\t"[0]].include?(character)
    end

tag(mark, contents) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 450
    def tag(mark, contents)
      contents.each do |content|
        @result << (mark + content)
      end
    end

tag_deleted(contents) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 456
    def tag_deleted(contents)
      tag("- ", contents)
    end

tag_difference(contents) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 468
    def tag_difference(contents)
      tag("? ", contents)
    end

tag_equal(contents) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 464
    def tag_equal(contents)
      tag("  ", contents)
    end

tag_inserted(contents) click to toggle source

    # File test-unit-3.6.7/lib/test/unit/diff.rb, line 460
    def tag_inserted(contents)
      tag("+ ", contents)
    end