Object
A Hunk is a group of Blocks which overlap because of the context surrounding each block. (So if we’re not using context, every hunk will contain one block.) Used in the diff program (bin/diff).
Change the “start” and “end” fields to note that context should be added to this hunk
Create a hunk using references to both the old and new data, as well as the piece of data
# File lib/diff/lcs/hunk.rb, line 25
25: def initialize(data_old, data_new, piece, context, file_length_difference)
26: # At first, a hunk will have just one Block in it
27: @blocks = [ Diff::LCS::Block.new(piece) ]
28: @data_old = data_old
29: @data_new = data_new
30:
31: before = after = file_length_difference
32: after += @blocks[0].diff_size
33: @file_length_difference = after # The caller must get this manually
34:
35: # Save the start & end of each array. If the array doesn't exist
36: # (e.g., we're only adding items in this block), then figure out the
37: # line number based on the line number of the other file and the
38: # current difference in file lengths.
39: if @blocks[0].remove.empty?
40: a1 = a2 = nil
41: else
42: a1 = @blocks[0].remove[0].position
43: a2 = @blocks[0].remove[1].position
44: end
45:
46: if @blocks[0].insert.empty?
47: b1 = b2 = nil
48: else
49: b1 = @blocks[0].insert[0].position
50: b2 = @blocks[0].insert[1].position
51: end
52:
53: @start_old = a1 || (b1 - before)
54: @start_new = b1 || (a1 + before)
55: @end_old = a2 || (b2 - after)
56: @end_new = b2 || (a2 + after)
57:
58: self.flag_context = context
59: end
# File lib/diff/lcs/hunk.rb, line 101
101: def diff(format)
102: case format
103: when :old
104: old_diff
105: when :unified
106: unified_diff
107: when :context
108: context_diff
109: when :ed
110: self
111: when :reverse_ed, :ed_finish
112: ed_diff(format)
113: else
114: raise "Unknown diff format #{format}."
115: end
116: end
# File lib/diff/lcs/hunk.rb, line 118
118: def each_old(block)
119: @data_old[@start_old .. @end_old].each { |e| yield e }
120: end
Is there an overlap between hunk arg0 and old hunk arg1? Note: if end of old hunk is one less than beginning of second, they overlap
# File lib/diff/lcs/hunk.rb, line 93
93: def overlaps?(hunk = nil)
94: return nil if hunk.nil?
95:
96: a = (@start_old - hunk.end_old) <= 1
97: b = (@start_new - hunk.end_new) <= 1
98: return (a or b)
99: end
# File lib/diff/lcs/hunk.rb, line 178
178: def context_diff
179: s = "***************\n"
180: s << "*** #{context_range(:old)} ****\n"
181: r = context_range(:new)
182:
183: # Print out file 1 part for each block in context diff format if there
184: # are any blocks that remove items
185: lo, hi = @start_old, @end_old
186: removes = @blocks.select { |e| not e.remove.empty? }
187: if removes
188: outlist = @data_old[lo .. hi].collect { |e| e.gsub(/^/, ' ') }
189: removes.each do |block|
190: block.remove.each do |item|
191: outlist[item.position - lo].gsub!(/^ /) { block.op } # - or !
192: end
193: end
194: s << outlist.join("\n")
195: end
196:
197: s << "\n--- #{r} ----\n"
198: lo, hi = @start_new, @end_new
199: inserts = @blocks.select { |e| not e.insert.empty? }
200: if inserts
201: outlist = @data_new[lo .. hi].collect { |e| e.gsub(/^/, ' ') }
202: inserts.each do |block|
203: block.insert.each do |item|
204: outlist[item.position - lo].gsub!(/^ /) { block.op } # + or !
205: end
206: end
207: s << outlist.join("\n")
208: end
209: s
210: end
Generate a range of item numbers to print. Only print 1 number if the range has only one item in it. Otherwise, it’s ‘start,end’
# File lib/diff/lcs/hunk.rb, line 231
231: def context_range(mode)
232: case mode
233: when :old
234: s, e = (@start_old + 1), (@end_old + 1)
235: when :new
236: s, e = (@start_new + 1), (@end_new + 1)
237: end
238:
239: (s < e) ? "#{s},#{e}" : "#{e}"
240: end
# File lib/diff/lcs/hunk.rb, line 212
212: def ed_diff(format)
213: op_act = { "+" => 'a', "-" => 'd', "!" => "c" }
214: warn "Expecting only one block in an old diff hunk!" if @blocks.size > 1
215:
216: if format == :reverse_ed
217: s = "#{op_act[@blocks[0].op]}#{context_range(:old)}\n"
218: else
219: s = "#{context_range(:old).gsub(/,/, ' ')}#{op_act[@blocks[0].op]}\n"
220: end
221:
222: unless @blocks[0].insert.empty?
223: @data_new[@start_new .. @end_new].each { |e| s << "#{e}\n" }
224: s << ".\n"
225: end
226: s
227: end
Note that an old diff can’t have any context. Therefore, we know that there’s only one block in the hunk.
# File lib/diff/lcs/hunk.rb, line 125
125: def old_diff
126: warn "Expecting only one block in an old diff hunk!" if @blocks.size > 1
127: op_act = { "+" => 'a', "-" => 'd', "!" => "c" }
128:
129: block = @blocks[0]
130:
131: # Calculate item number range. Old diff range is just like a context
132: # diff range, except the ranges are on one line with the action between
133: # them.
134: s = "#{context_range(:old)}#{op_act[block.op]}#{context_range(:new)}\n"
135: # If removing anything, just print out all the remove lines in the hunk
136: # which is just all the remove lines in the block.
137: @data_old[@start_old .. @end_old].each { |e| s << "< #{e}\n" } unless block.remove.empty?
138: s << "---\n" if block.op == "!"
139: @data_new[@start_new .. @end_new].each { |e| s << "> #{e}\n" } unless block.insert.empty?
140: s
141: end
# File lib/diff/lcs/hunk.rb, line 143
143: def unified_diff
144: # Calculate item number range.
145: s = "@@ -#{unified_range(:old)} +#{unified_range(:new)} @@\n"
146:
147: # Outlist starts containing the hunk of the old file. Removing an item
148: # just means putting a '-' in front of it. Inserting an item requires
149: # getting it from the new file and splicing it in. We splice in
150: # +num_added+ items. Remove blocks use +num_added+ because splicing
151: # changed the length of outlist.
152: #
153: # We remove +num_removed+ items. Insert blocks use +num_removed+
154: # because their item numbers -- corresponding to positions in the NEW
155: # file -- don't take removed items into account.
156: lo, hi, num_added, num_removed = @start_old, @end_old, 0, 0
157:
158: outlist = @data_old[lo .. hi].collect { |e| e.gsub(/^/, ' ') }
159:
160: @blocks.each do |block|
161: block.remove.each do |item|
162: op = item.action.to_s # -
163: offset = item.position - lo + num_added
164: outlist[offset].gsub!(/^ /, op.to_s)
165: num_removed += 1
166: end
167: block.insert.each do |item|
168: op = item.action.to_s # +
169: offset = item.position - @start_new + num_removed
170: outlist[offset, 0] = "#{op}#{@data_new[item.position]}"
171: num_added += 1
172: end
173: end
174:
175: s << outlist.join("\n")
176: end
Generate a range of item numbers to print for unified diff. Print number where block starts, followed by number of lines in the block (don’t print number of lines if it’s 1)
# File lib/diff/lcs/hunk.rb, line 245
245: def unified_range(mode)
246: case mode
247: when :old
248: s, e = (@start_old + 1), (@end_old + 1)
249: when :new
250: s, e = (@start_new + 1), (@end_new + 1)
251: end
252:
253: length = e - s + 1
254: first = (length < 2) ? e : s # "strange, but correct"
255: (length == 1) ? "#{first}" : "#{first},#{length}"
256: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.