diff-lcs 1.3 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'rubygems'
4
4
  require 'rspec'
@@ -11,14 +11,14 @@ Hoe.plugin :gemspec2
11
11
  Hoe.plugin :git
12
12
  Hoe.plugin :travis
13
13
 
14
- spec = Hoe.spec 'diff-lcs' do
14
+ _spec = Hoe.spec 'diff-lcs' do
15
15
  developer('Austin Ziegler', 'halostatue@gmail.com')
16
16
 
17
17
  require_ruby_version '>= 1.8'
18
18
 
19
19
  self.history_file = 'History.md'
20
20
  self.readme_file = 'README.rdoc'
21
- self.licenses = [ 'MIT', 'Artistic-2.0', 'GPL-2.0+' ]
21
+ self.licenses = ['MIT', 'Artistic-2.0', 'GPL-2.0+']
22
22
 
23
23
  extra_dev_deps << ['hoe-doofus', '~> 1.0']
24
24
  extra_dev_deps << ['hoe-gemspec2', '~> 1.1']
@@ -26,32 +26,26 @@ spec = Hoe.spec 'diff-lcs' do
26
26
  extra_dev_deps << ['hoe-rubygems', '~> 1.0']
27
27
  extra_dev_deps << ['hoe-travis', '~> 1.2']
28
28
  extra_dev_deps << ['rspec', '>= 2.0', '< 4']
29
- extra_dev_deps << ['rake', '>= 10.0', '< 12']
29
+ extra_dev_deps << ['rake', '>= 10.0', '< 14']
30
30
  extra_dev_deps << ['rdoc', '>= 0']
31
31
  end
32
32
 
33
- unless Rake::Task.task_defined? :test
34
- task :test => :spec
35
- Rake::Task['travis'].prerequisites.replace(%w(spec))
33
+ require "rspec/core/rake_task"
34
+
35
+ desc "Run all specifications"
36
+ RSpec::Core::RakeTask.new(:spec) do |t|
37
+ rspec_dirs = %w(spec lib)
38
+ t.rspec_opts = []
39
+ t.rspec_opts << "-I#{rspec_dirs.join(":")}" unless rspec_dirs.empty?
36
40
  end
41
+ task :default => :spec
37
42
 
38
43
  if RUBY_VERSION >= '2.0' && RUBY_ENGINE == 'ruby'
39
44
  namespace :spec do
40
- task :coveralls do
41
- if ENV['CI'] or ENV['TRAVIS']
42
- ENV['COVERALLS'] = 'yes'
43
- Rake::Task['spec'].execute
44
- else
45
- Rake::Task['spec:coverage'].execute
46
- end
47
- end
48
-
49
45
  desc "Runs test coverage. Only works Ruby 2.0+ and assumes 'simplecov' is installed."
50
46
  task :coverage do
51
47
  ENV['COVERAGE'] = 'yes'
52
48
  Rake::Task['spec'].execute
53
49
  end
54
50
  end
55
-
56
- # Rake::Task['travis'].prerequisites.replace(%w(spec:coveralls))
57
51
  end
@@ -1 +1,3 @@
1
- Autotest.add_discovery { "rspec2" }
1
+ # frozen_string_literal: true
2
+
3
+ Autotest.add_discovery { 'rspec2' }
@@ -1,4 +1,5 @@
1
- #!ruby -w
1
+ #! /usr/bin/env ruby -w
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'diff/lcs'
4
5
  require 'diff/lcs/htmldiff'
@@ -10,8 +11,8 @@ rescue LoadError
10
11
  end
11
12
 
12
13
  if ARGV.size < 2 or ARGV.size > 3
13
- $stderr.puts "usage: #{File.basename($0)} old new [output.html]"
14
- $stderr.puts " #{File.basename($0)} old new > output.html"
14
+ warn "usage: #{File.basename($0)} old new [output.html]"
15
+ warn " #{File.basename($0)} old new > output.html"
15
16
  exit 127
16
17
  end
17
18
 
@@ -23,10 +24,12 @@ options = { :title => "diff #{ARGV[0]} #{ARGV[1]}" }
23
24
  htmldiff = Diff::LCS::HTMLDiff.new(left, right, options)
24
25
 
25
26
  if ARGV[2]
26
- File.open(ARGV[2], "w") do |f|
27
+ File.open(ARGV[2], 'w') do |f|
27
28
  htmldiff.options[:output] = f
28
29
  htmldiff.run
29
30
  end
30
31
  else
31
32
  htmldiff.run
32
33
  end
34
+
35
+ # vim: ft=ruby
data/bin/ldiff CHANGED
@@ -1,6 +1,9 @@
1
- #!ruby -w
1
+ #! /usr/bin/env ruby -w
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'diff/lcs'
4
5
  require 'diff/lcs/ldiff'
5
6
 
6
7
  exit Diff::LCS::Ldiff.run(ARGV)
8
+
9
+ # vim: ft=ruby
@@ -1,3 +1,3 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'diff/lcs'
@@ -1,24 +1,24 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
3
+ module Diff; end unless defined? Diff # rubocop:disable Style/Documentation
2
4
 
3
- module Diff; end unless defined? Diff
4
5
  # == How Diff Works (by Mark-Jason Dominus)
5
6
  #
6
- # I once read an article written by the authors of +diff+; they said that
7
- # they hard worked very hard on the algorithm until they found the right
8
- # one.
7
+ # I once read an article written by the authors of +diff+; they said that they
8
+ # hard worked very hard on the algorithm until they found the right one.
9
9
  #
10
- # I think what they ended up using (and I hope someone will correct me,
11
- # because I am not very confident about this) was the `longest common
12
- # subsequence' method. In the LCS problem, you have two sequences of items:
10
+ # I think what they ended up using (and I hope someone will correct me, because
11
+ # I am not very confident about this) was the `longest common subsequence'
12
+ # method. In the LCS problem, you have two sequences of items:
13
13
  #
14
14
  # a b c d f g h j q z
15
15
  # a b c d e f g i j k r x y z
16
16
  #
17
17
  # and you want to find the longest sequence of items that is present in both
18
18
  # original sequences in the same order. That is, you want to find a new
19
- # sequence *S* which can be obtained from the first sequence by deleting
20
- # some items, and from the second sequence by deleting other items. You also
21
- # want *S* to be as long as possible. In this case *S* is:
19
+ # sequence *S* which can be obtained from the first sequence by deleting some
20
+ # items, and from the second sequence by deleting other items. You also want
21
+ # *S* to be as long as possible. In this case *S* is:
22
22
  #
23
23
  # a b c d f g j z
24
24
  #
@@ -30,9 +30,9 @@ module Diff; end unless defined? Diff
30
30
  # This module solves the LCS problem. It also includes a canned function to
31
31
  # generate +diff+-like output.
32
32
  #
33
- # It might seem from the example above that the LCS of two sequences is
34
- # always pretty obvious, but that's not always the case, especially when the
35
- # two sequences have many repeated elements. For example, consider
33
+ # It might seem from the example above that the LCS of two sequences is always
34
+ # pretty obvious, but that's not always the case, especially when the two
35
+ # sequences have many repeated elements. For example, consider
36
36
  #
37
37
  # a x b y c z p d q
38
38
  # a b c a x b y c z
@@ -43,29 +43,28 @@ module Diff; end unless defined? Diff
43
43
  # a x b y c z p d q
44
44
  # a b c a b y c z
45
45
  #
46
- # This finds the common subsequence +a b c z+. But actually, the LCS is +a x
47
- # b y c z+:
46
+ # This finds the common subsequence +a b c z+. But actually, the LCS is +a x b
47
+ # y c z+:
48
48
  #
49
49
  # a x b y c z p d q
50
50
  # a b c a x b y c z
51
51
  module Diff::LCS
52
- VERSION = '1.3'
52
+ VERSION = '1.4'
53
53
  end
54
54
 
55
55
  require 'diff/lcs/callbacks'
56
56
  require 'diff/lcs/internals'
57
57
 
58
- module Diff::LCS
58
+ module Diff::LCS # rubocop:disable Style/Documentation
59
59
  # Returns an Array containing the longest common subsequence(s) between
60
- # +self+ and +other+. See Diff::LCS#LCS.
60
+ # +self+ and +other+. See Diff::LCS#lcs.
61
61
  #
62
62
  # lcs = seq1.lcs(seq2)
63
63
  def lcs(other, &block) #:yields self[i] if there are matched subsequences:
64
64
  Diff::LCS.lcs(self, other, &block)
65
65
  end
66
66
 
67
- # Returns the difference set between +self+ and +other+. See
68
- # Diff::LCS#diff.
67
+ # Returns the difference set between +self+ and +other+. See Diff::LCS#diff.
69
68
  def diff(other, callbacks = nil, &block)
70
69
  Diff::LCS.diff(self, other, callbacks, &block)
71
70
  end
@@ -79,29 +78,27 @@ module Diff::LCS
79
78
  # Traverses the discovered longest common subsequences between +self+ and
80
79
  # +other+. See Diff::LCS#traverse_sequences.
81
80
  def traverse_sequences(other, callbacks = nil, &block)
82
- traverse_sequences(self, other, callbacks ||
83
- Diff::LCS.YieldingCallbacks, &block)
81
+ traverse_sequences(self, other, callbacks || Diff::LCS::SequenceCallbacks, &block)
84
82
  end
85
83
 
86
84
  # Traverses the discovered longest common subsequences between +self+ and
87
85
  # +other+ using the alternate, balanced algorithm. See
88
86
  # Diff::LCS#traverse_balanced.
89
87
  def traverse_balanced(other, callbacks = nil, &block)
90
- traverse_balanced(self, other, callbacks ||
91
- Diff::LCS.YieldingCallbacks, &block)
88
+ traverse_balanced(self, other, callbacks || Diff::LCS::BalancedCallbacks, &block)
92
89
  end
93
90
 
94
- # Attempts to patch +self+ with the provided +patchset+. A new sequence
95
- # based on +self+ and the +patchset+ will be created. See Diff::LCS#patch.
96
- # Attempts to autodiscover the direction of the patch.
91
+ # Attempts to patch +self+ with the provided +patchset+. A new sequence based
92
+ # on +self+ and the +patchset+ will be created. See Diff::LCS#patch. Attempts
93
+ # to autodiscover the direction of the patch.
97
94
  def patch(patchset)
98
95
  Diff::LCS.patch(self, patchset)
99
96
  end
100
- alias_method :unpatch, :patch
97
+ alias unpatch patch
101
98
 
102
- # Attempts to patch +self+ with the provided +patchset+. A new sequence
103
- # based on +self+ and the +patchset+ will be created. See Diff::LCS#patch.
104
- # Does no patch direction autodiscovery.
99
+ # Attempts to patch +self+ with the provided +patchset+. A new sequence based
100
+ # on +self+ and the +patchset+ will be created. See Diff::LCS#patch. Does no
101
+ # patch direction autodiscovery.
105
102
  def patch!(patchset)
106
103
  Diff::LCS.patch!(self, patchset)
107
104
  end
@@ -114,8 +111,8 @@ module Diff::LCS
114
111
  end
115
112
 
116
113
  # Attempts to patch +self+ with the provided +patchset+, using #patch!. If
117
- # the sequence this is used on supports #replace, the value of +self+ will
118
- # be replaced. See Diff::LCS#patch. Does no patch direction autodiscovery.
114
+ # the sequence this is used on supports #replace, the value of +self+ will be
115
+ # replaced. See Diff::LCS#patch. Does no patch direction autodiscovery.
119
116
  def patch_me(patchset)
120
117
  if respond_to? :replace
121
118
  replace(patch!(patchset))
@@ -124,10 +121,9 @@ module Diff::LCS
124
121
  end
125
122
  end
126
123
 
127
- # Attempts to unpatch +self+ with the provided +patchset+, using
128
- # #unpatch!. If the sequence this is used on supports #replace, the value
129
- # of +self+ will be replaced. See Diff::LCS#unpatch. Does no patch direction
130
- # autodiscovery.
124
+ # Attempts to unpatch +self+ with the provided +patchset+, using #unpatch!.
125
+ # If the sequence this is used on supports #replace, the value of +self+ will
126
+ # be replaced. See Diff::LCS#unpatch. Does no patch direction autodiscovery.
131
127
  def unpatch_me(patchset)
132
128
  if respond_to? :replace
133
129
  replace(unpatch!(patchset))
@@ -142,29 +138,28 @@ class << Diff::LCS
142
138
  matches = Diff::LCS::Internals.lcs(seq1, seq2)
143
139
  ret = []
144
140
  string = seq1.kind_of? String
145
- matches.each_with_index do |e, i|
146
- unless matches[i].nil?
147
- v = string ? seq1[i, 1] : seq1[i]
148
- v = block[v] if block
149
- ret << v
150
- end
141
+ matches.each_with_index do |_e, i|
142
+ next if matches[i].nil?
143
+
144
+ v = string ? seq1[i, 1] : seq1[i]
145
+ v = block[v] if block
146
+ ret << v
151
147
  end
152
148
  ret
153
149
  end
154
- alias_method :LCS, :lcs
150
+ alias LCS lcs
155
151
 
156
152
  # #diff computes the smallest set of additions and deletions necessary to
157
- # turn the first sequence into the second, and returns a description of
158
- # these changes.
153
+ # turn the first sequence into the second, and returns a description of these
154
+ # changes.
159
155
  #
160
156
  # See Diff::LCS::DiffCallbacks for the default behaviour. An alternate
161
157
  # behaviour may be implemented with Diff::LCS::ContextDiffCallbacks. If a
162
158
  # Class argument is provided for +callbacks+, #diff will attempt to
163
- # initialise it. If the +callbacks+ object (possibly initialised) responds
164
- # to #finish, it will be called.
159
+ # initialise it. If the +callbacks+ object (possibly initialised) responds to
160
+ # #finish, it will be called.
165
161
  def diff(seq1, seq2, callbacks = nil, &block) # :yields diff changes:
166
- diff_traversal(:diff, seq1, seq2, callbacks || Diff::LCS::DiffCallbacks,
167
- &block)
162
+ diff_traversal(:diff, seq1, seq2, callbacks || Diff::LCS::DiffCallbacks, &block)
168
163
  end
169
164
 
170
165
  # #sdiff computes all necessary components to show two sequences and their
@@ -179,18 +174,31 @@ class << Diff::LCS
179
174
  # See Diff::LCS::SDiffCallbacks for the default behaviour. An alternate
180
175
  # behaviour may be implemented with Diff::LCS::ContextDiffCallbacks. If a
181
176
  # Class argument is provided for +callbacks+, #diff will attempt to
182
- # initialise it. If the +callbacks+ object (possibly initialised) responds
183
- # to #finish, it will be called.
177
+ # initialise it. If the +callbacks+ object (possibly initialised) responds to
178
+ # #finish, it will be called.
179
+ #
180
+ # Each element of a returned array is a Diff::LCS::ContextChange object,
181
+ # which can be implicitly converted to an array.
182
+ #
183
+ # Diff::LCS.sdiff(a, b).each do |action, (old_pos, old_element), (new_pos, new_element)|
184
+ # case action
185
+ # when '!'
186
+ # # replace
187
+ # when '-'
188
+ # # delete
189
+ # when '+'
190
+ # # insert
191
+ # end
192
+ # end
184
193
  def sdiff(seq1, seq2, callbacks = nil, &block) #:yields diff changes:
185
- diff_traversal(:sdiff, seq1, seq2, callbacks || Diff::LCS::SDiffCallbacks,
186
- &block)
194
+ diff_traversal(:sdiff, seq1, seq2, callbacks || Diff::LCS::SDiffCallbacks, &block)
187
195
  end
188
196
 
189
- # #traverse_sequences is the most general facility provided by this
190
- # module; #diff and #lcs are implemented as calls to it.
197
+ # #traverse_sequences is the most general facility provided by this module;
198
+ # #diff and #lcs are implemented as calls to it.
191
199
  #
192
- # The arguments to #traverse_sequences are the two sequences to traverse,
193
- # and a callback object, like this:
200
+ # The arguments to #traverse_sequences are the two sequences to traverse, and
201
+ # a callback object, like this:
194
202
  #
195
203
  # traverse_sequences(seq1, seq2, Diff::LCS::ContextDiffCallbacks.new)
196
204
  #
@@ -218,56 +226,55 @@ class << Diff::LCS
218
226
  # ^
219
227
  # b---+
220
228
  #
221
- # If there are two arrows (+a+ and +b+) pointing to elements of sequences
222
- # +A+ and +B+, the arrows will initially point to the first elements of
223
- # their respective sequences. #traverse_sequences will advance the arrows
224
- # through the sequences one element at a time, calling a method on the
225
- # user-specified callback object before each advance. It will advance the
226
- # arrows in such a way that if there are elements <tt>A[i]</tt> and
227
- # <tt>B[j]</tt> which are both equal and part of the longest common
228
- # subsequence, there will be some moment during the execution of
229
- # #traverse_sequences when arrow +a+ is pointing to <tt>A[i]</tt> and
230
- # arrow +b+ is pointing to <tt>B[j]</tt>. When this happens,
231
- # #traverse_sequences will call <tt>callbacks#match</tt> and then it will
232
- # advance both arrows.
233
- #
234
- # Otherwise, one of the arrows is pointing to an element of its sequence
235
- # that is not part of the longest common subsequence. #traverse_sequences
236
- # will advance that arrow and will call <tt>callbacks#discard_a</tt> or
237
- # <tt>callbacks#discard_b</tt>, depending on which arrow it advanced. If
238
- # both arrows point to elements that are not part of the longest common
239
- # subsequence, then #traverse_sequences will advance one of them and call
240
- # the appropriate callback, but it is not specified which it will call.
241
- #
242
- # The methods for <tt>callbacks#match</tt>, <tt>callbacks#discard_a</tt>,
243
- # and <tt>callbacks#discard_b</tt> are invoked with an event comprising
244
- # the action ("=", "+", or "-", respectively), the indicies +i+ and +j+,
245
- # and the elements <tt>A[i]</tt> and <tt>B[j]</tt>. Return values are
246
- # discarded by #traverse_sequences.
229
+ # If there are two arrows (+a+ and +b+) pointing to elements of sequences +A+
230
+ # and +B+, the arrows will initially point to the first elements of their
231
+ # respective sequences. #traverse_sequences will advance the arrows through
232
+ # the sequences one element at a time, calling a method on the user-specified
233
+ # callback object before each advance. It will advance the arrows in such a
234
+ # way that if there are elements <tt>A[i]</tt> and <tt>B[j]</tt> which are
235
+ # both equal and part of the longest common subsequence, there will be some
236
+ # moment during the execution of #traverse_sequences when arrow +a+ is
237
+ # pointing to <tt>A[i]</tt> and arrow +b+ is pointing to <tt>B[j]</tt>. When
238
+ # this happens, #traverse_sequences will call <tt>callbacks#match</tt> and
239
+ # then it will advance both arrows.
240
+ #
241
+ # Otherwise, one of the arrows is pointing to an element of its sequence that
242
+ # is not part of the longest common subsequence. #traverse_sequences will
243
+ # advance that arrow and will call <tt>callbacks#discard_a</tt> or
244
+ # <tt>callbacks#discard_b</tt>, depending on which arrow it advanced. If both
245
+ # arrows point to elements that are not part of the longest common
246
+ # subsequence, then #traverse_sequences will advance one of them and call the
247
+ # appropriate callback, but it is not specified which it will call.
248
+ #
249
+ # The methods for <tt>callbacks#match</tt>, <tt>callbacks#discard_a</tt>, and
250
+ # <tt>callbacks#discard_b</tt> are invoked with an event comprising the
251
+ # action ("=", "+", or "-", respectively), the indicies +i+ and +j+, and the
252
+ # elements <tt>A[i]</tt> and <tt>B[j]</tt>. Return values are discarded by
253
+ # #traverse_sequences.
247
254
  #
248
255
  # === End of Sequences
249
256
  #
250
257
  # If arrow +a+ reaches the end of its sequence before arrow +b+ does,
251
- # #traverse_sequence will try to call <tt>callbacks#finished_a</tt> with
252
- # the last index and element of +A+ (<tt>A[-1]</tt>) and the current index
253
- # and element of +B+ (<tt>B[j]</tt>). If <tt>callbacks#finished_a</tt>
254
- # does not exist, then <tt>callbacks#discard_b</tt> will be called on each
255
- # element of +B+ until the end of the sequence is reached (the call will
256
- # be done with <tt>A[-1]</tt> and <tt>B[j]</tt> for each element).
258
+ # #traverse_sequence will try to call <tt>callbacks#finished_a</tt> with the
259
+ # last index and element of +A+ (<tt>A[-1]</tt>) and the current index and
260
+ # element of +B+ (<tt>B[j]</tt>). If <tt>callbacks#finished_a</tt> does not
261
+ # exist, then <tt>callbacks#discard_b</tt> will be called on each element of
262
+ # +B+ until the end of the sequence is reached (the call will be done with
263
+ # <tt>A[-1]</tt> and <tt>B[j]</tt> for each element).
257
264
  #
258
265
  # If +b+ reaches the end of +B+ before +a+ reaches the end of +A+,
259
266
  # <tt>callbacks#finished_b</tt> will be called with the current index and
260
267
  # element of +A+ (<tt>A[i]</tt>) and the last index and element of +B+
261
- # (<tt>A[-1]</tt>). Again, if <tt>callbacks#finished_b</tt> does not exist
262
- # on the callback object, then <tt>callbacks#discard_a</tt> will be called
263
- # on each element of +A+ until the end of the sequence is reached
264
- # (<tt>A[i]</tt> and <tt>B[-1]</tt>).
268
+ # (<tt>A[-1]</tt>). Again, if <tt>callbacks#finished_b</tt> does not exist on
269
+ # the callback object, then <tt>callbacks#discard_a</tt> will be called on
270
+ # each element of +A+ until the end of the sequence is reached (<tt>A[i]</tt>
271
+ # and <tt>B[-1]</tt>).
265
272
  #
266
273
  # There is a chance that one additional <tt>callbacks#discard_a</tt> or
267
- # <tt>callbacks#discard_b</tt> will be called after the end of the
268
- # sequence is reached, if +a+ has not yet reached the end of +A+ or +b+
269
- # has not yet reached the end of +B+.
270
- def traverse_sequences(seq1, seq2, callbacks = Diff::LCS::SequenceCallbacks, &block) #:yields change events:
274
+ # <tt>callbacks#discard_b</tt> will be called after the end of the sequence
275
+ # is reached, if +a+ has not yet reached the end of +A+ or +b+ has not yet
276
+ # reached the end of +B+.
277
+ def traverse_sequences(seq1, seq2, callbacks = Diff::LCS::SequenceCallbacks) #:yields change events:
271
278
  callbacks ||= Diff::LCS::SequenceCallbacks
272
279
  matches = Diff::LCS::Internals.lcs(seq1, seq2)
273
280
 
@@ -293,6 +300,7 @@ class << Diff::LCS
293
300
  else
294
301
  loop do
295
302
  break unless bj < b_line
303
+
296
304
  bx = string ? seq2[bj, 1] : seq2[bj]
297
305
  event = Diff::LCS::ContextChange.new('+', i, ax, bj, bx)
298
306
  event = yield event if block_given?
@@ -309,12 +317,12 @@ class << Diff::LCS
309
317
  end
310
318
  ai += 1
311
319
 
312
- # The last entry (if any) processed was a match. +ai+ and +bj+ point
313
- # just past the last matching lines in their sequences.
320
+ # The last entry (if any) processed was a match. +ai+ and +bj+ point just
321
+ # past the last matching lines in their sequences.
314
322
  while (ai < a_size) or (bj < b_size)
315
323
  # last A?
316
324
  if ai == a_size and bj < b_size
317
- if callbacks.respond_to?(:finished_a) and not run_finished_a
325
+ if callbacks.respond_to?(:finished_a) and !run_finished_a
318
326
  ax = string ? seq1[-1, 1] : seq1[-1]
319
327
  bx = string ? seq2[bj, 1] : seq2[bj]
320
328
  event = Diff::LCS::ContextChange.new('>', (a_size - 1), ax, bj, bx)
@@ -336,7 +344,7 @@ class << Diff::LCS
336
344
 
337
345
  # last B?
338
346
  if bj == b_size and ai < a_size
339
- if callbacks.respond_to?(:finished_b) and not run_finished_b
347
+ if callbacks.respond_to?(:finished_b) and !run_finished_b
340
348
  ax = string ? seq1[ai, 1] : seq1[ai]
341
349
  bx = string ? seq2[-1, 1] : seq2[-1]
342
350
  event = Diff::LCS::ContextChange.new('<', ai, ax, (b_size - 1), bx)
@@ -365,25 +373,25 @@ class << Diff::LCS
365
373
  ai += 1
366
374
  end
367
375
 
368
- if bj < b_size
369
- ax = string ? seq1[ai, 1] : seq1[ai]
370
- bx = string ? seq2[bj, 1] : seq2[bj]
371
- event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
372
- event = yield event if block_given?
373
- callbacks.discard_b(event)
374
- bj += 1
375
- end
376
+ next unless bj < b_size
377
+
378
+ ax = string ? seq1[ai, 1] : seq1[ai]
379
+ bx = string ? seq2[bj, 1] : seq2[bj]
380
+ event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
381
+ event = yield event if block_given?
382
+ callbacks.discard_b(event)
383
+ bj += 1
376
384
  end
377
385
  end
378
386
 
379
387
  # #traverse_balanced is an alternative to #traverse_sequences. It uses a
380
- # different algorithm to iterate through the entries in the computed
381
- # longest common subsequence. Instead of viewing the changes as insertions
382
- # or deletions from one of the sequences, #traverse_balanced will report
388
+ # different algorithm to iterate through the entries in the computed longest
389
+ # common subsequence. Instead of viewing the changes as insertions or
390
+ # deletions from one of the sequences, #traverse_balanced will report
383
391
  # <em>changes</em> between the sequences.
384
392
  #
385
- # The arguments to #traverse_balanced are the two sequences to traverse
386
- # and a callback object, like this:
393
+ # The arguments to #traverse_balanced are the two sequences to traverse and a
394
+ # callback object, like this:
387
395
  #
388
396
  # traverse_balanced(seq1, seq2, Diff::LCS::ContextDiffCallbacks.new)
389
397
  #
@@ -419,24 +427,23 @@ class << Diff::LCS
419
427
  #
420
428
  # === Matches
421
429
  #
422
- # If there are two arrows (+a+ and +b+) pointing to elements of sequences
423
- # +A+ and +B+, the arrows will initially point to the first elements of
424
- # their respective sequences. #traverse_sequences will advance the arrows
425
- # through the sequences one element at a time, calling a method on the
426
- # user-specified callback object before each advance. It will advance the
427
- # arrows in such a way that if there are elements <tt>A[i]</tt> and
428
- # <tt>B[j]</tt> which are both equal and part of the longest common
429
- # subsequence, there will be some moment during the execution of
430
- # #traverse_sequences when arrow +a+ is pointing to <tt>A[i]</tt> and
431
- # arrow +b+ is pointing to <tt>B[j]</tt>. When this happens,
432
- # #traverse_sequences will call <tt>callbacks#match</tt> and then it will
433
- # advance both arrows.
430
+ # If there are two arrows (+a+ and +b+) pointing to elements of sequences +A+
431
+ # and +B+, the arrows will initially point to the first elements of their
432
+ # respective sequences. #traverse_sequences will advance the arrows through
433
+ # the sequences one element at a time, calling a method on the user-specified
434
+ # callback object before each advance. It will advance the arrows in such a
435
+ # way that if there are elements <tt>A[i]</tt> and <tt>B[j]</tt> which are
436
+ # both equal and part of the longest common subsequence, there will be some
437
+ # moment during the execution of #traverse_sequences when arrow +a+ is
438
+ # pointing to <tt>A[i]</tt> and arrow +b+ is pointing to <tt>B[j]</tt>. When
439
+ # this happens, #traverse_sequences will call <tt>callbacks#match</tt> and
440
+ # then it will advance both arrows.
434
441
  #
435
442
  # === Discards
436
443
  #
437
- # Otherwise, one of the arrows is pointing to an element of its sequence
438
- # that is not part of the longest common subsequence. #traverse_sequences
439
- # will advance that arrow and will call <tt>callbacks#discard_a</tt> or
444
+ # Otherwise, one of the arrows is pointing to an element of its sequence that
445
+ # is not part of the longest common subsequence. #traverse_sequences will
446
+ # advance that arrow and will call <tt>callbacks#discard_a</tt> or
440
447
  # <tt>callbacks#discard_b</tt>, depending on which arrow it advanced.
441
448
  #
442
449
  # === Changes
@@ -450,14 +457,14 @@ class << Diff::LCS
450
457
  #
451
458
  # The methods for <tt>callbacks#match</tt>, <tt>callbacks#discard_a</tt>,
452
459
  # <tt>callbacks#discard_b</tt>, and <tt>callbacks#change</tt> are invoked
453
- # with an event comprising the action ("=", "+", "-", or "!",
454
- # respectively), the indicies +i+ and +j+, and the elements
455
- # <tt>A[i]</tt> and <tt>B[j]</tt>. Return values are discarded by
456
- # #traverse_balanced.
460
+ # with an event comprising the action ("=", "+", "-", or "!", respectively),
461
+ # the indicies +i+ and +j+, and the elements <tt>A[i]</tt> and <tt>B[j]</tt>.
462
+ # Return values are discarded by #traverse_balanced.
457
463
  #
458
464
  # === Context
459
- # Note that +i+ and +j+ may not be the same index position, even if +a+
460
- # and +b+ are considered to be pointing to matching or changed elements.
465
+ #
466
+ # Note that +i+ and +j+ may not be the same index position, even if +a+ and
467
+ # +b+ are considered to be pointing to matching or changed elements.
461
468
  def traverse_balanced(seq1, seq2, callbacks = Diff::LCS::BalancedCallbacks)
462
469
  matches = Diff::LCS::Internals.lcs(seq1, seq2)
463
470
  a_size = seq1.size
@@ -475,6 +482,7 @@ class << Diff::LCS
475
482
  end
476
483
 
477
484
  break if ma >= matches.size # end of matches?
485
+
478
486
  mb = matches[ma]
479
487
 
480
488
  # Change(seq2)
@@ -489,7 +497,6 @@ class << Diff::LCS
489
497
  event = yield event if block_given?
490
498
  callbacks.change(event)
491
499
  ai += 1
492
- bj += 1
493
500
  else
494
501
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
495
502
  event = yield event if block_given?
@@ -499,8 +506,9 @@ class << Diff::LCS
499
506
  event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
500
507
  event = yield event if block_given?
501
508
  callbacks.discard_b(event)
502
- bj += 1
503
509
  end
510
+
511
+ bj += 1
504
512
  when [true, false]
505
513
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
506
514
  event = yield event if block_given?
@@ -535,7 +543,6 @@ class << Diff::LCS
535
543
  event = yield event if block_given?
536
544
  callbacks.change(event)
537
545
  ai += 1
538
- bj += 1
539
546
  else
540
547
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
541
548
  event = yield event if block_given?
@@ -545,8 +552,9 @@ class << Diff::LCS
545
552
  event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
546
553
  event = yield event if block_given?
547
554
  callbacks.discard_b(event)
548
- bj += 1
549
555
  end
556
+
557
+ bj += 1
550
558
  when [true, false]
551
559
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
552
560
  event = yield event if block_given?
@@ -562,9 +570,9 @@ class << Diff::LCS
562
570
  end
563
571
 
564
572
  PATCH_MAP = { #:nodoc:
565
- :patch => { '+' => '+', '-' => '-', '!' => '!', '=' => '=' },
566
- :unpatch => { '+' => '-', '-' => '+', '!' => '!', '=' => '=' }
567
- }
573
+ :patch => { '+' => '+', '-' => '-', '!' => '!', '=' => '=' }.freeze,
574
+ :unpatch => { '+' => '-', '-' => '+', '!' => '!', '=' => '=' }.freeze
575
+ }.freeze
568
576
 
569
577
  # Applies a +patchset+ to the sequence +src+ according to the +direction+
570
578
  # (<tt>:patch</tt> or <tt>:unpatch</tt>), producing a new sequence.
@@ -577,23 +585,23 @@ class << Diff::LCS
577
585
  #
578
586
  # patch(s1, diff(s1, s2)) -> s2
579
587
  #
580
- # A +patchset+ can be considered to apply backward (<tt>:unpatch</tt>) if
581
- # the following expression is true:
588
+ # A +patchset+ can be considered to apply backward (<tt>:unpatch</tt>) if the
589
+ # following expression is true:
582
590
  #
583
591
  # patch(s2, diff(s1, s2)) -> s1
584
592
  #
585
- # If the +patchset+ contains no changes, the +src+ value will be returned
586
- # as either <tt>src.dup</tt> or +src+. A +patchset+ can be deemed as
587
- # having no changes if the following predicate returns true:
593
+ # If the +patchset+ contains no changes, the +src+ value will be returned as
594
+ # either <tt>src.dup</tt> or +src+. A +patchset+ can be deemed as having no
595
+ # changes if the following predicate returns true:
588
596
  #
589
597
  # patchset.empty? or
590
- # patchset.flatten.all? { |change| change.unchanged? }
598
+ # patchset.flatten(1).all? { |change| change.unchanged? }
591
599
  #
592
600
  # === Patchsets
593
601
  #
594
- # A +patchset+ is always an enumerable sequence of changes, hunks of
595
- # changes, or a mix of the two. A hunk of changes is an enumerable
596
- # sequence of changes:
602
+ # A +patchset+ is always an enumerable sequence of changes, hunks of changes,
603
+ # or a mix of the two. A hunk of changes is an enumerable sequence of
604
+ # changes:
597
605
  #
598
606
  # [ # patchset
599
607
  # # change
@@ -602,18 +610,15 @@ class << Diff::LCS
602
610
  # ]
603
611
  # ]
604
612
  #
605
- # The +patch+ method accepts <tt>patchset</tt>s that are enumerable
606
- # sequences containing either Diff::LCS::Change objects (or a subclass) or
607
- # the array representations of those objects. Prior to application, array
613
+ # The +patch+ method accepts <tt>patchset</tt>s that are enumerable sequences
614
+ # containing either Diff::LCS::Change objects (or a subclass) or the array
615
+ # representations of those objects. Prior to application, array
608
616
  # representations of Diff::LCS::Change objects will be reified.
609
617
  def patch(src, patchset, direction = nil)
610
618
  # Normalize the patchset.
611
619
  has_changes, patchset = Diff::LCS::Internals.analyze_patchset(patchset)
612
620
 
613
- if not has_changes
614
- return src.dup if src.respond_to? :dup
615
- return src
616
- end
621
+ return src.respond_to?(:dup) ? src.dup : src unless has_changes
617
622
 
618
623
  string = src.kind_of?(String)
619
624
  # Start with a new empty type of the source's class
@@ -625,7 +630,7 @@ class << Diff::LCS
625
630
 
626
631
  patch_map = PATCH_MAP[direction]
627
632
 
628
- patchset.flatten.each do |change|
633
+ patchset.each do |change|
629
634
  # Both Change and ContextChange support #action
630
635
  action = patch_map[change.action]
631
636
 
@@ -657,8 +662,8 @@ class << Diff::LCS
657
662
  bj += 1
658
663
  end
659
664
 
660
- res << el
661
- bj += 1
665
+ res << el
666
+ bj += 1
662
667
  when '='
663
668
  # This only appears in sdiff output with the SDiff callback.
664
669
  # Therefore, we only need to worry about dealing with a single
@@ -674,10 +679,10 @@ class << Diff::LCS
674
679
  bj += 1
675
680
  end
676
681
 
677
- bj += 1
678
- ai += 1
682
+ bj += 1
683
+ ai += 1
679
684
 
680
- res << el
685
+ res << el
681
686
  end
682
687
  when Diff::LCS::Change
683
688
  case action
@@ -711,15 +716,17 @@ class << Diff::LCS
711
716
  res
712
717
  end
713
718
 
714
- # Given a set of patchset, convert the current version to the prior
715
- # version. Does no auto-discovery.
719
+ # Given a set of patchset, convert the current version to the prior version.
720
+ # Does no auto-discovery.
716
721
  def unpatch!(src, patchset)
717
722
  patch(src, patchset, :unpatch)
718
723
  end
719
724
 
720
- # Given a set of patchset, convert the current version to the next
721
- # version. Does no auto-discovery.
725
+ # Given a set of patchset, convert the current version to the next version.
726
+ # Does no auto-discovery.
722
727
  def patch!(src, patchset)
723
728
  patch(src, patchset, :patch)
724
729
  end
725
730
  end
731
+
732
+ require 'diff/lcs/backports'