class DocDiff::Diff::EditScript
Attributes
additions[R]
count_a[R]
count_b[R]
deletions[R]
Public Class Methods
new()
click to toggle source
# File lib/docdiff/diff/editscript.rb, line 7 def initialize @chunk_common = nil @chunk_add = [] @chunk_del = [] @list = [] @list << @chunk_del @list << @chunk_add @cs = Subsequence.new @count_a = 0 @count_b = 0 @additions = 0 @deletions = 0 end
parse_rcsdiff(input)
click to toggle source
# File lib/docdiff/diff/rcsdiff.rb, line 12 def EditScript.parse_rcsdiff(input) ses = EditScript.new l = 1 scan_rcsdiff(input) {|mark, beg, len, lines| if mark == :del ses.common beg - l if l < beg ses.del len l = beg + len else ses.add lines end } return ses end
scan_rcsdiff(input) { |:del, beg, len, nil| ... }
click to toggle source
# File lib/docdiff/diff/rcsdiff.rb, line 27 def EditScript.scan_rcsdiff(input) state = :command beg = len = nil adds = nil input.each_line("\n") {|line| case state when :command case line when /\Aa(\d+)\s+(\d+)/ beg = $1.to_i len = $2.to_i adds = [] state = :add when /\Ad(\d+)\s+(\d+)/ beg = $1.to_i len = $2.to_i yield :del, beg, len, nil state = :command else raise InvalidRCSDiffFormat.new(line) end when :add adds << line if adds.length == len yield :add, beg, len, adds adds = nil state = :command end else raise StandardError.new("unknown state") end } end
Public Instance Methods
add(seq_or_len)
click to toggle source
# File lib/docdiff/diff/editscript.rb, line 53 def add(seq_or_len) unless @chunk_add @chunk_add = [] @chunk_del = [] @chunk_common = nil @list << @chunk_del @list << @chunk_add end if Array === seq_or_len len = seq_or_len.length mark = :add_elt else len = seq_or_len mark = :add_num end if !@chunk_add.empty? && @chunk_add.last[0] == mark @chunk_add.last[2] += seq_or_len else @chunk_add << [mark, nil, seq_or_len] end @count_b += len @additions += len end
apply(src)
click to toggle source
# File lib/docdiff/diff/editscript.rb, line 118 def apply(src) l = 0 dst = [] each {|mark, del, add| case mark when :add_elt dst.concat add when :add_num raise ArgumentError.new("additionnal lines are not known.") when :common_elt_elt dst.concat add l += del.length when :common_elt_num dst.concat src[l, del] l += del when :common_num_elt dst.concat add l += add when :common_num_num dst.concat src[l, del] l += del when :del_elt l += del.length when :del_num l += del end } dst.concat src[l..-1] return dst end
common(seq_or_len_a, seq_or_len_b=seq_or_len_a)
click to toggle source
# File lib/docdiff/diff/editscript.rb, line 77 def common(seq_or_len_a, seq_or_len_b=seq_or_len_a) unless @chunk_common @list.pop @list.pop @list << @chunk_del unless @chunk_del.empty? @list << @chunk_add unless @chunk_add.empty? @chunk_add = nil @chunk_del = nil @chunk_common = [] @list << @chunk_common end len_a = Array === seq_or_len_a ? seq_or_len_a.length : seq_or_len_a len_b = Array === seq_or_len_b ? seq_or_len_b.length : seq_or_len_b raise ArgumentError.new("length not equal: #{len_a} != #{len_b}") if len_a != len_b len = len_a mark = ((Array === seq_or_len_a) ? (Array === seq_or_len_b ? :common_elt_elt : :common_elt_num) : (Array === seq_or_len_b ? :common_num_elt : :common_num_num)) if !@chunk_common.empty? && @chunk_common.last[0] == mark @chunk_common.last[1] += seq_or_len_a @chunk_common.last[2] += seq_or_len_b else @chunk_common << [mark, seq_or_len_a, seq_or_len_b] end @cs.add @count_a, @count_b, len @count_a += len @count_b += len end
commonsubsequence()
click to toggle source
# File lib/docdiff/diff/editscript.rb, line 25 def commonsubsequence return @cs end
del(seq_or_len)
click to toggle source
# File lib/docdiff/diff/editscript.rb, line 29 def del(seq_or_len) unless @chunk_del @chunk_add = [] @chunk_del = [] @chunk_common = nil @list << @chunk_del @list << @chunk_add end if Array === seq_or_len len = seq_or_len.length mark = :del_elt else len = seq_or_len mark = :del_num end if !@chunk_del.empty? && @chunk_del.last[0] == mark @chunk_del.last[1] += seq_or_len else @chunk_del << [mark, seq_or_len, nil] end @count_a += len @deletions += len end
each() { |mark_del_add| ... }
click to toggle source
# File lib/docdiff/diff/editscript.rb, line 110 def each @list.each {|chunk| chunk.each {|mark_del_add| yield mark_del_add } } end
rcsdiff(out='')
click to toggle source
# File lib/docdiff/diff/rcsdiff.rb, line 61 def rcsdiff(out='') state = :lines l = 1 each {|mark, del, add| case mark when :add_elt out << "a#{l - 1} #{add.length}\n" add.each {|line| case state when :lines case line when /\A.*\n\z/ when /\A.*\z/ state = :after_last_line else raise ArgumentError.new("additional element is not line") end when :after_last_line raise ArgumentError.new("additional elements after last incomplete line") end out << line } when :add_num raise ArgumentError.new("additionnal lines are not known.") when :common_elt_elt l += del.length when :common_elt_num l += add when :common_num_elt l += del when :common_num_num l += del when :del_elt del = del.length out << "d#{l} #{del}\n" l += del when :del_num out << "d#{l} #{del}\n" l += del end } return out end
unidiff(out='', context_lines=3)
click to toggle source
# File lib/docdiff/diff/unidiff.rb, line 22 def unidiff(out='', context_lines=3) state = :common l1 = l2 = 1 hunk = [] hunk_l1 = hunk_l2 = 1 hunk_tail = 0 each {|mark, del, add| case mark when :add_elt unless hunk hunk = [] hunk_l1 = l1 hunk_l2 = l2 end add.each {|line| hunk << '+' + line} hunk[-1] += "\n\\ No newline at end of file\n" if /\n\z/ !~ hunk[-1] l2 += add.length hunk_tail = 0 when :add_num raise ArgumentError.new("additionnal lines are not known.") when :common_elt_elt if hunk if hunk_tail + add.length <= context_lines * 2 add.each {|line| hunk << ' ' + line} hunk[-1] += "\n\\ No newline at end of file\n" if /\n\z/ !~ hunk[-1] l1 += add.length l2 += add.length hunk_tail += add.length else i = 0 if hunk_tail != hunk.length while hunk_tail < context_lines hunk << ' ' + add[i] l1 += 1 l2 += 1 hunk_tail += 1 i += 1 end hunk[-1] += "\n\\ No newline at end of file\n" if /\n\z/ !~ hunk[-1] out << unidiff_hunk_header(hunk_l1, l1 - hunk_l1, hunk_l2, l2 - hunk_l1) h = hunk.length - (hunk_tail - context_lines) (0...h).each {|j| out << hunk[j]} hunk[0, h] = [] end l1 += add.length - i l2 += add.length - i hunk_l1 = l1 - context_lines hunk_l2 = l2 - context_lines hunk = add[-context_lines..-1].collect {|line| ' ' + line} hunk[-1] += "\n\\ No newline at end of file\n" if /\n\z/ !~ hunk[-1] hunk_tail = context_lines end else hunk_l1 = l1 hunk_l2 = l2 l1 += add.length l2 += add.length if context_lines <= add.length hunk = add[-context_lines..-1].collect {|line| ' ' + line} else hunk = add.collect {|line| ' ' + line} end hunk[-1] += "\n\\ No newline at end of file\n" if /\n\z/ !~ hunk[-1] hunk_tail = hunk.length end when :common_elt_num raise ArgumentError.new("deleted lines are not known.") when :common_num_elt raise ArgumentError.new("additional lines are not known.") when :common_num_num raise ArgumentError.new("deleted and additional lines are not known.") when :del_elt if hunk_tail == hunk.length && context_lines < hunk_tail i = hunk_tail - context_lines hunk[0, i] = [] hunk_l1 += i hunk_l2 += i end del.each {|line| hunk << '-' + line} hunk[-1] += "\n\\ No newline at end of file\n" if /\n\z/ !~ hunk[-1] l1 += del.length hunk_tail = 0 when :del_num raise ArgumentError.new("deleted lines are not known.") end } if hunk_tail != hunk.length if context_lines < hunk_tail i = hunk_tail - context_lines hunk[-i..-1] = [] l1 -= i l2 -= i end out << unidiff_hunk_header(hunk_l1, l1 - hunk_l1, hunk_l2, l2 - hunk_l1) hunk.each {|line| out << line} end return out end
unidiff_hunk_header(l1, ll1, l2, ll2)
click to toggle source
# File lib/docdiff/diff/unidiff.rb, line 12 def unidiff_hunk_header(l1, ll1, l2, ll2) l1 = 0 if ll1 == 0 l2 = 0 if ll2 == 0 result = "@@ -#{l1}" result << ",#{ll1}" if ll1 != 1 result << " +#{l2}" result << ",#{ll2}" if ll2 != 1 result << " @@\n" end